Fix wrong usages of region align enumerations
authorJulian Eisel <eiseljulian@gmail.com>
Thu, 16 Jan 2020 14:55:49 +0000 (15:55 +0100)
committerJulian Eisel <eiseljulian@gmail.com>
Thu, 16 Jan 2020 15:13:15 +0000 (16:13 +0100)
`ARegion.alignment` unfortunately is a mixture of value and bitflag
enumerations. When checking for left/right/top/bottom region alignment,
the flags have to be masked out usually.
Most of the fixed cases here probably didn't cause issues in practice,
but could in fact break at any point when surrounding logic changes.

In fact the assert in #region_visible_rect_calc() failed in an older
file from https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=949035. This
fixes it.

12 files changed:
source/blender/editors/interface/interface_align.c
source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/interface_layout.c
source/blender/editors/interface/interface_panel.c
source/blender/editors/interface/interface_region_menu_popup.c
source/blender/editors/interface/interface_region_popover.c
source/blender/editors/screen/area.c
source/blender/editors/screen/area_query.c
source/blender/editors/screen/screen_ops.c
source/blender/editors/space_statusbar/space_statusbar.c
source/blender/editors/space_topbar/space_topbar.c
source/blender/windowmanager/intern/wm_draw.c

index cc68e303e4ab2e2cdbb666c6d4b64596dbfe4168..c058fefb4fa5ed99172a74c2aed1a885b8c3733f 100644 (file)
@@ -124,7 +124,7 @@ bool ui_but_can_align(const uiBut *but)
 
 int ui_but_align_opposite_to_area_align_get(const ARegion *ar)
 {
-  switch (ar->alignment) {
+  switch (RGN_ALIGN_ENUM_FROM_MASK(ar->alignment)) {
     case RGN_ALIGN_TOP:
       return UI_BUT_ALIGN_DOWN;
     case RGN_ALIGN_BOTTOM:
index 05d5f03a363bf8107836d1c6724e65c2aee3a76d..1699668169588e809970a7e9cc00002f0ba365ec 100644 (file)
@@ -1886,11 +1886,13 @@ static bool ui_but_drag_init(bContext *C,
                RGN_TYPE_HEADER,
                RGN_TYPE_TOOL_HEADER,
                RGN_TYPE_FOOTER)) {
+        const int ar_alignment = RGN_ALIGN_ENUM_FROM_MASK(data->region->alignment);
         int lock_axis = -1;
-        if (ELEM(data->region->alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
+
+        if (ELEM(ar_alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
           lock_axis = 0;
         }
-        else if (ELEM(data->region->alignment, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
+        else if (ELEM(ar_alignment, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
           lock_axis = 1;
         }
         if (lock_axis != -1) {
index 68cd450a451f6212507c82f5d85273e6145661ab..179fe84264f9f9869af7b0dde1c1758ae56e600a 100644 (file)
@@ -1241,17 +1241,19 @@ static void ui_item_menu_hold(struct bContext *C, ARegion *butregion, uiBut *but
 
   char direction = UI_DIR_DOWN;
   if (!but->drawstr[0]) {
-    if (butregion->alignment == RGN_ALIGN_LEFT) {
-      direction = UI_DIR_RIGHT;
-    }
-    else if (butregion->alignment == RGN_ALIGN_RIGHT) {
-      direction = UI_DIR_LEFT;
-    }
-    else if (butregion->alignment == RGN_ALIGN_BOTTOM) {
-      direction = UI_DIR_UP;
-    }
-    else {
-      direction = UI_DIR_DOWN;
+    switch (RGN_ALIGN_ENUM_FROM_MASK(butregion->alignment)) {
+      case RGN_ALIGN_LEFT:
+        direction = UI_DIR_RIGHT;
+        break;
+      case RGN_ALIGN_RIGHT:
+        direction = UI_DIR_LEFT;
+        break;
+      case RGN_ALIGN_BOTTOM:
+        direction = UI_DIR_UP;
+        break;
+      default:
+        direction = UI_DIR_DOWN;
+        break;
     }
   }
   UI_block_direction_set(block, direction);
index 8adb82a22c8739ade530a512e7108e9bee993217..3b21b689ba02244805e805d94c4c6df4b8b1d34c 100644 (file)
@@ -1065,7 +1065,7 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo
   ps->pa->ofsy = -get_panel_size_y(ps->pa);
 
   if (has_category_tabs) {
-    if (align == BUT_VERTICAL && (ar->alignment != RGN_ALIGN_RIGHT)) {
+    if (align == BUT_VERTICAL && (RGN_ALIGN_ENUM_FROM_MASK(ar->alignment) != RGN_ALIGN_RIGHT)) {
       ps->pa->ofsx += UI_PANEL_CATEGORY_MARGIN_WIDTH;
     }
   }
@@ -1913,7 +1913,7 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
 {
   /* no tab outlines for */
   // #define USE_FLAT_INACTIVE
-  const bool is_left = (ar->alignment != RGN_ALIGN_RIGHT);
+  const bool is_left = RGN_ALIGN_ENUM_FROM_MASK(ar->alignment != RGN_ALIGN_RIGHT);
   View2D *v2d = &ar->v2d;
   uiStyle *style = UI_style_get();
   const uiFontStyle *fstyle = &style->widget;
@@ -2201,7 +2201,7 @@ static int ui_handle_panel_category_cycling(const wmEvent *event,
 {
   const bool is_mousewheel = ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE);
   const bool inside_tabregion =
-      ((ar->alignment != RGN_ALIGN_RIGHT) ?
+      ((RGN_ALIGN_ENUM_FROM_MASK(ar->alignment) != RGN_ALIGN_RIGHT) ?
            (event->mval[0] < ((PanelCategoryDyn *)ar->panels_category.first)->rect.xmax) :
            (event->mval[0] > ((PanelCategoryDyn *)ar->panels_category.first)->rect.xmin));
 
index fed3c0b3d1178e30adf8532b6e69ab14a1510762..560c6146afe59725f97b2c722a8360c9cd9e0dee 100644 (file)
@@ -280,13 +280,13 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
       ARegion *ar = CTX_wm_region(C);
       if (sa && ar) {
         if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
-          if (ED_area_header_alignment(sa) == RGN_ALIGN_BOTTOM) {
+          if (RGN_ALIGN_ENUM_FROM_MASK(ED_area_header_alignment(sa)) == RGN_ALIGN_BOTTOM) {
             UI_block_direction_set(block, UI_DIR_UP);
             UI_block_order_flip(block);
           }
         }
         if (ar->regiontype == RGN_TYPE_FOOTER) {
-          if (ED_area_footer_alignment(sa) == RGN_ALIGN_BOTTOM) {
+          if (RGN_ALIGN_ENUM_FROM_MASK(ED_area_footer_alignment(sa)) == RGN_ALIGN_BOTTOM) {
             UI_block_direction_set(block, UI_DIR_UP);
             UI_block_order_flip(block);
           }
index cd0421dde09d194e0df78789387eb02040743e6f..2042c15ed967e92be1b8d5bba40bb4cc76022fa9 100644 (file)
@@ -189,12 +189,12 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v
       /* Prefer popover from header to be positioned into the editor. */
       else if (sa && ar) {
         if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
-          if (ED_area_header_alignment(sa) == RGN_ALIGN_BOTTOM) {
+          if (RGN_ALIGN_ENUM_FROM_MASK(ED_area_header_alignment(sa)) == RGN_ALIGN_BOTTOM) {
             UI_block_direction_set(block, UI_DIR_UP | UI_DIR_CENTER_X);
           }
         }
         if (ar->regiontype == RGN_TYPE_FOOTER) {
-          if (ED_area_footer_alignment(sa) == RGN_ALIGN_BOTTOM) {
+          if (RGN_ALIGN_ENUM_FROM_MASK(ED_area_footer_alignment(sa)) == RGN_ALIGN_BOTTOM) {
             UI_block_direction_set(block, UI_DIR_UP | UI_DIR_CENTER_X);
           }
         }
index f4d9c353102c416ec85996b822da13034f47cef8..39b2c060ba4ea8ddbca807312687096a04ad6b5f 100644 (file)
@@ -1141,6 +1141,9 @@ static void region_overlap_fix(ScrArea *sa, ARegion *ar)
     }
   }
 
+  /* Guard against flags slipping through that would have to be masked out in usages below. */
+  BLI_assert(align1 == RGN_ALIGN_ENUM_FROM_MASK(align1));
+
   /* translate or close */
   if (ar1) {
     if (align1 == RGN_ALIGN_LEFT) {
@@ -2585,7 +2588,7 @@ void ED_region_panels_draw(const bContext *C, ARegion *ar)
   /* scrollers */
   const rcti *mask = NULL;
   rcti mask_buf;
-  if (ar->runtime.category && (ar->alignment == RGN_ALIGN_RIGHT)) {
+  if (ar->runtime.category && (RGN_ALIGN_ENUM_FROM_MASK(ar->alignment) == RGN_ALIGN_RIGHT)) {
     UI_view2d_mask_from_win(v2d, &mask_buf);
     mask_buf.xmax -= UI_PANEL_CATEGORY_MARGIN_WIDTH;
     mask = &mask_buf;
@@ -3347,7 +3350,9 @@ static void region_visible_rect_calc(ARegion *ar, rcti *rect)
   for (; arn; arn = arn->next) {
     if (ar != arn && arn->overlap) {
       if (BLI_rcti_isect(rect, &arn->winrct, NULL)) {
-        if (ELEM(arn->alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
+        int alignment = RGN_ALIGN_ENUM_FROM_MASK(arn->alignment);
+
+        if (ELEM(alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
           /* Overlap left, also check 1 pixel offset (2 regions on one side). */
           if (ABS(rect->xmin - arn->winrct.xmin) < 2) {
             rect->xmin = arn->winrct.xmax;
@@ -3358,7 +3363,7 @@ static void region_visible_rect_calc(ARegion *ar, rcti *rect)
             rect->xmax = arn->winrct.xmin;
           }
         }
-        else if (ELEM(arn->alignment, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
+        else if (ELEM(alignment, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
           /* Same logic as above for vertical regions. */
           if (ABS(rect->ymin - arn->winrct.ymin) < 2) {
             rect->ymin = arn->winrct.ymax;
@@ -3367,7 +3372,7 @@ static void region_visible_rect_calc(ARegion *ar, rcti *rect)
             rect->ymax = arn->winrct.ymin;
           }
         }
-        else if (arn->alignment == RGN_ALIGN_FLOAT) {
+        else if (alignment == RGN_ALIGN_FLOAT) {
           /* Skip floating. */
         }
         else {
index 46559efc6140d418e4018590a1a2aace4686b1e4..942050aaffd142993d790ad49583d04a2fd7ca92 100644 (file)
@@ -67,10 +67,12 @@ bool ED_region_panel_category_gutter_calc_rect(const ARegion *ar, rcti *r_ar_gut
   if (UI_panel_category_is_visible(ar)) {
     const int category_tabs_width = round_fl_to_int(UI_view2d_scale_get_x(&ar->v2d) *
                                                     UI_PANEL_CATEGORY_MARGIN_WIDTH);
-    if (ar->alignment == RGN_ALIGN_LEFT) {
+    const int alignment = RGN_ALIGN_ENUM_FROM_MASK(ar->alignment);
+
+    if (alignment == RGN_ALIGN_LEFT) {
       r_ar_gutter->xmax = r_ar_gutter->xmin + category_tabs_width;
     }
-    else if (ar->alignment == RGN_ALIGN_RIGHT) {
+    else if (alignment == RGN_ALIGN_RIGHT) {
       r_ar_gutter->xmin = r_ar_gutter->xmax - category_tabs_width;
     }
     else {
@@ -141,14 +143,16 @@ bool ED_region_contains_xy(const ARegion *ar, const int event_xy[2])
       else {
         /* Side-bar & any other kind of overlapping region. */
 
+        const int alignment = RGN_ALIGN_ENUM_FROM_MASK(ar->alignment);
+
         /* Check alignment to avoid region tabs being clipped out
          * by only clipping a single axis for aligned regions. */
-        if (ELEM(ar->alignment, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
+        if (ELEM(alignment, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
           if (!ED_region_overlap_isect_x_with_margin(ar, event_xy[0], overlap_margin)) {
             return false;
           }
         }
-        else if (ELEM(ar->alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
+        else if (ELEM(alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
           if (ED_region_panel_category_gutter_isect_xy(ar, event_xy)) {
             /* pass */
           }
index dd09def2df6781918f8cbdf5d60dcb5364223fb5..9ea8c8293d42f081cb8abb2fb2ce959e5124cfea 100644 (file)
@@ -4114,8 +4114,9 @@ void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UN
 {
   ScrArea *sa = CTX_wm_area(C);
   ARegion *ar = CTX_wm_region(C);
-  const char *but_flip_str = (ar->alignment == RGN_ALIGN_TOP) ? IFACE_("Flip to Bottom") :
-                                                                IFACE_("Flip to Top");
+  const char *but_flip_str = (RGN_ALIGN_ENUM_FROM_MASK(ar->alignment) == RGN_ALIGN_TOP) ?
+                                 IFACE_("Flip to Bottom") :
+                                 IFACE_("Flip to Top");
   {
     PointerRNA ptr;
     RNA_pointer_create((ID *)CTX_wm_screen(C), &RNA_Space, sa->spacedata.first, &ptr);
@@ -4160,8 +4161,9 @@ void ED_screens_footer_tools_menu_create(bContext *C, uiLayout *layout, void *UN
 {
   ScrArea *sa = CTX_wm_area(C);
   ARegion *ar = CTX_wm_region(C);
-  const char *but_flip_str = (ar->alignment == RGN_ALIGN_TOP) ? IFACE_("Flip to Bottom") :
-                                                                IFACE_("Flip to Top");
+  const char *but_flip_str = (RGN_ALIGN_ENUM_FROM_MASK(ar->alignment) == RGN_ALIGN_TOP) ?
+                                 IFACE_("Flip to Bottom") :
+                                 IFACE_("Flip to Top");
   {
     PointerRNA ptr;
     RNA_pointer_create((ID *)CTX_wm_screen(C), &RNA_Space, sa->spacedata.first, &ptr);
@@ -4186,8 +4188,9 @@ void ED_screens_footer_tools_menu_create(bContext *C, uiLayout *layout, void *UN
 void ED_screens_navigation_bar_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg))
 {
   const ARegion *ar = CTX_wm_region(C);
-  const char *but_flip_str = (ar->alignment == RGN_ALIGN_LEFT) ? IFACE_("Flip to Right") :
-                                                                 IFACE_("Flip to Left");
+  const char *but_flip_str = (RGN_ALIGN_ENUM_FROM_MASK(ar->alignment) == RGN_ALIGN_LEFT) ?
+                                 IFACE_("Flip to Right") :
+                                 IFACE_("Flip to Left");
 
   /* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */
   uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
index 63f27b4d74a4bdc85d47ebe468be16b5fc8c7b95..69060daa171be53c9335a2d8ec2e9c9ca76cfba1 100644 (file)
@@ -81,7 +81,7 @@ static SpaceLink *statusbar_duplicate(SpaceLink *sl)
 /* add handlers, stuff you only do once or on area/region changes */
 static void statusbar_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region)
 {
-  if (ELEM(region->alignment, RGN_ALIGN_RIGHT)) {
+  if (ELEM(RGN_ALIGN_ENUM_FROM_MASK(region->alignment), RGN_ALIGN_RIGHT)) {
     region->flag |= RGN_FLAG_DYNAMIC_SIZE;
   }
   ED_region_header_init(region);
index 725a49e417e13ae22072c95fefb2247eb93ca326..d62fcf45d684fd4f466b3fe5b6761fc51cded66b 100644 (file)
@@ -103,7 +103,7 @@ static void topbar_main_region_init(wmWindowManager *wm, ARegion *region)
   wmKeyMap *keymap;
 
   /* force delayed UI_view2d_region_reinit call */
-  if (ELEM(region->alignment, RGN_ALIGN_RIGHT)) {
+  if (ELEM(RGN_ALIGN_ENUM_FROM_MASK(region->alignment), RGN_ALIGN_RIGHT)) {
     region->flag |= RGN_FLAG_DYNAMIC_SIZE;
   }
   UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_HEADER, region->winx, region->winy);
@@ -123,7 +123,7 @@ static void topbar_keymap(struct wmKeyConfig *UNUSED(keyconf))
 /* add handlers, stuff you only do once or on area/region changes */
 static void topbar_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
 {
-  if ((ar->alignment & ~RGN_SPLIT_PREV) == RGN_ALIGN_RIGHT) {
+  if (RGN_ALIGN_ENUM_FROM_MASK(ar->alignment) == RGN_ALIGN_RIGHT) {
     ar->flag |= RGN_FLAG_DYNAMIC_SIZE;
   }
   ED_region_header_init(ar);
index 14d4e05b77ab4f9972b3f79c57b114ac910ba8d8..a26a728461d56783168c6b42059b98d14cd91c90 100644 (file)
@@ -514,12 +514,12 @@ void wm_draw_region_blend(ARegion *ar, int view, bool blend)
 
   /* Slide vertical panels */
   float ofs_x = BLI_rcti_size_x(&ar->winrct) * (1.0f - alpha_easing);
-  if (ar->alignment == RGN_ALIGN_RIGHT) {
+  if (RGN_ALIGN_ENUM_FROM_MASK(ar->alignment) == RGN_ALIGN_RIGHT) {
     rect_geo.xmin += ofs_x;
     rect_tex.xmax *= alpha_easing;
     alpha = 1.0f;
   }
-  else if (ar->alignment == RGN_ALIGN_LEFT) {
+  else if (RGN_ALIGN_ENUM_FROM_MASK(ar->alignment) == RGN_ALIGN_LEFT) {
     rect_geo.xmax -= ofs_x;
     rect_tex.xmin += 1.0f - alpha_easing;
     alpha = 1.0f;