Fix missing redraws of affected regions with dynamically sized regions

Regions that change their size in the layout phase (something that is
supported for a while now) might affect the size of following regions.
For example the asset shelf design forsees that it takes space away from
the tool- and sidebar. When its size changes, tool- and sidebar need to
redraw.

Without this there is a crash in the `asset-shelf` branch:
- Open sidebar
- In the asset shelf Display Settings popover, toggle "Names" twice.

At first the sidebar will be empty, when toggling the second time a
null-dereference will cause a crash. This is because the layout phase of
the sidebar does not run, but after that the region size is updated,
it's tagged for redraw and the draw phase runs (without any layout).

Pull Request: https://projects.blender.org/blender/blender/pulls/110212
This commit is contained in:
Julian Eisel 2023-07-25 12:07:53 +02:00 committed by Julian Eisel
parent aefc9835f8
commit 4137f9a87f
3 changed files with 40 additions and 4 deletions

View File

@ -212,6 +212,11 @@ void ED_area_tag_redraw(ScrArea *area);
void ED_area_tag_redraw_no_rebuild(ScrArea *area);
void ED_area_tag_redraw_regiontype(ScrArea *area, int type);
void ED_area_tag_refresh(ScrArea *area);
/**
* For regions that change the region size in their #ARegionType.layout() callback: Mark the area
* as having a changed region size, requiring refitting of regions within the area.
*/
void ED_area_tag_region_size_update(ScrArea *area, ARegion *changed_region);
/**
* Only exported for WM.
*/

View File

@ -325,12 +325,12 @@ void ED_area_type_hud_ensure(bContext *C, ScrArea *area)
/* Let 'ED_area_update_region_sizes' do the work of placing the region.
* Otherwise we could set the 'region->winrct' & 'region->winx/winy' here. */
if (init) {
area->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
ED_area_tag_region_size_update(area, region);
}
else {
if (region->flag & RGN_FLAG_HIDDEN) {
/* Also forces recalculating HUD size in hud_region_layout(). */
area->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
ED_area_tag_region_size_update(area, region);
}
region->flag &= ~RGN_FLAG_HIDDEN;
}

View File

@ -752,6 +752,37 @@ void ED_area_tag_refresh(ScrArea *area)
}
}
void ED_area_tag_region_size_update(ScrArea *area, ARegion *changed_region)
{
if (!area || (area->flag & AREA_FLAG_REGION_SIZE_UPDATE)) {
return;
}
area->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
/* Floating regions don't affect other regions, so the following can be skipped. */
if (changed_region->alignment == RGN_ALIGN_FLOAT) {
return;
}
/* Tag the following regions for redraw, since the size change of this region may affect the
* available space for them. */
for (ARegion *following_region = changed_region->next; following_region;
following_region = following_region->next)
{
/* Overlapping and non-overlapping regions don't affect each others space. So layout changes
* of one don't require redrawing the other. */
if (changed_region->overlap != following_region->overlap) {
continue;
}
/* Floating regions don't affect space of other regions. */
if (following_region->alignment == RGN_ALIGN_FLOAT) {
continue;
}
ED_region_tag_redraw(following_region);
}
}
/* *************************************************************** */
const char *ED_area_region_search_filter_get(const ScrArea *area, const ARegion *region)
@ -3111,7 +3142,7 @@ void ED_region_panels_layout_ex(const bContext *C,
if ((region->sizex != size_dyn[0]) || (region->sizey != size_dyn[1])) {
region->sizex = size_dyn[0];
region->sizey = size_dyn[1];
area->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
ED_area_tag_region_size_update(area, region);
}
y = fabsf(region->sizey * UI_SCALE_FAC - 1);
}
@ -3432,7 +3463,7 @@ void ED_region_header_layout(const bContext *C, ARegion *region)
ScrArea *area = CTX_wm_area(C);
region->sizex = new_sizex;
area->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
ED_area_tag_region_size_update(area, region);
}
UI_block_end(C, block);