UI: avoid subtracting shadow from winrct
authorCampbell Barton <ideasman42@gmail.com>
Tue, 18 Aug 2015 04:16:58 +0000 (14:16 +1000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 18 Aug 2015 04:16:58 +0000 (14:16 +1000)
For popup interactions we need to know if events are in the region or not,
however subtracting the shadow isn't so reliable, since its not always added to all sides of a popup.

Instead, get the winrct value from a popup using the block rect, otherwise the winrct as-is.

source/blender/blenlib/BLI_rect.h
source/blender/blenlib/intern/rct.c
source/blender/editors/interface/interface.c
source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/interface_intern.h

index 242ba9f860ae941e78a920de56f5c65cf5585a2f..a98931d2ae88a5266f6e305305bf46edc98a8052 100644 (file)
@@ -92,6 +92,7 @@ void BLI_rcti_union(struct rcti *rcti1, const struct rcti *rcti2);
 void BLI_rctf_union(struct rctf *rctf1, const struct rctf *rctf2);
 void BLI_rcti_rctf_copy(struct rcti *dst, const struct rctf *src);
 void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src);
+void BLI_rcti_rctf_copy_floor(struct rcti *dst, const struct rctf *src);
 
 void BLI_rctf_rotate_expand(rctf *dst, const rctf *src, const float angle);
 
index 8de5d2ef1728d5478164790c7de55f365ebe70a0..646613d9a2970977269338c363710592259402f9 100644 (file)
@@ -584,6 +584,14 @@ void BLI_rcti_rctf_copy(rcti *dst, const rctf *src)
        dst->ymax = dst->ymin + floorf(BLI_rctf_size_y(src) + 0.5f);
 }
 
+void BLI_rcti_rctf_copy_floor(rcti *dst, const rctf *src)
+{
+       dst->xmin = floorf(src->xmin);
+       dst->xmax = floorf(src->xmax);
+       dst->ymin = floorf(src->ymin);
+       dst->ymax = floorf(src->ymax);
+}
+
 void BLI_rctf_rcti_copy(rctf *dst, const rcti *src)
 {
        dst->xmin = src->xmin;
index 8efa14a5358b3172bad85885890c643df13fbf15..e435d40a2ef4535cde3f198bb60573e9fe54ea0e 100644 (file)
@@ -215,6 +215,23 @@ void ui_region_to_window(const ARegion *ar, int *x, int *y)
        *x += ar->winrct.xmin;
        *y += ar->winrct.ymin;
 }
+
+/**
+ * Popups will add a margin to #ARegion.winrct for shadow,
+ * for interactivity (point-inside tests for eg), we want the winrct without the margin added.
+ */
+void ui_region_winrct_get_no_margin(const struct ARegion *ar, struct rcti *r_rect)
+{
+       uiBlock *block = ar->uiblocks.first;
+       if (block && block->flag & UI_BLOCK_LOOP) {
+               BLI_rcti_rctf_copy_floor(r_rect, &block->rect);
+               BLI_rcti_translate(r_rect, ar->winrct.xmin, ar->winrct.ymin);
+       }
+       else {
+               *r_rect = ar->winrct;
+       }
+}
+
 /* ******************* block calc ************************* */
 
 void ui_block_translate(uiBlock *block, int x, int y)
@@ -1313,16 +1330,8 @@ static void ui_but_to_pixelrect(rcti *rect, const ARegion *ar, uiBlock *block, u
        rctf rectf;
 
        ui_block_to_window_rctf(ar, block, &rectf, (but) ? &but->rect : &block->rect);
-
-       rectf.xmin -= ar->winrct.xmin;
-       rectf.ymin -= ar->winrct.ymin;
-       rectf.xmax -= ar->winrct.xmin;
-       rectf.ymax -= ar->winrct.ymin;
-
-       rect->xmin = floorf(rectf.xmin);
-       rect->ymin = floorf(rectf.ymin);
-       rect->xmax = floorf(rectf.xmax);
-       rect->ymax = floorf(rectf.ymax);
+       BLI_rcti_rctf_copy_floor(rect, &rectf);
+       BLI_rcti_translate(rect, -ar->winrct.xmin, -ar->winrct.ymin);
 }
 
 /* uses local copy of style, to scale things down, and allow widgets to change stuff */
index 231ba03000ba67d974f15a287a198b9e62d7aa4c..6b3523f388fd6c8a3290cd8e06def22a87462896 100644 (file)
@@ -7226,18 +7226,13 @@ static void ui_blocks_set_tooltips(ARegion *ar, const bool enable)
 static bool ui_region_contains_point_px(ARegion *ar, int x, int y)
 {
        uiBlock *block = ar->uiblocks.first;
-       rcti rect = ar->winrct;
-       const bool is_block_loop = block->flag & UI_BLOCK_LOOP;
+       rcti winrct;
 
        /* scale down area rect to exclude shadow */
-       if (is_block_loop) {
-               const int shadow_xy = UI_ThemeMenuShadowWidth();
-               BLI_rcti_resize(&rect, BLI_rcti_size_x(&ar->winrct) - shadow_xy * 2,
-                               BLI_rcti_size_y(&ar->winrct) - shadow_xy * 2);
-       }
+       ui_region_winrct_get_no_margin(ar, &winrct);
 
        /* check if the mouse is in the region */
-       if (!BLI_rcti_isect_pt(&rect, x, y)) {
+       if (!BLI_rcti_isect_pt(&winrct, x, y)) {
                for (block = ar->uiblocks.first; block; block = block->next)
                        block->auto_open = false;
                
@@ -9703,16 +9698,14 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE
                uiBut *but_other;
                uiHandleButtonData *data;
                bool is_inside_menu = false;
-               const int shadow_xy = UI_ThemeMenuShadowWidth();
 
                /* look for a popup menu containing the mouse */
                for (ar_temp = screen->regionbase.first; ar_temp; ar_temp = ar_temp->next) {
-                       rcti rect = ar_temp->winrct;
+                       rcti winrct;
+
+                       ui_region_winrct_get_no_margin(ar_temp, &winrct);
 
-                       /* resize region rect to ignore shadow */
-                       BLI_rcti_resize(&rect, BLI_rcti_size_x(&ar_temp->winrct) - shadow_xy * 2,
-                                       BLI_rcti_size_y(&ar_temp->winrct) - shadow_xy * 2);
-                       if (BLI_rcti_isect_pt_v(&rect, &event->x)) {
+                       if (BLI_rcti_isect_pt_v(&winrct, &event->x)) {
                                BLI_assert(ar_temp->type->regionid == RGN_TYPE_TEMPORARY);
 
                                is_inside_menu = true;
index df554a2fdfd6a01eadd24df8b6fd44af74b35243..8ad9770983c850829f1dc1ed0e73acf80a5fc242 100644 (file)
@@ -450,6 +450,7 @@ extern void ui_window_to_block_fl(const struct ARegion *ar, uiBlock *block, floa
 extern void ui_window_to_block(const struct ARegion *ar, uiBlock *block, int *x, int *y);
 extern void ui_window_to_region(const ARegion *ar, int *x, int *y);
 extern void ui_region_to_window(const struct ARegion *ar, int *x, int *y);
+extern void ui_region_winrct_get_no_margin(const struct ARegion *ar, struct rcti *r_rect);
 
 extern double ui_but_value_get(uiBut *but);
 extern void ui_but_value_set(uiBut *but, double value);