[Bf-blender-cvs] [758361556b5] master: Fix invalid region rectangles, sanitize dynamic region size calulations

Julian Eisel noreply at git.blender.org
Wed Jan 15 15:07:16 CET 2020


Commit: 758361556b5b9afff506e4247345b739c0f8170c
Author: Julian Eisel
Date:   Wed Jan 15 13:03:51 2020 +0100
Branches: master
https://developer.blender.org/rB758361556b5b9afff506e4247345b739c0f8170c

Fix invalid region rectangles, sanitize dynamic region size calulations

It was too easy to end up with invalid region rectangles and we were
badly protected against them, so that they were hard to catch.
In fact we still create a main region for the top-bar, which ended up
getting a region height of -1. While this doesn't seem to have caused
issues in practice, we should prevent them entirely.

So idea was that at the end of region layout resolving,
`BLI_rcti_is_valid()` should return `true` for the region rectangle.
Further changes here ensure this is true: The `RGN_FLAG_TOO_SMALL` flag
is now set whenever there is not enough space for a region or if it
would get a size of zero or less.

Note: Should the assert fail, please do not just disable it and try to
actually address the root of the issue.

===================================================================

M	source/blender/editors/screen/area.c
M	source/blender/windowmanager/intern/wm_draw.c

===================================================================

diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 3c5400bd021..a4318db0cb5 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -1244,6 +1244,20 @@ static void region_rect_recursive(
     alignment = RGN_ALIGN_NONE;
   }
 
+  /* If both the ARegion.sizex/y and the prefsize are 0, the region is tagged as too small, even
+   * before the layout for dynamic regions is created. #wm_draw_window_offscreen() allows the
+   * layout to be created despite the RGN_FLAG_TOO_SMALL flag being set. But there may still be
+   * regions that don't have a separate ARegionType.layout callback. For those, set a default
+   * prefsize so they can become visible. */
+  if ((ar->flag & RGN_FLAG_DYNAMIC_SIZE) && !(ar->type->layout)) {
+    if ((ar->sizex == 0) && (ar->type->prefsizex == 0)) {
+      ar->type->prefsizex = AREAMINX;
+    }
+    if ((ar->sizey == 0) && (ar->type->prefsizey == 0)) {
+      ar->type->prefsizey = HEADERY;
+    }
+  }
+
   /* prefsize, taking into account DPI */
   int prefsizex = UI_DPI_FAC * ((ar->sizex > 1) ? ar->sizex + 0.5f : ar->type->prefsizex);
   int prefsizey;
@@ -1323,7 +1337,7 @@ static void region_rect_recursive(
   else if (alignment == RGN_ALIGN_TOP || alignment == RGN_ALIGN_BOTTOM) {
     rcti *winrct = (ar->overlap) ? overlap_remainder : remainder;
 
-    if (rct_fits(winrct, 'v', prefsizey) < 0) {
+    if ((prefsizey == 0) || (rct_fits(winrct, 'v', prefsizey) < 0)) {
       ar->flag |= RGN_FLAG_TOO_SMALL;
     }
     else {
@@ -1348,7 +1362,7 @@ static void region_rect_recursive(
   else if (ELEM(alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
     rcti *winrct = (ar->overlap) ? overlap_remainder : remainder;
 
-    if (rct_fits(winrct, 'h', prefsizex) < 0) {
+    if ((prefsizex == 0) || (rct_fits(winrct, 'h', prefsizex) < 0)) {
       ar->flag |= RGN_FLAG_TOO_SMALL;
     }
     else {
@@ -1478,9 +1492,12 @@ static void region_rect_recursive(
         ar->winrct.xmin = ar->winrct.xmax;
         break;
       case RGN_ALIGN_LEFT:
+        ar->winrct.xmax = ar->winrct.xmin;
+        break;
       default:
         /* prevent winrct to be valid */
         ar->winrct.xmax = ar->winrct.xmin;
+        BLI_rcti_sanitize(&ar->winrct);
         break;
     }
   }
@@ -1500,6 +1517,8 @@ static void region_rect_recursive(
     *overlap_remainder = *remainder;
   }
 
+  BLI_assert(BLI_rcti_is_valid(&ar->winrct));
+
   region_rect_recursive(sa, ar->next, remainder, overlap_remainder, quad);
 
   /* Tag for redraw if size changes. */
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 09b7d89fc2b..14d4e05b77a 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -581,7 +581,14 @@ static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo)
 
     /* Compute UI layouts for dynamically size regions. */
     for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
-      if (ar->visible && ar->do_draw && ar->type && ar->type->layout) {
+      /* Dynamic region may have been flagged as too small because their size on init is 0.
+       * ARegion.visible is false then, as expected. The layout should still be created then, so
+       * the region size can be updated (it may turn out to be not too small then). */
+      const bool ignore_visibility = (ar->flag & RGN_FLAG_DYNAMIC_SIZE) &&
+                                     (ar->flag & RGN_FLAG_TOO_SMALL) &&
+                                     !(ar->flag & RGN_FLAG_HIDDEN);
+
+      if ((ar->visible || ignore_visibility) && ar->do_draw && ar->type && ar->type->layout) {
         CTX_wm_region_set(C, ar);
         ED_region_do_layout(C, ar);
         CTX_wm_region_set(C, NULL);



More information about the Bf-blender-cvs mailing list