Fix T39144: text-select scrolling too fast
Use a timer to get predictable speed.
This commit is contained in:
parent
bd401d9517
commit
2b107beffd
Notes:
blender-bot
2023-02-14 11:00:23 +01:00
Referenced by issue #41919, text selection on large files Referenced by issue #39144, Moving cursor quickly jumps it out of the window when translating objects
|
@ -135,7 +135,7 @@ static void text_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
|
|||
break;
|
||||
case ND_CURSOR:
|
||||
if (st->text && st->text == wmn->reference)
|
||||
text_scroll_to_cursor(st, sa);
|
||||
text_scroll_to_cursor__area(st, sa, true);
|
||||
|
||||
ED_area_tag_redraw(sa);
|
||||
break;
|
||||
|
@ -156,7 +156,7 @@ static void text_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
|
|||
break;
|
||||
case NA_SELECTED:
|
||||
if (st->text && st->text == wmn->reference)
|
||||
text_scroll_to_cursor(st, sa);
|
||||
text_scroll_to_cursor__area(st, sa, true);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
* \ingroup sptext
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLF_api.h"
|
||||
|
@ -44,6 +42,7 @@
|
|||
#include "BKE_context.h"
|
||||
#include "BKE_suggestions.h"
|
||||
#include "BKE_text.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "BIF_gl.h"
|
||||
|
||||
|
@ -1461,22 +1460,15 @@ void text_update_character_width(SpaceText *st)
|
|||
|
||||
/* Moves the view to the cursor location,
|
||||
* also used to make sure the view isn't outside the file */
|
||||
void text_scroll_to_cursor(SpaceText *st, ScrArea *sa)
|
||||
void text_scroll_to_cursor(SpaceText *st, ARegion *ar, const bool center)
|
||||
{
|
||||
Text *text;
|
||||
ARegion *ar = NULL;
|
||||
int i, x, winx = 0;
|
||||
int i, x, winx = ar->winx;
|
||||
|
||||
if (ELEM(NULL, st, st->text, st->text->curl)) return;
|
||||
|
||||
text = st->text;
|
||||
|
||||
for (ar = sa->regionbase.first; ar; ar = ar->next)
|
||||
if (ar->regiontype == RGN_TYPE_WINDOW) {
|
||||
winx = ar->winx;
|
||||
break;
|
||||
}
|
||||
|
||||
text_update_character_width(st);
|
||||
|
||||
i = txt_get_span(text->lines.first, text->sell);
|
||||
|
@ -1486,8 +1478,19 @@ void text_scroll_to_cursor(SpaceText *st, ScrArea *sa)
|
|||
i += offl;
|
||||
}
|
||||
|
||||
if (st->top + st->viewlines <= i || st->top > i)
|
||||
st->top = i - st->viewlines / 2;
|
||||
if (center) {
|
||||
if (st->top + st->viewlines <= i || st->top > i) {
|
||||
st->top = i - st->viewlines / 2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (st->top + st->viewlines <= i) {
|
||||
st->top = i - (st->viewlines - 1);
|
||||
}
|
||||
else if (st->top > i) {
|
||||
st->top = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (st->wordwrap) {
|
||||
st->left = 0;
|
||||
|
@ -1496,8 +1499,19 @@ void text_scroll_to_cursor(SpaceText *st, ScrArea *sa)
|
|||
x = st->cwidth * (text_get_char_pos(st, text->sell->line, text->selc) - st->left);
|
||||
winx -= TXT_OFFSET + (st->showlinenrs ? TEXTXLOC : 0) + TXT_SCROLL_WIDTH;
|
||||
|
||||
if (x <= 0 || x > winx)
|
||||
st->left += (x - winx / 2) / st->cwidth;
|
||||
if (center) {
|
||||
if (x <= 0 || x > winx) {
|
||||
st->left += (x - winx / 2) / st->cwidth;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (x <= 0) {
|
||||
st->left += ((x + 1) / st->cwidth) - 1;
|
||||
}
|
||||
else if (x > winx) {
|
||||
st->left += ((x - (winx + 1)) / st->cwidth) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (st->top < 0) st->top = 0;
|
||||
|
@ -1507,10 +1521,24 @@ void text_scroll_to_cursor(SpaceText *st, ScrArea *sa)
|
|||
st->scroll_accum[1] = 0.0f;
|
||||
}
|
||||
|
||||
/* takes an area instead of a region, use for listeners */
|
||||
void text_scroll_to_cursor__area(SpaceText *st, ScrArea *sa, const bool center)
|
||||
{
|
||||
ARegion *ar;
|
||||
|
||||
if (ELEM(NULL, st, st->text, st->text->curl)) return;
|
||||
|
||||
ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
|
||||
|
||||
if (ar) {
|
||||
text_scroll_to_cursor(st, ar, center);
|
||||
}
|
||||
}
|
||||
|
||||
void text_update_cursor_moved(bContext *C)
|
||||
{
|
||||
ScrArea *sa = CTX_wm_area(C);
|
||||
SpaceText *st = CTX_wm_space_text(C);
|
||||
|
||||
text_scroll_to_cursor(st, sa);
|
||||
text_scroll_to_cursor__area(st, sa, true);
|
||||
}
|
||||
|
|
|
@ -50,7 +50,8 @@ void draw_text_main(struct SpaceText *st, struct ARegion *ar);
|
|||
void text_update_line_edited(struct TextLine *line);
|
||||
void text_update_edited(struct Text *text);
|
||||
void text_update_character_width(struct SpaceText *st);
|
||||
void text_scroll_to_cursor(struct SpaceText *st, struct ScrArea *sa);
|
||||
void text_scroll_to_cursor(struct SpaceText *st, struct ARegion *ar, bool center);
|
||||
void text_scroll_to_cursor__area(struct SpaceText *st, struct ScrArea *sa, bool center);
|
||||
void text_update_cursor_moved(struct bContext *C);
|
||||
|
||||
#define TXT_OFFSET ((int)(0.5f * U.widget_unit))
|
||||
|
|
|
@ -2415,6 +2415,7 @@ typedef struct SetSelection {
|
|||
int selecting;
|
||||
int selc, sell;
|
||||
short old[2];
|
||||
wmTimer *timer; /* needed for scrolling when mouse at region bounds */
|
||||
} SetSelection;
|
||||
|
||||
static int flatten_width(SpaceText *st, const char *str)
|
||||
|
@ -2629,6 +2630,29 @@ static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, con
|
|||
if (!sel) txt_pop_sel(text);
|
||||
}
|
||||
|
||||
static void text_cursor_timer_ensure(bContext *C, SetSelection *ssel)
|
||||
{
|
||||
if (ssel->timer == NULL) {
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
|
||||
ssel->timer = WM_event_add_timer(wm, win, TIMER, 0.02f);
|
||||
}
|
||||
}
|
||||
|
||||
static void text_cursor_timer_remove(bContext *C, SetSelection *ssel)
|
||||
{
|
||||
if (ssel->timer) {
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
|
||||
WM_event_remove_timer(wm, win, ssel->timer);
|
||||
}
|
||||
ssel->timer = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void text_cursor_set_apply(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
SpaceText *st = CTX_wm_space_text(C);
|
||||
|
@ -2636,32 +2660,34 @@ static void text_cursor_set_apply(bContext *C, wmOperator *op, const wmEvent *ev
|
|||
SetSelection *ssel = op->customdata;
|
||||
|
||||
if (event->mval[1] < 0 || event->mval[1] > ar->winy) {
|
||||
int d = (ssel->old[1] - event->mval[1]) * st->pix_per_line;
|
||||
if (d) txt_screen_skip(st, ar, d);
|
||||
text_cursor_timer_ensure(C, ssel);
|
||||
|
||||
text_cursor_set_to_pos(st, ar, event->mval[0], event->mval[1] < 0 ? 0 : ar->winy, 1);
|
||||
|
||||
text_update_cursor_moved(C);
|
||||
WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
|
||||
if (event->type == TIMER) {
|
||||
text_cursor_set_to_pos(st, ar, event->mval[0], event->mval[1], 1);
|
||||
text_scroll_to_cursor(st, ar, false);
|
||||
WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
|
||||
}
|
||||
}
|
||||
else if (!st->wordwrap && (event->mval[0] < 0 || event->mval[0] > ar->winx)) {
|
||||
if (event->mval[0] > ar->winx) st->left++;
|
||||
else if (event->mval[0] < 0 && st->left > 0) st->left--;
|
||||
text_cursor_timer_ensure(C, ssel);
|
||||
|
||||
text_cursor_set_to_pos(st, ar, event->mval[0], event->mval[1], 1);
|
||||
|
||||
text_update_cursor_moved(C);
|
||||
WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
|
||||
// XXX PIL_sleep_ms(10);
|
||||
if (event->type == TIMER) {
|
||||
text_cursor_set_to_pos(st, ar, CLAMPIS(event->mval[0], 0, ar->winx), event->mval[1], 1);
|
||||
text_scroll_to_cursor(st, ar, false);
|
||||
WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
|
||||
}
|
||||
}
|
||||
else {
|
||||
text_cursor_set_to_pos(st, ar, event->mval[0], event->mval[1], 1);
|
||||
text_cursor_timer_remove(C, ssel);
|
||||
|
||||
text_update_cursor_moved(C);
|
||||
WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
|
||||
if (event->type != TIMER) {
|
||||
text_cursor_set_to_pos(st, ar, event->mval[0], event->mval[1], 1);
|
||||
text_scroll_to_cursor(st, ar, false);
|
||||
WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
|
||||
|
||||
ssel->old[0] = event->mval[0];
|
||||
ssel->old[1] = event->mval[1];
|
||||
ssel->old[0] = event->mval[0];
|
||||
ssel->old[1] = event->mval[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2681,6 +2707,7 @@ static void text_cursor_set_exit(bContext *C, wmOperator *op)
|
|||
text_update_cursor_moved(C);
|
||||
WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
|
||||
|
||||
text_cursor_timer_remove(C, ssel);
|
||||
MEM_freeN(ssel);
|
||||
}
|
||||
|
||||
|
@ -2717,6 +2744,7 @@ static int text_set_selection_modal(bContext *C, wmOperator *op, const wmEvent *
|
|||
case RIGHTMOUSE:
|
||||
text_cursor_set_exit(C, op);
|
||||
return OPERATOR_FINISHED;
|
||||
case TIMER:
|
||||
case MOUSEMOVE:
|
||||
text_cursor_set_apply(C, op, event);
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue