From c1c3d66079adb2e0ea7b7eb9bdb2997f37623591 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 24 Nov 2011 13:51:31 +0000 Subject: [PATCH] Fix #29306: Alt+N, Enter In Image View Does closes the dialog without executing. If enter is pressed outside of any button in menu, generate two menu return values: - UI_RETURN_CANCEL so button wouldn't be executed - UI_RETURN_POPUP_OK so callback associated with popup block would be executed --- source/blender/editors/include/UI_interface.h | 51 ++++++++++--------- .../editors/interface/interface_handlers.c | 18 +++---- .../editors/interface/interface_regions.c | 4 +- .../windowmanager/intern/wm_operators.c | 13 ++++- 4 files changed, 48 insertions(+), 38 deletions(-) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index ec6958c8415..d1f11d60999 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -122,6 +122,7 @@ typedef struct uiLayout uiLayout; #define UI_RETURN_OK 2 /* choice made */ #define UI_RETURN_OUT 4 /* left the menu */ #define UI_RETURN_UPDATE 8 /* update the button that opened */ +#define UI_RETURN_POPUP_OK 16 /* popup is ok to be handled */ /* block->flag bits 12-15 are identical to but->flag bits */ @@ -278,6 +279,30 @@ void uiDrawBoxVerticalShade(int mode, float minx, float miny, float maxx, float #define UI_SCROLL_NO_OUTLINE 4 void uiWidgetScrollDraw(struct uiWidgetColors *wcol, struct rcti *rect, struct rcti *slider, int state); +/* Callbacks + * + * uiBlockSetHandleFunc/ButmFunc are for handling events through a callback. + * HandleFunc gets the retval passed on, and ButmFunc gets a2. The latter is + * mostly for compatibility with older code. + * + * uiButSetCompleteFunc is for tab completion. + * + * uiButSearchFunc is for name buttons, showing a popup with matches + * + * uiBlockSetFunc and uiButSetFunc are callbacks run when a button is used, + * in case events, operators or RNA are not sufficient to handle the button. + * + * uiButSetNFunc will free the argument with MEM_freeN. */ + +typedef struct uiSearchItems uiSearchItems; + +typedef void (*uiButHandleFunc)(struct bContext *C, void *arg1, void *arg2); +typedef void (*uiButHandleRenameFunc)(struct bContext *C, void *arg, char *origstr); +typedef void (*uiButHandleNFunc)(struct bContext *C, void *argN, void *arg2); +typedef void (*uiButCompleteFunc)(struct bContext *C, char *str, void *arg); +typedef void (*uiButSearchFunc)(const struct bContext *C, void *arg, const char *str, uiSearchItems *items); +typedef void (*uiBlockHandleFunc)(struct bContext *C, void *arg, int event); + /* Menu Callbacks */ typedef void (*uiMenuCreateFunc)(struct bContext *C, struct uiLayout *layout, void *arg1); @@ -313,7 +338,7 @@ typedef void (*uiBlockCancelFunc)(void *arg1); void uiPupBlock(struct bContext *C, uiBlockCreateFunc func, void *arg); void uiPupBlockO(struct bContext *C, uiBlockCreateFunc func, void *arg, const char *opname, int opcontext); -void uiPupBlockEx(struct bContext *C, uiBlockCreateFunc func, uiBlockCancelFunc cancel_func, void *arg); +void uiPupBlockEx(struct bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg); /* void uiPupBlockOperator(struct bContext *C, uiBlockCreateFunc func, struct wmOperator *op, int opcontext); */ /* UNUSED */ void uiPupBlockClose(struct bContext *C, uiBlock *block); @@ -529,30 +554,6 @@ void uiSetButLink(struct uiBut *but, void **poin, void ***ppoin, short *tot, void uiComposeLinks(uiBlock *block); uiBut *uiFindInlink(uiBlock *block, void *poin); -/* Callbacks - * - * uiBlockSetHandleFunc/ButmFunc are for handling events through a callback. - * HandleFunc gets the retval passed on, and ButmFunc gets a2. The latter is - * mostly for compatibility with older code. - * - * uiButSetCompleteFunc is for tab completion. - * - * uiButSearchFunc is for name buttons, showing a popup with matches - * - * uiBlockSetFunc and uiButSetFunc are callbacks run when a button is used, - * in case events, operators or RNA are not sufficient to handle the button. - * - * uiButSetNFunc will free the argument with MEM_freeN. */ - -typedef struct uiSearchItems uiSearchItems; - -typedef void (*uiButHandleFunc)(struct bContext *C, void *arg1, void *arg2); -typedef void (*uiButHandleRenameFunc)(struct bContext *C, void *arg, char *origstr); -typedef void (*uiButHandleNFunc)(struct bContext *C, void *argN, void *arg2); -typedef void (*uiButCompleteFunc)(struct bContext *C, char *str, void *arg); -typedef void (*uiButSearchFunc)(const struct bContext *C, void *arg, const char *str, uiSearchItems *items); -typedef void (*uiBlockHandleFunc)(struct bContext *C, void *arg, int event); - /* use inside searchfunc to add items */ int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int iconid); /* bfunc gets search item *poin as arg2, or if NULL the old string */ diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 1ba6acf367a..a0b0d34ab44 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -5861,14 +5861,14 @@ static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut * menu= data->menu; /* copy over return values from the closing menu */ - if(menu->menuretval == UI_RETURN_OK || menu->menuretval == UI_RETURN_UPDATE) { + if((menu->menuretval & UI_RETURN_OK) || (menu->menuretval & UI_RETURN_UPDATE)) { if(but->type == COL) copy_v3_v3(data->vec, menu->retvec); else if(ELEM3(but->type, MENU, ICONROW, ICONTEXTROW)) data->value= menu->retvalue; } - if(menu->menuretval == UI_RETURN_UPDATE) { + if(menu->menuretval & UI_RETURN_UPDATE) { if(data->interactive) ui_apply_button(C, but->block, but, data, 1); else ui_check_but(but); @@ -5876,13 +5876,13 @@ static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut * } /* now change button state or exit, which will close the submenu */ - if(ELEM(menu->menuretval, UI_RETURN_OK, UI_RETURN_CANCEL)) { + if((menu->menuretval & UI_RETURN_OK) || (menu->menuretval & UI_RETURN_CANCEL)) { if(menu->menuretval != UI_RETURN_OK) data->cancel= 1; button_activate_exit(C, data, but, 1, 0); } - else if(menu->menuretval == UI_RETURN_OUT) { + else if(menu->menuretval & UI_RETURN_OUT) { if(event->type==MOUSEMOVE && ui_mouse_inside_button(data->region, but, event->x, event->y)) { button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT); } @@ -6330,7 +6330,7 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle /* enter will always close this block, we let the event * get handled by the button if it is activated, otherwise we cancel */ if(!ui_but_find_activated(ar)) - menu->menuretval= UI_RETURN_CANCEL; + menu->menuretval= UI_RETURN_CANCEL | UI_RETURN_POPUP_OK; } else { ui_mouse_motion_towards_check(block, menu, mx, my); @@ -6370,7 +6370,7 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle * buttons inside this region. disabled inside check .. not sure * anymore why it was there? but it meant enter didn't work * for example when mouse was not over submenu */ - if((/*inside &&*/ (!menu->menuretval || menu->menuretval == UI_RETURN_UPDATE) && retval == WM_UI_HANDLER_CONTINUE) || event->type == TIMER) { + if((/*inside &&*/ (!menu->menuretval || (menu->menuretval & UI_RETURN_UPDATE)) && retval == WM_UI_HANDLER_CONTINUE) || event->type == TIMER) { but= ui_but_find_activated(ar); if(but) { @@ -6419,14 +6419,14 @@ static int ui_handle_menu_return_submenu(bContext *C, wmEvent *event, uiPopupBlo if(submenu->menuretval) { /* first decide if we want to close our own menu cascading, if * so pass on the sub menu return value to our own menu handle */ - if(ELEM(submenu->menuretval, UI_RETURN_OK, UI_RETURN_CANCEL)) { + if((submenu->menuretval & UI_RETURN_OK) || (submenu->menuretval & UI_RETURN_CANCEL)) { if(!(block->flag & UI_BLOCK_KEEP_OPEN)) { menu->menuretval= submenu->menuretval; menu->butretval= data->retval; } } - update= (submenu->menuretval == UI_RETURN_UPDATE); + update= (submenu->menuretval & UI_RETURN_UPDATE); /* now let activated button in this menu exit, which * will actually close the submenu too */ @@ -6599,7 +6599,7 @@ static int ui_handler_popup(bContext *C, wmEvent *event, void *userdata) ui_popup_block_free(C, menu); UI_remove_popup_handlers(&CTX_wm_window(C)->modalhandlers, menu); - if(temp.menuretval == UI_RETURN_OK) { + if((temp.menuretval & UI_RETURN_OK) || (temp.menuretval & UI_RETURN_POPUP_OK)) { if(temp.popup_func) temp.popup_func(C, temp.popup_arg, temp.retvalue); if(temp.optype) diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index d117a7f4e6e..58c3c0130b8 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -2603,7 +2603,7 @@ void uiPupBlock(bContext *C, uiBlockCreateFunc func, void *arg) uiPupBlockO(C, func, arg, NULL, 0); } -void uiPupBlockEx(bContext *C, uiBlockCreateFunc func, uiBlockCancelFunc cancel_func, void *arg) +void uiPupBlockEx(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg) { wmWindow *window= CTX_wm_window(C); uiPopupBlockHandle *handle; @@ -2613,7 +2613,7 @@ void uiPupBlockEx(bContext *C, uiBlockCreateFunc func, uiBlockCancelFunc cancel_ handle->retvalue= 1; handle->popup_arg= arg; - // handle->popup_func= operator_cb; + handle->popup_func= popup_func; handle->cancel_func= cancel_func; // handle->opcontext= opcontext; diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 0c538865501..26f59189e47 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1072,6 +1072,15 @@ static void wm_operator_ui_popup_cancel(void *userData) MEM_freeN(data); } +static void wm_operator_ui_popup_ok(struct bContext *C, void *arg, int retval) +{ + wmOpPopUp *data= arg; + wmOperator *op= data->op; + + if(op && retval > 0) + WM_operator_call(C, op); +} + int WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height) { wmOpPopUp *data= MEM_callocN(sizeof(wmOpPopUp), "WM_operator_ui_popup"); @@ -1079,7 +1088,7 @@ int WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height) data->width= width; data->height= height; data->free_op= TRUE; /* if this runs and gets registered we may want not to free it */ - uiPupBlockEx(C, wm_operator_ui_create, wm_operator_ui_popup_cancel, data); + uiPupBlockEx(C, wm_operator_ui_create, NULL, wm_operator_ui_popup_cancel, data); return OPERATOR_RUNNING_MODAL; } @@ -1110,7 +1119,7 @@ int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width, int h data->free_op= TRUE; /* if this runs and gets registered we may want not to free it */ /* op is not executed until popup OK but is clicked */ - uiPupBlockEx(C, wm_block_dialog_create, wm_operator_ui_popup_cancel, data); + uiPupBlockEx(C, wm_block_dialog_create, wm_operator_ui_popup_ok, wm_operator_ui_popup_cancel, data); return OPERATOR_RUNNING_MODAL; }