Fix #117572: Top vertical scrollbar tool not working properly #117685

Closed
Philipp Oeser wants to merge 3 commits from lichtwerk/blender:117572 into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
4 changed files with 41 additions and 14 deletions

View File

@ -7,8 +7,11 @@
struct ID;
struct SpaceSpreadsheet;
#define TOP_ROW_HEIGHT (UI_UNIT_Y * 1.1f)
namespace blender::ed::spreadsheet {
ID *get_current_id(const SpaceSpreadsheet *sspreadsheet);
rcti get_layout_maskrect(const SpaceSpreadsheet &sspreadsheet, const ARegion &region);
}
} // namespace blender::ed::spreadsheet

View File

@ -27,7 +27,9 @@
#include "WM_api.hh"
#include "WM_types.hh"
#include "ED_fileselect.hh"
#include "ED_screen.hh"
#include "ED_spreadsheet.hh"
#include "UI_interface.hh"
#include "UI_view2d.hh"
@ -1908,12 +1910,24 @@ static void scroller_activate_init(bContext *C,
* - zooming must be allowed on this axis, otherwise, default to pan
*/
View2DScrollers scrollers;
/* Some Editors like the File-browser or Spreadsheet already set up custom masks for scroll-bars
* (they don't cover the whole region width or height), these need to be considered, otherwise
* coords for `mouse_in_scroller_handle` later are not compatible. */
rcti scroller_mask = v2d->hor;
BLI_rcti_union(&scroller_mask, &v2d->vert);
view2d_scrollers_calc(v2d, &scroller_mask, &scrollers);
/* Some Editors already set up custom masks for scroll-bar drawing (they don't cover the whole
* region width or height), these need to be considered, otherwise coords for
* `mouse_in_scroller_handle` later are not compatible. */
ScrArea *area = CTX_wm_area(C);
rcti scroller_mask;
bool use_scroller_mask = false;
if (area->spacetype == SPACE_FILE) {
Review

Putting checks for specific space types in the 2D view code is a bit hacky/ugly. It's a leaky abstraction that would be nice to avoid.

Putting checks for specific space types in the 2D view code is a bit hacky/ugly. It's a leaky abstraction that would be nice to avoid.
Review

Hm, if an editor can mess with v2d data on its own behalf (without letting a trace that it did), I am not sure how this could be handled better? But if it did, we have to make sure we can repeat the same modifications it did for drawing for mouse interaction as well, no?

Maybe @ideasman42 has a better idea?

Hm, if an editor can mess with v2d data on its own behalf (without letting a trace that it did), I am not sure how this could be handled better? But if it did, we have to make sure we can repeat the same modifications it did for drawing for mouse interaction as well, no? Maybe @ideasman42 has a better idea?
Review

Hmm, okay. Thanks for bearing with me. Would an alternative be storing information in the View2D that told it enough information about the scrollers? I guess scrolling (part of?) scroller_mask there? I'd usually try not to store things that can just be computed from scratch, but these are two very different code paths. I'm basically just trying to think of a way to make this not add complexity long term.

Hmm, okay. Thanks for bearing with me. Would an alternative be storing information in the View2D that told it enough information about the scrollers? I guess scrolling (part of?) `scroller_mask` there? I'd usually try not to store things that can just be computed from scratch, but these are two very different code paths. I'm basically just trying to think of a way to make this not add complexity long term.
Review

guess this could be done, would appreciate feedback from others if putting additional stuff into View2D is preferred

guess this could be done, would appreciate feedback from others if putting additional stuff into View2D is preferred
Review

Maybe I am misunderstanding, but would this be helped with an optional SpaceType callback that returns this rect? Then instead of testing for a specific spacetype just check for the callback?

Maybe I am misunderstanding, but would this be helped with an optional SpaceType callback that returns this rect? Then instead of testing for a specific spacetype just check for the callback?
Review

@Harley : think a spacetype callback is too general, this (at least in theory) could have multiple regions with scrollers (each could have set up own masks)

@Harley : think a spacetype callback is too general, this (at least in theory) could have multiple regions with scrollers (each could have set up own masks)
Review

Would an alternative be storing information in the View2D that told it enough information about the scrollers? I guess scrolling (part of?) scroller_mask there? I'd usually try not to store things that can just be computed from scratch, but these are two very different code paths. I'm basically just trying to think of a way to make this not add complexity long term.

For reference, rcti vert, hor is already for scrollbars, it is just that these are set from one place for drawing and recalculated for interaction. ed556113ce reused those rects, but then again there is this case of V2D_SCROLL_VERTICAL_HANDLES in view2d_masks which does not fit the current approach (but I think I already explained that?).

> Would an alternative be storing information in the View2D that told it enough information about the scrollers? I guess scrolling (part of?) `scroller_mask` there? I'd usually try not to store things that can just be computed from scratch, but these are two very different code paths. I'm basically just trying to think of a way to make this not add complexity long term. For reference, `rcti vert, hor` is already for scrollbars, it is just that these are set from one place for drawing and recalculated for interaction. ed556113ce reused those rects, but then again there is this case of `V2D_SCROLL_VERTICAL_HANDLES` in `view2d_masks` which does not fit the current approach (but I think I already explained that?).
SpaceFile *sfile = CTX_wm_space_file(C);
ED_fileselect_layout_maskrect(sfile->layout, v2d, &scroller_mask);
use_scroller_mask = true;
}
else if (area->spacetype == SPACE_SPREADSHEET) {
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
scroller_mask = blender::ed::spreadsheet::get_layout_maskrect(*sspreadsheet, *region);
use_scroller_mask = true;
}
view2d_scrollers_calc(v2d, use_scroller_mask ? &scroller_mask : nullptr, &scrollers);
/* Use a union of 'cur' & 'tot' in case the current view is far outside 'tot'. In this cases
* moving the scroll bars has far too little effect and the view can get stuck #31476. */

View File

@ -429,6 +429,16 @@ static void update_visible_columns(ListBase &columns, DataSource &data_source)
}
});
}
rcti get_layout_maskrect(const SpaceSpreadsheet &sspreadsheet, const ARegion &region)
{
rcti maskrect;
lichtwerk marked this conversation as resolved Outdated

Return rcti by value, make pointers into references

Return `rcti` by value, make pointers into references
BLI_rcti_init(&maskrect,
get_index_column_width(sspreadsheet.runtime->tot_rows),
region.winx,
0,
region.winy - TOP_ROW_HEIGHT);
return maskrect;
}
static void spreadsheet_main_region_draw(const bContext *C, ARegion *region)
{

View File

@ -8,6 +8,10 @@
#include "GPU_immediate.h"
#include "BKE_context.hh"
#include "ED_spreadsheet.hh"
#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
@ -22,7 +26,7 @@ namespace blender::ed::spreadsheet {
SpreadsheetDrawer::SpreadsheetDrawer()
{
left_column_width = UI_UNIT_X * 2;
top_row_height = UI_UNIT_Y * 1.1f;
top_row_height = TOP_ROW_HEIGHT;
row_height = UI_UNIT_Y;
}
@ -288,12 +292,8 @@ void draw_spreadsheet_in_region(const bContext *C,
draw_top_row_content(C, region, drawer, scroll_offset_x);
draw_cell_contents(C, region, drawer, scroll_offset_x, scroll_offset_y);
rcti scroller_mask;
BLI_rcti_init(&scroller_mask,
drawer.left_column_width,
region->winx,
0,
region->winy - drawer.top_row_height);
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
rcti scroller_mask = get_layout_maskrect(*sspreadsheet, *region);
UI_view2d_scrollers_draw(v2d, &scroller_mask);
}