fix [#34936] Unable to select items using only the arrow keys
ignore small mouse motions for menu/search-box after using the keyboard to navigate.
This commit is contained in:
@@ -84,11 +84,19 @@
|
||||
/* support dragging toggle buttons */
|
||||
#define USE_DRAG_TOGGLE
|
||||
|
||||
/* so we can avoid very small mouse-moves from jumping away from keyboard navigation [#34936] */
|
||||
#define USE_KEYNAV_LIMIT
|
||||
|
||||
/* proto */
|
||||
static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to);
|
||||
static void ui_add_link(bContext *C, uiBut *from, uiBut *to);
|
||||
static int ui_do_but_EXIT(bContext *C, uiBut *but, struct uiHandleButtonData *data, const wmEvent *event);
|
||||
|
||||
#ifdef USE_KEYNAV_LIMIT
|
||||
static void ui_mouse_motion_keynav_init(struct uiKeyNavLock *keynav, const wmEvent *event);
|
||||
static bool ui_mouse_motion_keynav_test(struct uiKeyNavLock *keynav, const wmEvent *event);
|
||||
#endif
|
||||
|
||||
/***************** structs and defines ****************/
|
||||
|
||||
#define BUTTON_TOOLTIP_DELAY 0.500
|
||||
@@ -96,6 +104,8 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, struct uiHandleButtonData *da
|
||||
#define MENU_SCROLL_INTERVAL 0.1
|
||||
#define BUTTON_AUTO_OPEN_THRESH 0.3
|
||||
#define BUTTON_MOUSE_TOWARDS_THRESH 1.0
|
||||
/* pixels to move the cursor to get out of keyboard navigation */
|
||||
#define BUTTON_KEYNAV_PX_LIMIT 4
|
||||
|
||||
typedef enum uiButtonActivateType {
|
||||
BUTTON_ACTIVATE_OVER,
|
||||
@@ -2118,12 +2128,20 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
|
||||
bool changed = false, inbox = false, update = false;
|
||||
|
||||
switch (event->type) {
|
||||
case WHEELUPMOUSE:
|
||||
case WHEELDOWNMOUSE:
|
||||
case MOUSEMOVE:
|
||||
case MOUSEPAN:
|
||||
if (data->searchbox)
|
||||
if (data->searchbox) {
|
||||
#ifdef USE_KEYNAV_LIMIT
|
||||
if ((event->type == MOUSEMOVE) && ui_mouse_motion_keynav_test(&block->handle->keynav_state, event)) {
|
||||
/* pass */
|
||||
}
|
||||
else {
|
||||
ui_searchbox_event(C, data->searchbox, but, event);
|
||||
}
|
||||
#else
|
||||
ui_searchbox_event(C, data->searchbox, but, event);
|
||||
#endif
|
||||
}
|
||||
|
||||
break;
|
||||
case RIGHTMOUSE:
|
||||
@@ -2194,8 +2212,12 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
|
||||
event->shift, event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
|
||||
retval = WM_UI_HANDLER_BREAK;
|
||||
break;
|
||||
case WHEELDOWNMOUSE:
|
||||
case DOWNARROWKEY:
|
||||
if (data->searchbox) {
|
||||
#ifdef USE_KEYNAV_LIMIT
|
||||
ui_mouse_motion_keynav_init(&block->handle->keynav_state, event);
|
||||
#endif
|
||||
ui_searchbox_event(C, data->searchbox, but, event);
|
||||
break;
|
||||
}
|
||||
@@ -2205,8 +2227,12 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
|
||||
event->shift, STRCUR_JUMP_ALL);
|
||||
retval = WM_UI_HANDLER_BREAK;
|
||||
break;
|
||||
case WHEELUPMOUSE:
|
||||
case UPARROWKEY:
|
||||
if (data->searchbox) {
|
||||
#ifdef USE_KEYNAV_LIMIT
|
||||
ui_mouse_motion_keynav_init(&block->handle->keynav_state, event);
|
||||
#endif
|
||||
ui_searchbox_event(C, data->searchbox, but, event);
|
||||
break;
|
||||
}
|
||||
@@ -6727,6 +6753,26 @@ static bool ui_mouse_motion_towards_check(uiBlock *block, uiPopupBlockHandle *me
|
||||
return menu->dotowards;
|
||||
}
|
||||
|
||||
#ifdef USE_KEYNAV_LIMIT
|
||||
static void ui_mouse_motion_keynav_init(struct uiKeyNavLock *keynav, const wmEvent *event)
|
||||
{
|
||||
keynav->is_keynav = true;
|
||||
copy_v2_v2_int(keynav->event_xy, &event->x);
|
||||
}
|
||||
/**
|
||||
* Return true if keyinput isn't blocking mouse-motion,
|
||||
* or if the mouse-motion is enough to disable keyinput.
|
||||
*/
|
||||
static bool ui_mouse_motion_keynav_test(struct uiKeyNavLock *keynav, const wmEvent *event)
|
||||
{
|
||||
if (keynav->is_keynav && (len_manhattan_v2v2_int(keynav->event_xy, &event->x) > BUTTON_KEYNAV_PX_LIMIT)) {
|
||||
keynav->is_keynav = false;
|
||||
}
|
||||
|
||||
return keynav->is_keynav;
|
||||
}
|
||||
#endif /* USE_KEYNAV_LIMIT */
|
||||
|
||||
static char ui_menu_scroll_test(uiBlock *block, int my)
|
||||
{
|
||||
if (block->flag & (UI_BLOCK_CLIPTOP | UI_BLOCK_CLIPBOTTOM)) {
|
||||
@@ -6918,6 +6964,10 @@ static int ui_handle_menu_event(bContext *C, const wmEvent *event, uiPopupBlockH
|
||||
|
||||
PASS_EVENT_TO_PARENT_IF_NONACTIVE;
|
||||
|
||||
#ifdef USE_KEYNAV_LIMIT
|
||||
ui_mouse_motion_keynav_init(&menu->keynav_state, event);
|
||||
#endif
|
||||
|
||||
but = ui_but_find_activated(ar);
|
||||
if (but) {
|
||||
/* is there a situation where UI_LEFT or UI_RIGHT would also change navigation direction? */
|
||||
@@ -7132,6 +7182,12 @@ static int ui_handle_menu_event(bContext *C, const wmEvent *event, uiPopupBlockH
|
||||
if (menu->menuretval) {
|
||||
/* pass */
|
||||
}
|
||||
#ifdef USE_KEYNAV_LIMIT
|
||||
else if ((event->type == MOUSEMOVE) && ui_mouse_motion_keynav_test(&menu->keynav_state, event)) {
|
||||
/* don't handle the mousemove if we're using key-navigation */
|
||||
retval = WM_UI_HANDLER_BREAK;
|
||||
}
|
||||
#endif
|
||||
else if (event->type == ESCKEY && event->val == KM_PRESS) {
|
||||
/* esc cancels this and all preceding menus */
|
||||
menu->menuretval = UI_RETURN_CANCEL;
|
||||
|
||||
@@ -419,6 +419,13 @@ void ui_block_to_scene_linear_v3(uiBlock *block, float pixel[3]);
|
||||
|
||||
/* interface_regions.c */
|
||||
|
||||
struct uiKeyNavLock {
|
||||
/* set when we're using keyinput */
|
||||
bool is_keynav;
|
||||
/* only used to check if we've moved the cursor */
|
||||
int event_xy[2];
|
||||
};
|
||||
|
||||
struct uiPopupBlockHandle {
|
||||
/* internal */
|
||||
struct ARegion *region;
|
||||
@@ -433,6 +440,8 @@ struct uiPopupBlockHandle {
|
||||
|
||||
struct wmTimer *scrolltimer;
|
||||
|
||||
struct uiKeyNavLock keynav_state;
|
||||
|
||||
/* for operator popups */
|
||||
struct wmOperatorType *optype;
|
||||
ScrArea *ctx_area;
|
||||
|
||||
Reference in New Issue
Block a user