diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-23 09:43:50 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-23 09:51:00 +0300 |
commit | be3adb51de21652d64a6839cd5614c5096064c6a (patch) | |
tree | b76f6346673205ed3aeb33a4768bd2a182a4c605 /source/blender/editors/screen | |
parent | 310f288bb03b4197f54b7d7b6d611669f2604d04 (diff) |
UI: ignore events in empty region overlap areas
- Resizable areas use 2D view bounds.
- Header uses the button bounds.
- A margin is added to avoid clicking between buttons.
- Region resize edges clamp to the 2D view bounds.
Resovles T61554
Diffstat (limited to 'source/blender/editors/screen')
-rw-r--r-- | source/blender/editors/screen/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/editors/screen/area.c | 32 | ||||
-rw-r--r-- | source/blender/editors/screen/area_query.c | 123 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_edit.c | 2 |
4 files changed, 157 insertions, 1 deletions
diff --git a/source/blender/editors/screen/CMakeLists.txt b/source/blender/editors/screen/CMakeLists.txt index daa72ac194c..9576920bcd2 100644 --- a/source/blender/editors/screen/CMakeLists.txt +++ b/source/blender/editors/screen/CMakeLists.txt @@ -39,6 +39,7 @@ set(INC_SYS set(SRC area.c + area_query.c area_utils.c glutil.c screen_context.c diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 5923d0373d5..ab68b3cfcf8 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -901,33 +901,65 @@ static void fullscreen_azone_initialize(ScrArea *sa, ARegion *ar) #define AZONEPAD_ICON (0.45f * U.widget_unit) static void region_azone_edge(AZone *az, ARegion *ar) { + int clip_axis = -1; switch (az->edge) { case AE_TOP_TO_BOTTOMRIGHT: az->x1 = ar->winrct.xmin; az->y1 = ar->winrct.ymax - AZONEPAD_EDGE; az->x2 = ar->winrct.xmax; az->y2 = ar->winrct.ymax + AZONEPAD_EDGE; + if (ar->overlap) { + clip_axis = 0; + } break; case AE_BOTTOM_TO_TOPLEFT: az->x1 = ar->winrct.xmin; az->y1 = ar->winrct.ymin + AZONEPAD_EDGE; az->x2 = ar->winrct.xmax; az->y2 = ar->winrct.ymin - AZONEPAD_EDGE; + if (ar->overlap) { + clip_axis = 0; + } break; case AE_LEFT_TO_TOPRIGHT: az->x1 = ar->winrct.xmin - AZONEPAD_EDGE; az->y1 = ar->winrct.ymin; az->x2 = ar->winrct.xmin + AZONEPAD_EDGE; az->y2 = ar->winrct.ymax; + if (ar->overlap) { + clip_axis = 1; + } break; case AE_RIGHT_TO_TOPLEFT: az->x1 = ar->winrct.xmax + AZONEPAD_EDGE; az->y1 = ar->winrct.ymin; az->x2 = ar->winrct.xmax - AZONEPAD_EDGE; az->y2 = ar->winrct.ymax; + if (ar->overlap) { + clip_axis = 1; + } break; } + /* Constrain action zones to usable area of region. + * Needed so blank areas of the region are interactive and aciton zones don't get in the way. */ + if (clip_axis == 0) { + az->x1 = max_ii(az->x1, + (ar->winrct.xmin + UI_view2d_view_to_region_x(&ar->v2d, ar->v2d.tot.xmin)) - + UI_REGION_OVERLAP_MARGIN); + az->x2 = min_ii(az->x2, + (ar->winrct.xmin + UI_view2d_view_to_region_x(&ar->v2d, ar->v2d.tot.xmax)) + + UI_REGION_OVERLAP_MARGIN); + } + else if (clip_axis == 1) { + az->y1 = max_ii(az->y1, + (ar->winrct.ymin + UI_view2d_view_to_region_y(&ar->v2d, ar->v2d.tot.ymin)) - + UI_REGION_OVERLAP_MARGIN); + az->y2 = min_ii(az->y2, + (ar->winrct.ymin + UI_view2d_view_to_region_y(&ar->v2d, ar->v2d.tot.ymax)) + + UI_REGION_OVERLAP_MARGIN); + } + BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2); } diff --git a/source/blender/editors/screen/area_query.c b/source/blender/editors/screen/area_query.c new file mode 100644 index 00000000000..a4bcf622815 --- /dev/null +++ b/source/blender/editors/screen/area_query.c @@ -0,0 +1,123 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup edscr + * + * Query functions for area/region. + */ + +#include "DNA_userdef_types.h" + +#include "BLI_blenlib.h" +#include "BLI_utildefines.h" + +#include "RNA_types.h" + +#include "WM_api.h" + +#include "ED_screen.h" + +#include "UI_interface.h" +#include "UI_view2d.h" + +bool ED_region_overlap_isect_x(const ARegion *ar, const int event_x) +{ + BLI_assert(ar->overlap); + /* No contents, skip it. */ + if (ar->v2d.mask.xmin == ar->v2d.mask.xmax) { + return false; + } + return BLI_rctf_isect_x(&ar->v2d.tot, + UI_view2d_region_to_view_x(&ar->v2d, event_x - ar->winrct.xmin)); +} + +bool ED_region_overlap_isect_y(const ARegion *ar, const int event_y) +{ + BLI_assert(ar->overlap); + /* No contents, skip it. */ + if (ar->v2d.mask.ymin == ar->v2d.mask.ymax) { + return false; + } + return BLI_rctf_isect_y(&ar->v2d.tot, + UI_view2d_region_to_view_y(&ar->v2d, event_y - ar->winrct.ymin)); +} + +bool ED_region_overlap_isect_xy(const ARegion *ar, const int event_xy[2]) +{ + return (ED_region_overlap_isect_x(ar, event_xy[0]) && + ED_region_overlap_isect_y(ar, event_xy[1])); +} + +bool ED_region_overlap_isect_x_with_margin(const ARegion *ar, const int event_x, const int margin) +{ + BLI_assert(ar->overlap); + /* No contents, skip it. */ + if (ar->v2d.mask.xmin == ar->v2d.mask.xmax) { + return false; + } + int region_x = event_x - ar->winrct.xmin; + return ((ar->v2d.tot.xmin <= UI_view2d_region_to_view_x(&ar->v2d, region_x + margin)) && + (ar->v2d.tot.xmax >= UI_view2d_region_to_view_x(&ar->v2d, region_x - margin))); +} + +bool ED_region_overlap_isect_y_with_margin(const ARegion *ar, const int event_y, const int margin) +{ + BLI_assert(ar->overlap); + /* No contents, skip it. */ + if (ar->v2d.mask.ymin == ar->v2d.mask.ymax) { + return false; + } + int region_y = event_y - ar->winrct.ymin; + return ((ar->v2d.tot.ymin <= UI_view2d_region_to_view_y(&ar->v2d, region_y + margin)) && + (ar->v2d.tot.ymax >= UI_view2d_region_to_view_y(&ar->v2d, region_y - margin))); +} + +bool ED_region_overlap_isect_xy_with_margin(const ARegion *ar, + const int event_xy[2], + const int margin) +{ + return (ED_region_overlap_isect_x_with_margin(ar, event_xy[0], margin) && + ED_region_overlap_isect_y_with_margin(ar, event_xy[1], margin)); +} + +bool ED_region_contains_xy(const ARegion *ar, const int event_xy[2]) +{ + /* Only use the margin when inside the region. */ + if (BLI_rcti_isect_pt_v(&ar->winrct, event_xy)) { + if (ar->overlap) { + const int overlap_margin = UI_REGION_OVERLAP_MARGIN; + /* Note the View2D.tot isn't reliable for headers with spacers otherwise + * we'd check #ED_region_overlap_isect_xy_with_margin for both bases. */ + if (ar->v2d.keeptot == V2D_KEEPTOT_STRICT) { + /* Header. */ + rcti rect; + BLI_rcti_init_pt_radius(&rect, event_xy, overlap_margin); + if (UI_region_but_find_rect_over(ar, &rect) == NULL) { + return false; + } + } + else { + /* Side-bar & any other kind of overlapping region. */ + if (!ED_region_overlap_isect_xy_with_margin(ar, event_xy, overlap_margin)) { + return false; + } + } + } + return true; + } + return false; +} diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 95bade1da64..50f0ab9b96b 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -683,7 +683,7 @@ void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2]) if (sa) { /* make overlap active when mouse over */ for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (BLI_rcti_isect_pt_v(&ar->winrct, xy)) { + if (ED_region_contains_xy(ar, xy)) { scr->active_region = ar; break; } |