forked from bartvdbraak/blender
Fix for glitch with menus not reliably setting an active item (D674)
When menus are clamped to the window bounds, its was possible not to have an active menu-item under the mouse, Making Ctrl+S,Enter not completely reliable. Changes needed to support this are: - menu item is activated on popup menus (to avoid relying on mouse-over) - moving mouse away from menu items only de-activates when over a new menu-item. - Mouse clicks are ignored if they are not directly over the menu item.
This commit is contained in:
parent
e7b396c954
commit
47e7ce696c
@ -385,7 +385,7 @@ void ui_pan_to_scroll(const wmEvent *event, int *type, int *val)
|
||||
}
|
||||
}
|
||||
|
||||
static bool ui_but_is_editable(const uiBut *but)
|
||||
bool ui_but_is_editable(const uiBut *but)
|
||||
{
|
||||
return !ELEM(but->type, LABEL, SEPR, SEPRLINE, ROUNDBOX, LISTBOX, PROGRESSBAR);
|
||||
}
|
||||
@ -7199,6 +7199,17 @@ void ui_button_activate_do(bContext *C, ARegion *ar, uiBut *but)
|
||||
ui_do_button(C, but->block, but, &event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulate moving the mouse over a button (or navigating to it with arrow keys).
|
||||
*
|
||||
* exported so menus can start with a highlighted button,
|
||||
* even if the mouse isnt over it
|
||||
*/
|
||||
void ui_button_activate_over(bContext *C, ARegion *ar, uiBut *but)
|
||||
{
|
||||
button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
|
||||
}
|
||||
|
||||
void ui_button_execute_begin(struct bContext *UNUSED(C), struct ARegion *ar, uiBut *but, void **active_back)
|
||||
{
|
||||
/* note: ideally we would not have to change 'but->active' however
|
||||
@ -7261,12 +7272,20 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
|
||||
retval = WM_UI_HANDLER_CONTINUE;
|
||||
break;
|
||||
case MOUSEMOVE:
|
||||
/* verify if we are still over the button, if not exit */
|
||||
if (!ui_mouse_inside_button(ar, but, event->x, event->y)) {
|
||||
data->cancel = true;
|
||||
button_activate_state(C, but, BUTTON_STATE_EXIT);
|
||||
{
|
||||
uiBut *but_other = ui_but_find_mouse_over(ar, event);
|
||||
bool exit = false;
|
||||
|
||||
if (!ui_block_is_menu(block) &&
|
||||
!ui_mouse_inside_button(ar, but, event->x, event->y))
|
||||
{
|
||||
exit = true;
|
||||
}
|
||||
else if (ui_but_find_mouse_over(ar, event) != but) {
|
||||
else if (but_other && ui_but_is_editable(but_other) && (but_other != but)) {
|
||||
exit = true;
|
||||
}
|
||||
|
||||
if (exit) {
|
||||
data->cancel = true;
|
||||
button_activate_state(C, but, BUTTON_STATE_EXIT);
|
||||
}
|
||||
@ -7277,6 +7296,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case TIMER:
|
||||
{
|
||||
/* handle tooltip timer */
|
||||
@ -7859,6 +7879,16 @@ static int ui_handle_menu_button(bContext *C, const wmEvent *event, uiPopupBlock
|
||||
uiBut *but = ui_but_find_activated(ar);
|
||||
int retval;
|
||||
|
||||
if (but) {
|
||||
/* Its possible there is an active menu item NOT under the mouse,
|
||||
* in this case ignore mouse clicks outside the button (but Enter etc is accepted) */
|
||||
if ((event->type != MOUSEMOVE) && ISMOUSE(event->type)) {
|
||||
if (!ui_mouse_inside_button(but->active->region, but, event->x, event->y)) {
|
||||
but = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (but) {
|
||||
ScrArea *ctx_area = CTX_wm_area(C);
|
||||
ARegion *ctx_region = CTX_wm_region(C);
|
||||
|
@ -552,6 +552,7 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol
|
||||
PointerRNA *ui_handle_afterfunc_add_operator(struct wmOperatorType *ot, int opcontext, bool create_props);
|
||||
extern void ui_pan_to_scroll(const struct wmEvent *event, int *type, int *val);
|
||||
extern void ui_button_activate_do(struct bContext *C, struct ARegion *ar, uiBut *but);
|
||||
extern void ui_button_activate_over(struct bContext *C, struct ARegion *ar, uiBut *but);
|
||||
extern void ui_button_execute_begin(struct bContext *C, struct ARegion *ar, uiBut *but, void **active_back);
|
||||
extern void ui_button_execute_end(struct bContext *C, struct ARegion *ar, uiBut *but, void *active_back);
|
||||
extern void ui_button_active_free(const struct bContext *C, uiBut *but);
|
||||
@ -559,6 +560,7 @@ extern bool ui_button_is_active(struct ARegion *ar) ATTR_WARN_UNUSED_RESULT;
|
||||
extern int ui_button_open_menu_direction(uiBut *but);
|
||||
extern void ui_button_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but, const bool restore);
|
||||
extern uiBut *ui_but_find_activated(struct ARegion *ar);
|
||||
bool ui_but_is_editable(const uiBut *but);
|
||||
|
||||
void ui_button_clipboard_free(void);
|
||||
void ui_panel_menu(struct bContext *C, ARegion *ar, Panel *pa);
|
||||
|
@ -2408,6 +2408,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
|
||||
uiBlockSetFlag(block, UI_BLOCK_MOVEMOUSE_QUIT);
|
||||
|
||||
if (pup->popup) {
|
||||
uiBut *but_activate = NULL;
|
||||
uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_NUMSELECT);
|
||||
uiBlockSetDirection(block, direction);
|
||||
|
||||
@ -2421,6 +2422,10 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
|
||||
* block to be under the mouse */
|
||||
offset[0] = -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect));
|
||||
offset[1] = -(bt->rect.ymin + 0.5f * UI_UNIT_Y);
|
||||
|
||||
if (ui_but_is_editable(bt)) {
|
||||
but_activate = bt;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* position mouse at 0.8*width of the button and below the tile
|
||||
@ -2430,6 +2435,20 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
|
||||
offset[0] = min_ii(offset[0], -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect)));
|
||||
|
||||
offset[1] = 2.1 * UI_UNIT_Y;
|
||||
|
||||
for (bt = block->buttons.first; bt; bt = bt->next) {
|
||||
if (ui_but_is_editable(bt)) {
|
||||
but_activate = bt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* in rare cases this is needed since moving the popup
|
||||
* to be within the window bounds may move it away from the mouse,
|
||||
* This ensures we set an item to be active. */
|
||||
if (but_activate) {
|
||||
ui_button_activate_over(C, handle->region, but_activate);
|
||||
}
|
||||
|
||||
block->minbounds = minwidth;
|
||||
|
Loading…
Reference in New Issue
Block a user