aboutsummaryrefslogtreecommitdiff
path: root/sway/tree/container.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/tree/container.c')
-rw-r--r--sway/tree/container.c267
1 files changed, 195 insertions, 72 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c
index feaf7647..76a21c19 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -452,80 +452,139 @@ struct sway_container *container_parent(struct sway_container *container,
return container;
}
-struct sway_container *container_at(struct sway_container *parent,
- double lx, double ly,
+static struct sway_container *container_at_view(struct sway_container *swayc,
+ double ox, double oy,
struct wlr_surface **surface, double *sx, double *sy) {
- list_t *queue = get_bfs_queue();
- if (!queue) {
+ struct sway_view *sview = swayc->sway_view;
+ double view_sx = ox - sview->x;
+ double view_sy = oy - sview->y;
+
+ double _sx, _sy;
+ struct wlr_surface *_surface = NULL;
+ switch (sview->type) {
+ case SWAY_VIEW_XWAYLAND:
+ _surface = wlr_surface_surface_at(sview->surface,
+ view_sx, view_sy, &_sx, &_sy);
+ break;
+ case SWAY_VIEW_XDG_SHELL_V6:
+ // the top left corner of the sway container is the
+ // coordinate of the top left corner of the window geometry
+ view_sx += sview->wlr_xdg_surface_v6->geometry.x;
+ view_sy += sview->wlr_xdg_surface_v6->geometry.y;
+
+ _surface = wlr_xdg_surface_v6_surface_at(
+ sview->wlr_xdg_surface_v6,
+ view_sx, view_sy, &_sx, &_sy);
+ break;
+ case SWAY_VIEW_XDG_SHELL:
+ // the top left corner of the sway container is the
+ // coordinate of the top left corner of the window geometry
+ view_sx += sview->wlr_xdg_surface->geometry.x;
+ view_sy += sview->wlr_xdg_surface->geometry.y;
+
+ _surface = wlr_xdg_surface_surface_at(
+ sview->wlr_xdg_surface,
+ view_sx, view_sy, &_sx, &_sy);
+ break;
+ }
+ if (_surface) {
+ *sx = _sx;
+ *sy = _sy;
+ *surface = _surface;
+ }
+ return swayc;
+}
+
+/**
+ * container_at for a container with layout L_TABBED.
+ */
+static struct sway_container *container_at_tabbed(struct sway_container *parent,
+ double ox, double oy,
+ struct wlr_surface **surface, double *sx, double *sy) {
+ if (oy < parent->y || oy > parent->y + parent->height) {
return NULL;
}
+ struct sway_seat *seat = input_manager_current_seat(input_manager);
- list_add(queue, parent);
+ // Tab titles
+ int title_height = config->border_thickness * 2 + config->font_height;
+ if (oy < parent->y + title_height) {
+ int tab_width = parent->width / parent->children->length;
+ int child_index = (ox - parent->x) / tab_width;
+ if (child_index >= parent->children->length) {
+ child_index = parent->children->length - 1;
+ }
+ struct sway_container *child = parent->children->items[child_index];
+ return seat_get_focus_inactive(seat, child);
+ }
- struct sway_container *swayc = NULL;
- while (queue->length) {
- swayc = queue->items[0];
- list_del(queue, 0);
- if (swayc->type == C_VIEW) {
- struct sway_view *sview = swayc->sway_view;
- struct sway_container *soutput = container_parent(swayc, C_OUTPUT);
- struct wlr_box *output_box =
- wlr_output_layout_get_box(
- root_container.sway_root->output_layout,
- soutput->sway_output->wlr_output);
- double ox = lx - output_box->x;
- double oy = ly - output_box->y;
- double view_sx = ox - sview->x;
- double view_sy = oy - sview->y;
-
- double _sx, _sy;
- struct wlr_surface *_surface;
- switch (sview->type) {
- case SWAY_VIEW_XWAYLAND:
- _surface = wlr_surface_surface_at(sview->surface,
- view_sx, view_sy, &_sx, &_sy);
- break;
- case SWAY_VIEW_XDG_SHELL_V6:
- // the top left corner of the sway container is the
- // coordinate of the top left corner of the window geometry
- view_sx += sview->wlr_xdg_surface_v6->geometry.x;
- view_sy += sview->wlr_xdg_surface_v6->geometry.y;
-
- _surface = wlr_xdg_surface_v6_surface_at(
- sview->wlr_xdg_surface_v6,
- view_sx, view_sy, &_sx, &_sy);
- break;
- case SWAY_VIEW_XDG_SHELL:
- // the top left corner of the sway container is the
- // coordinate of the top left corner of the window geometry
- view_sx += sview->wlr_xdg_surface->geometry.x;
- view_sy += sview->wlr_xdg_surface->geometry.y;
-
- _surface = wlr_xdg_surface_surface_at(
- sview->wlr_xdg_surface,
- view_sx, view_sy, &_sx, &_sy);
- break;
- }
- if (_surface) {
- *sx = _sx;
- *sy = _sy;
- *surface = _surface;
- return swayc;
- }
- // Check the view's decorations
- struct wlr_box swayc_box = {
- .x = swayc->x,
- .y = swayc->y,
- .width = swayc->width,
- .height = swayc->height,
- };
- if (wlr_box_contains_point(&swayc_box, ox, oy)) {
- return swayc;
- }
- } else {
- list_cat(queue, swayc->children);
+ // Surfaces
+ struct sway_container *current = seat_get_focus_inactive(seat, parent);
+ while (current->parent != parent) {
+ current = current->parent;
+ }
+
+ return container_at(current, ox, oy, surface, sx, sy);
+}
+
+/**
+ * container_at for a container with layout L_STACKED.
+ */
+static struct sway_container *container_at_stacked(
+ struct sway_container *parent, double ox, double oy,
+ struct wlr_surface **surface, double *sx, double *sy) {
+ // TODO
+ return NULL;
+}
+
+/**
+ * container_at for a container with layout L_HORIZ or L_VERT.
+ */
+static struct sway_container *container_at_linear(struct sway_container *parent,
+ double ox, double oy,
+ struct wlr_surface **surface, double *sx, double *sy) {
+ for (int i = 0; i < parent->children->length; ++i) {
+ struct sway_container *child = parent->children->items[i];
+ struct wlr_box box = {
+ .x = child->x,
+ .y = child->y,
+ .width = child->width,
+ .height = child->height,
+ };
+ if (wlr_box_contains_point(&box, ox, oy)) {
+ return container_at(child, ox, oy, surface, sx, sy);
}
}
+ return NULL;
+}
+
+struct sway_container *container_at(struct sway_container *parent,
+ double ox, double oy,
+ 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, ox, oy, surface, sx, sy);
+ }
+ if (!parent->children->length) {
+ return NULL;
+ }
+
+ switch (parent->layout) {
+ case L_HORIZ:
+ case L_VERT:
+ return container_at_linear(parent, ox, oy, surface, sx, sy);
+ case L_TABBED:
+ return container_at_tabbed(parent, ox, oy, surface, sx, sy);
+ case L_STACKED:
+ return container_at_stacked(parent, ox, oy, surface, sx, sy);
+ case L_FLOATING:
+ return NULL; // TODO
+ case L_NONE:
+ return NULL;
+ }
return NULL;
}
@@ -699,18 +758,82 @@ void container_calculate_title_height(struct sway_container *container) {
container->title_height = height;
}
+/**
+ * Calculate and return the length of the concatenated child titles.
+ * An example concatenated title is: V[Terminal, Firefox]
+ * If buffer is not NULL, also populate the buffer with the concatenated title.
+ */
+static size_t concatenate_child_titles(struct sway_container *parent,
+ char *buffer) {
+ size_t len = 2; // V[
+ if (buffer) {
+ switch (parent->layout) {
+ case L_VERT:
+ strcpy(buffer, "V[");
+ break;
+ case L_HORIZ:
+ strcpy(buffer, "H[");
+ break;
+ case L_TABBED:
+ strcpy(buffer, "T[");
+ break;
+ case L_STACKED:
+ strcpy(buffer, "S[");
+ break;
+ case L_FLOATING:
+ strcpy(buffer, "F[");
+ break;
+ case L_NONE:
+ strcpy(buffer, "?[");
+ break;
+ }
+ }
+
+ for (int i = 0; i < parent->children->length; ++i) {
+ if (i != 0) {
+ len += 2;
+ if (buffer) {
+ strcat(buffer, ", ");
+ }
+ }
+ struct sway_container *child = parent->children->items[i];
+ if (child->name) {
+ len += strlen(child->name);
+ if (buffer) {
+ strcat(buffer, child->name);
+ }
+ } else {
+ len += 6;
+ if (buffer) {
+ strcat(buffer, "(null)");
+ }
+ }
+ }
+
+ len += 1;
+ if (buffer) {
+ strcat(buffer, "]");
+ }
+ return len;
+}
+
void container_notify_child_title_changed(struct sway_container *container) {
if (!container || container->type != C_CONTAINER) {
return;
}
- if (container->layout != L_TABBED && container->layout != L_STACKED) {
- return;
- }
if (container->formatted_title) {
free(container->formatted_title);
}
- // TODO: iterate children and concatenate their titles
- container->formatted_title = strdup("");
+
+ size_t len = concatenate_child_titles(container, NULL);
+ char *buffer = calloc(len + 1, sizeof(char));
+ if (!sway_assert(buffer, "Unable to allocate title string")) {
+ return;
+ }
+ concatenate_child_titles(container, buffer);
+
+ container->name = buffer;
+ container->formatted_title = buffer;
container_calculate_title_height(container);
container_update_title_textures(container);
container_notify_child_title_changed(container->parent);