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:
2013-04-11 02:28:34 +00:00
parent b77acc2879
commit 075a655cc6
2 changed files with 68 additions and 3 deletions

View File

@@ -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;

View File

@@ -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;