From: Consolatis <35009135+Consolatis@users.noreply.github.com> Date: Thu, 10 Mar 2022 05:50:42 +0000 (+0100) Subject: ssd: dynamically adjust resize extents based on usable_area X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=3171aba0e2d1fd58dd4db667ebe74e57f5ee598e;p=proto%2Flabwc.git ssd: dynamically adjust resize extents based on usable_area Fixes #265 --- diff --git a/include/ssd.h b/include/ssd.h index a87df8df..e3feee0a 100644 --- a/include/ssd.h +++ b/include/ssd.h @@ -74,6 +74,8 @@ struct ssd { * don't update things we don't have to. */ struct { + int x; + int y; int width; int height; struct ssd_state_title { @@ -110,6 +112,9 @@ struct ssd_part { /* This part represented in scene graph */ struct wlr_scene_node *node; + /* Targeted geometry. May be NULL */ + struct wlr_box *geometry; + struct wl_list link; }; diff --git a/src/ssd/ssd.c b/src/ssd/ssd.c index 902fd2d7..4c4e5990 100644 --- a/src/ssd/ssd.c +++ b/src/ssd/ssd.c @@ -155,28 +155,35 @@ ssd_create(struct view *view) view->ssd.tree = wlr_scene_tree_create(&view->scene_tree->node); wlr_scene_node_lower_to_bottom(&view->ssd.tree->node); ssd_extents_create(view); - ssd_titlebar_create(view); ssd_border_create(view); + ssd_titlebar_create(view); } void ssd_update_geometry(struct view *view) { - /* TODO: verify we are not called without reason. like in commit handlers */ if (!view->ssd.tree || !view->scene_node) { return; } - if (view->ssd.enabled && !view->ssd.tree->node.state.enabled) { + if (!view->ssd.enabled) { + if (view->ssd.tree->node.state.enabled) { + wlr_scene_node_set_enabled(&view->ssd.tree->node, false); + } + return; + } else if (!view->ssd.tree->node.state.enabled) { wlr_scene_node_set_enabled(&view->ssd.tree->node, true); } - if (!view->ssd.enabled && view->ssd.tree->node.state.enabled) { - wlr_scene_node_set_enabled(&view->ssd.tree->node, false); - } int width = view->w; int height = view->h; if (width == view->ssd.state.width && height == view->ssd.state.height) { + if (view->x != view->ssd.state.x || view->y != view->ssd.state.y) { + /* Dynamically resize extents based on position and usable_area */ + ssd_extents_update(view); + view->ssd.state.x = view->x; + view->ssd.state.y = view->y; + } return; } ssd_extents_update(view); @@ -185,6 +192,8 @@ ssd_update_geometry(struct view *view) view->ssd.state.width = width; view->ssd.state.height = height; + view->ssd.state.x = view->x; + view->ssd.state.y = view->y; } void diff --git a/src/ssd/ssd_extents.c b/src/ssd/ssd_extents.c index 85f6e7ff..28e19934 100644 --- a/src/ssd/ssd_extents.c +++ b/src/ssd/ssd_extents.c @@ -5,20 +5,40 @@ #include "theme.h" #include "common/scene-helpers.h" +static struct ssd_part * +add_extent(struct wl_list *part_list, enum ssd_part_type type, + struct wlr_scene_node *parent) +{ + float invisible[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + struct ssd_part *part = add_scene_part(part_list, type); + /* + * Extents need additional geometry to enable dynamic + * resize based on position and output->usable_area. + * + * part->geometry will get free'd automatically in ssd_destroy_parts(). + */ + part->node = &wlr_scene_rect_create(parent, 0, 0, invisible)->node; + part->geometry = calloc(1, sizeof(struct wlr_box)); + return part; +} + +static void +lab_wlr_output_layout_layout_coords(struct wlr_output_layout *layout, + struct wlr_output *output, int *x, int *y) +{ + struct wlr_output_layout_output *l_output; + l_output = wlr_output_layout_get(layout, output); + *x += l_output->x; + *y += l_output->y; +} + void ssd_extents_create(struct view *view) { struct theme *theme = view->server->theme; - float invisible[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; struct wl_list *part_list = &view->ssd.extents.parts; - int width = view->w; - int height = view->h; - int full_height = height + theme->border_width * 2 + theme->title_height; - int full_width = width + theme->border_width * 2; int extended_area = EXTENDED_AREA; int corner_size = extended_area + theme->border_width + BUTTON_WIDTH / 2; - int side_width = full_width + extended_area * 2 - corner_size * 2; - int side_height = full_height + extended_area * 2 - corner_size * 2; view->ssd.extents.tree = wlr_scene_tree_create(&view->ssd.tree->node); struct wlr_scene_node *parent = &view->ssd.extents.tree->node; @@ -29,35 +49,43 @@ ssd_extents_create(struct view *view) wlr_scene_node_set_position(parent, -(theme->border_width + extended_area), -(theme->title_height + theme->border_width + extended_area)); + /* Initialize parts and set constant values for targeted geometry */ + struct ssd_part *p; + /* Top */ - add_scene_rect(part_list, LAB_SSD_PART_CORNER_TOP_LEFT, parent, - corner_size, corner_size, - 0, 0, invisible); - add_scene_rect(part_list, LAB_SSD_PART_TOP, parent, - side_width, extended_area, - corner_size, 0, invisible); - add_scene_rect(part_list, LAB_SSD_PART_CORNER_TOP_RIGHT, parent, - corner_size, corner_size, - corner_size + side_width, 0, invisible); + p = add_extent(part_list, LAB_SSD_PART_CORNER_TOP_LEFT, parent); + p->geometry->width = corner_size; + p->geometry->height = corner_size; + + p = add_extent(part_list, LAB_SSD_PART_TOP, parent); + p->geometry->x = corner_size; + p->geometry->height = extended_area; + + p = add_extent(part_list, LAB_SSD_PART_CORNER_TOP_RIGHT, parent); + p->geometry->width = corner_size; + p->geometry->height = corner_size; /* Sides */ - add_scene_rect(part_list, LAB_SSD_PART_LEFT, parent, - extended_area, side_height, - 0, corner_size, invisible); - add_scene_rect(part_list, LAB_SSD_PART_RIGHT, parent, - extended_area, side_height, - corner_size + side_width, corner_size, invisible); + p = add_extent(part_list, LAB_SSD_PART_LEFT, parent); + p->geometry->y = corner_size; + p->geometry->width = extended_area; + + p = add_extent(part_list, LAB_SSD_PART_RIGHT, parent); + p->geometry->y = corner_size; + p->geometry->width = extended_area; /* Bottom */ - add_scene_rect(part_list, LAB_SSD_PART_CORNER_BOTTOM_LEFT, parent, - corner_size, corner_size, - 0, corner_size + side_height, invisible); - add_scene_rect(part_list, LAB_SSD_PART_BOTTOM, parent, - side_width, extended_area, - corner_size, extended_area + full_height, invisible); - add_scene_rect(part_list, LAB_SSD_PART_CORNER_BOTTOM_RIGHT, parent, - corner_size, corner_size, - corner_size + side_width, corner_size + side_height, invisible); + p = add_extent(part_list, LAB_SSD_PART_CORNER_BOTTOM_LEFT, parent); + p->geometry->width = corner_size; + p->geometry->height = corner_size; + + p = add_extent(part_list, LAB_SSD_PART_BOTTOM, parent); + p->geometry->x = corner_size; + p->geometry->height = extended_area; + + p = add_extent(part_list, LAB_SSD_PART_CORNER_BOTTOM_RIGHT, parent); + p->geometry->width = corner_size; + p->geometry->height = corner_size; } void @@ -71,6 +99,10 @@ ssd_extents_update(struct view *view) wlr_scene_node_set_enabled(&view->ssd.extents.tree->node, true); } + if (!view->output) { + return; + } + struct theme *theme = view->server->theme; int width = view->w; @@ -82,42 +114,87 @@ ssd_extents_update(struct view *view) int side_width = full_width + extended_area * 2 - corner_size * 2; int side_height = full_height + extended_area * 2 - corner_size * 2; + struct wlr_box part_box; + struct wlr_box result_box; struct ssd_part *part; struct wlr_scene_rect *rect; + + /* Convert usable area into layout coordinates */ + struct wlr_box usable_area; + memcpy(&usable_area, &view->output->usable_area, sizeof(struct wlr_box)); + lab_wlr_output_layout_layout_coords(view->server->output_layout, + view->output->wlr_output, &usable_area.x, &usable_area.y); + + /* Remember base layout coordinates */ + int base_x, base_y; + wlr_scene_node_coords(&view->ssd.extents.tree->node, &base_x, &base_y); + + struct wlr_box *target; wl_list_for_each(part, &view->ssd.extents.parts, link) { rect = lab_wlr_scene_get_rect(part->node); + target = part->geometry; switch (part->type) { case LAB_SSD_PART_TOP: - wlr_scene_rect_set_size(rect, side_width, extended_area); - continue; + target->width = side_width; + break; case LAB_SSD_PART_CORNER_TOP_RIGHT: - wlr_scene_node_set_position( - part->node, corner_size + side_width, 0); - continue; + target->x = corner_size + side_width; + break; case LAB_SSD_PART_LEFT: - wlr_scene_rect_set_size(rect, extended_area, side_height); - continue; + target->height = side_height; + break; case LAB_SSD_PART_RIGHT: - wlr_scene_rect_set_size(rect, extended_area, side_height); - wlr_scene_node_set_position( - part->node, extended_area + full_width, corner_size); - continue; + target->x = extended_area + full_width; + target->height = side_height; + break; case LAB_SSD_PART_CORNER_BOTTOM_LEFT: - wlr_scene_node_set_position( - part->node, 0, corner_size + side_height); - continue; + target->y = corner_size + side_height; + break; case LAB_SSD_PART_BOTTOM: - wlr_scene_rect_set_size(rect, side_width, extended_area); - wlr_scene_node_set_position( - part->node, corner_size, extended_area + full_height); - continue; + target->width = side_width; + target->y = extended_area + full_height; + break; case LAB_SSD_PART_CORNER_BOTTOM_RIGHT: - wlr_scene_node_set_position(part->node, - corner_size + side_width, corner_size + side_height); - continue; + target->x = corner_size + side_width; + target->y = corner_size + side_height; + break; default: + break; + } + + /* Get layout geometry of what the part *should* be */ + part_box.x = base_x + target->x; + part_box.y = base_y + target->y; + part_box.width = target->width; + part_box.height = target->height; + + /* Constrain part to output->usable_area */ + if (!wlr_box_intersection(&result_box, &part_box, &usable_area)) { + /* Not visible */ + wlr_scene_node_set_enabled(part->node, false); + continue; + } else if (!part->node->state.enabled) { + wlr_scene_node_set_enabled(part->node, true); + } + + if (part_box.width != result_box.width + || part_box.height != result_box.height) { + /* Partly visible */ + wlr_scene_rect_set_size(rect, result_box.width, result_box.height); + wlr_scene_node_set_position(part->node, + target->x + (result_box.x - part_box.x), + target->y + (result_box.y - part_box.y)); continue; } + + /* Fully visible */ + if (target->x != part->node->state.x + || target->y != part->node->state.y) { + wlr_scene_node_set_position(part->node, target->x, target->y); + } + if (target->width != rect->width || target->height != rect->height) { + wlr_scene_rect_set_size(rect, target->width, target->height); + } } } diff --git a/src/ssd/ssd_part.c b/src/ssd/ssd_part.c index 95eac508..ec754697 100644 --- a/src/ssd/ssd_part.c +++ b/src/ssd/ssd_part.c @@ -66,8 +66,8 @@ finish_scene_button(struct wl_list *part_list, enum ssd_part_type type, /* Hover overlay */ struct ssd_part *hover_part; - hover_part = add_scene_rect(part_list, type, parent, - BUTTON_WIDTH, rc.theme->title_height, offset_x, offset_y, hover_bg); + hover_part = add_scene_rect(part_list, type, parent, BUTTON_WIDTH, + rc.theme->title_height, offset_x, offset_y, hover_bg); wlr_scene_node_set_enabled(hover_part->node, false); } @@ -77,7 +77,10 @@ add_scene_button_corner(struct wl_list *part_list, enum ssd_part_type type, struct wlr_buffer *icon_buffer, int x) { struct ssd_part *part; - /* Background, y adjusted for border_width */ + /* + * Background, y adjusted for border_width which is + * already included in rendered theme.c / corner_buffer + */ part = add_scene_buffer(part_list, type, parent, corner_buffer, x, -rc.theme->border_width); finish_scene_button(part_list, type, part->node, icon_buffer); @@ -116,9 +119,15 @@ ssd_destroy_parts(struct wl_list *list) wl_list_for_each_reverse_safe(part, tmp, list, link) { if (part->node) { wlr_scene_node_destroy(part->node); + part->node = NULL; } if (part->buffer) { wlr_buffer_drop(&part->buffer->base); + part->buffer = NULL; + } + if (part->geometry) { + free(part->geometry); + part->geometry = NULL; } wl_list_remove(&part->link); free(part); diff --git a/src/view.c b/src/view.c index 4d661e04..91c9aadc 100644 --- a/src/view.c +++ b/src/view.c @@ -35,6 +35,7 @@ view_move(struct view *view, double x, double y) } view_discover_output(view); wlr_scene_node_set_position(&view->scene_tree->node, view->x, view->y); + ssd_update_geometry(view); } /* N.B. Use view_move() if not resizing. */