diff options
author | Ton Roosendaal <ton@blender.org> | 2009-07-28 20:48:02 +0400 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2009-07-28 20:48:02 +0400 |
commit | 347a1f4376e08ef56d932175669402b3eeb99948 (patch) | |
tree | f73517c70b36dbe346b86ee79b7fee4e82ed64a7 | |
parent | aa44603146e87f29f08cee2abab7e0ddd89222c5 (diff) |
2.5
Keymap feature: RightMouse in pulldown menus allows to assign
a new hotkey.
-rw-r--r-- | source/blender/editors/include/UI_interface.h | 3 | ||||
-rw-r--r-- | source/blender/editors/interface/interface.c | 40 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_handlers.c | 144 | ||||
-rw-r--r-- | source/blender/editors/space_outliner/outliner.c | 3 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 1 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_keymap.c | 75 | ||||
-rw-r--r-- | source/blender/windowmanager/wm_event_types.h | 4 |
7 files changed, 239 insertions, 31 deletions
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 8dc766499bc..d818f298de7 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -206,6 +206,8 @@ typedef struct uiLayout uiLayout; #define HSVCIRCLE (42<<9) #define LISTBOX (43<<9) #define LISTROW (44<<9) +#define HOTKEYEVT (45<<9) + #define BUTTYPE (63<<9) /* Drawing @@ -426,6 +428,7 @@ uiBut *uiDefIconBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, int uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, int icon, char *str, short x1, short y1, short x2, short y2, char *tip); void uiDefKeyevtButS(uiBlock *block, int retval, char *str, short x1, short y1, short x2, short y2, short *spoin, char *tip); +uiBut *uiDefHotKeyevtButS(uiBlock *block, int retval, char *str, short x1, short y1, short x2, short y2, short *keypoin, short *modkeypoin, char *tip); uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxlen, short x1, short y1, short x2, short y2, char *tip); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index ca3be250a92..f6bf8f2cd31 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -739,6 +739,7 @@ static void ui_is_but_sel(uiBut *but) case BUT: push= 2; break; + case HOTKEYEVT: case KEYEVT: push= 2; break; @@ -1846,7 +1847,33 @@ void ui_check_but(uiBut *but) strcat(but->drawstr, WM_key_event_string((short) ui_get_but_val(but))); } break; - + + case HOTKEYEVT: + if (but->flag & UI_SELECT) { + short *sp= (short *)but->func_arg3; + + strcpy(but->drawstr, but->str); + + if(*sp) { + char *str= but->drawstr; + + if(*sp & KM_SHIFT) + str= strcat(str, "Shift "); + if(*sp & KM_CTRL) + str= strcat(str, "Ctrl "); + if(*sp & KM_ALT) + str= strcat(str, "Alt "); + if(*sp & KM_OSKEY) + str= strcat(str, "Cmd "); + } + else + strcat(but->drawstr, "Press a key "); + } else { + /* XXX todo, button currently only used temporarily */ + strcpy(but->drawstr, WM_key_event_string((short) ui_get_but_val(but))); + } + break; + case BUT_TOGDUAL: /* trying to get the dual-icon to left of text... not very nice */ if(but->str[0]) { @@ -2941,6 +2968,17 @@ void uiDefKeyevtButS(uiBlock *block, int retval, char *str, short x1, short y1, ui_check_but(but); } +/* short pointers hardcoded */ +/* modkeypoin will be set to KM_SHIFT, KM_ALT, KM_CTRL, KM_OSKEY bits */ +uiBut *uiDefHotKeyevtButS(uiBlock *block, int retval, char *str, short x1, short y1, short x2, short y2, short *keypoin, short *modkeypoin, char *tip) +{ + uiBut *but= ui_def_but(block, HOTKEYEVT|SHO, retval, str, x1, y1, x2, y2, keypoin, 0.0, 0.0, 0.0, 0.0, tip); + but->func_arg3= modkeypoin; /* XXX hrmf, abuse! */ + ui_check_but(but); + return but; +} + + /* arg is pointer to string/name, use uiButSetSearchFunc() below to make this work */ uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxlen, short x1, short y1, short x2, short y2, char *tip) { diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 0987f0d2f2a..5c3fc890144 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -840,6 +840,9 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut ui_apply_but_CHARTAB(C, but, data); break; #endif + case HOTKEYEVT: + ui_apply_but_BUT(C, but, data); + break; case LINK: case INLINK: ui_apply_but_LINK(C, but, data); @@ -1801,6 +1804,60 @@ static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, wmEv return WM_UI_HANDLER_CONTINUE; } +static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event) +{ + if(data->state == BUTTON_STATE_HIGHLIGHT) { + if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val==KM_PRESS) { + but->drawstr[0]= 0; + button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT); + return WM_UI_HANDLER_BREAK; + } + } + else if(data->state == BUTTON_STATE_WAIT_KEY_EVENT) { + short *sp= (short *)but->func_arg3; + + if(event->type == MOUSEMOVE) + return WM_UI_HANDLER_CONTINUE; + + if(ELEM(event->type, ESCKEY, LEFTMOUSE)) { + /* data->cancel doesnt work, this button opens immediate */ + ui_set_but_val(but, 0); + button_activate_state(C, but, BUTTON_STATE_EXIT); + return WM_UI_HANDLER_BREAK; + } + + /* always set */ + *sp= 0; + if(event->shift) + *sp |= KM_SHIFT; + if(event->alt) + *sp |= KM_ALT; + if(event->ctrl) + *sp |= KM_CTRL; + if(event->oskey) + *sp |= KM_OSKEY; + + ui_check_but(but); + ED_region_tag_redraw(data->region); + + if(event->val==KM_PRESS) { + if(ISHOTKEY(event->type)) { + + if(WM_key_event_string(event->type)[0]) + ui_set_but_val(but, event->type); + else + data->cancel= 1; + + button_activate_state(C, but, BUTTON_STATE_EXIT); + return WM_UI_HANDLER_BREAK; + } + } + } + + return WM_UI_HANDLER_CONTINUE; +} + + static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event) { if(data->state == BUTTON_STATE_HIGHLIGHT) { @@ -3103,6 +3160,67 @@ static int ui_do_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data, wmE return WM_UI_HANDLER_CONTINUE; } +/* callback for hotkey change button/menu */ +static void do_menu_change_hotkey(bContext *C, void *but_v, void *key_v) +{ + uiBut *but= but_v; + IDProperty *prop= (but->opptr)? but->opptr->data: NULL; + short *key= key_v; + char buf[512], *butstr, *cpoin; + + /* signal for escape */ + if(key[0]==0) return; + + WM_key_event_operator_change(C, but->optype->idname, but->opcontext, prop, key[0], key[1]); + + /* complex code to change name of button */ + if(WM_key_event_operator_string(C, but->optype->idname, but->opcontext, prop, buf, sizeof(buf))) { + + butstr= MEM_mallocN(strlen(but->str)+strlen(buf)+2, "menu_block_set_keymaps"); + + /* XXX but->str changed... should not, remove the hotkey from it */ + cpoin= strchr(but->str, '|'); + if(cpoin) *cpoin= 0; + + strcpy(butstr, but->str); + strcat(butstr, "|"); + strcat(butstr, buf); + + but->str= but->strdata; + BLI_strncpy(but->str, butstr, sizeof(but->strdata)); + MEM_freeN(butstr); + + ui_check_but(but); + } + +} + + +static uiBlock *menu_change_hotkey(bContext *C, ARegion *ar, void *arg_but) +{ + uiBlock *block; + uiBut *but= arg_but; + wmOperatorType *ot= WM_operatortype_find(but->optype->idname, 1); + static short dummy[2]; + char buf[OP_MAX_TYPENAME+10]; + + dummy[0]= 0; + dummy[1]= 0; + + block= uiBeginBlock(C, ar, "_popup", UI_EMBOSSP); + uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_MOVEMOUSE_QUIT|UI_BLOCK_RET_1); + + BLI_strncpy(buf, ot->name, OP_MAX_TYPENAME); + strcat(buf, " |"); + + but= uiDefHotKeyevtButS(block, 0, buf, 0, 0, 200, 20, dummy, dummy+1, ""); + uiButSetFunc(but, do_menu_change_hotkey, arg_but, dummy); + + uiPopupBoundsBlock(block, 6.0f, 50, -10); + uiEndBlock(C, block); + + return block; +} static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event) { @@ -3145,9 +3263,22 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event) } /* handle menu */ else if(event->type == RIGHTMOUSE && event->val == KM_PRESS) { - button_timers_tooltip_remove(C, but); - ui_but_anim_menu(C, but); - return WM_UI_HANDLER_BREAK; + /* RMB has two options now */ + if(but->rnapoin.data && but->rnaprop) { + button_timers_tooltip_remove(C, but); + ui_but_anim_menu(C, but); + return WM_UI_HANDLER_BREAK; + } + else if((but->block->flag & UI_BLOCK_LOOP) && but->optype) { + IDProperty *prop= (but->opptr)? but->opptr->data: NULL; + char buf[512]; + + if(WM_key_event_operator_string(C, but->optype->idname, but->opcontext, prop, buf, sizeof(buf))) { + + uiPupBlock(C, menu_change_hotkey, but); + + } + } } } @@ -3176,6 +3307,9 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event) case KEYEVT: retval= ui_do_but_KEYEVT(C, but, data, event); break; + case HOTKEYEVT: + retval= ui_do_but_HOTKEYEVT(C, but, data, event); + break; case TOGBUT: case TOG: case TOGR: @@ -3521,6 +3655,10 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA } button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT); + /* activate right away */ + if(but->type==HOTKEYEVT) + button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT); + if(type == BUTTON_ACTIVATE_OPEN) { button_activate_state(C, but, BUTTON_STATE_MENU_OPEN); diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c index 21ba9cfa707..b05d9637a69 100644 --- a/source/blender/editors/space_outliner/outliner.c +++ b/source/blender/editors/space_outliner/outliner.c @@ -1132,8 +1132,9 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i te->name= km->nameid; if(!(tselem->flag & TSE_CLOSED)) { + a= 0; - for (kmi= km->keymap.first; kmi; kmi= kmi->next) { + for (kmi= km->keymap.first; kmi; kmi= kmi->next, a++) { const char *key= WM_key_event_string(kmi->type); if(key[0]) { diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 36c78d17ab3..7d3dd478178 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -100,6 +100,7 @@ int WM_key_event_is_tweak(short type); const char *WM_key_event_string(short type); char *WM_key_event_operator_string(const struct bContext *C, const char *opname, int opcontext, struct IDProperty *properties, char *str, int len); +void WM_key_event_operator_change(const bContext *C, const char *opname, int opcontext, struct IDProperty *properties, short key, short modifier); /* handlers */ diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 1d959665f40..ad0dd786791 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -65,6 +65,8 @@ static void keymap_event_set(wmKeymapItem *kmi, short type, short val, int modif } else { + kmi->shift= kmi->ctrl= kmi->alt= kmi->oskey= 0; + /* defines? */ if(modifier & KM_SHIFT) kmi->shift= 1; @@ -232,7 +234,7 @@ static char *wm_keymap_item_to_string(wmKeymapItem *kmi, char *str, int len) strcat(buf, "Alt "); if(kmi->oskey) - strcat(buf, "OS "); + strcat(buf, "Cmd "); strcat(buf, WM_key_event_string(kmi->type)); BLI_strncpy(str, buf, len); @@ -240,7 +242,7 @@ static char *wm_keymap_item_to_string(wmKeymapItem *kmi, char *str, int len) return str; } -static char *wm_keymap_item_find(ListBase *handlers, const char *opname, int opcontext, IDProperty *properties, char *str, int len) +static wmKeymapItem *wm_keymap_item_find_handlers(ListBase *handlers, const char *opname, int opcontext, IDProperty *properties) { wmEventHandler *handler; wmKeymapItem *kmi; @@ -251,45 +253,66 @@ static char *wm_keymap_item_find(ListBase *handlers, const char *opname, int opc for(kmi=handler->keymap->first; kmi; kmi=kmi->next) if(strcmp(kmi->idname, opname) == 0 && WM_key_event_string(kmi->type)[0]) if(kmi->ptr && IDP_EqualsProperties(properties, kmi->ptr->data)) - return wm_keymap_item_to_string(kmi, str, len); + return kmi; return NULL; } -char *WM_key_event_operator_string(const bContext *C, const char *opname, int opcontext, IDProperty *properties, char *str, int len) +static wmKeymapItem *wm_keymap_item_find(const bContext *C, const char *opname, int opcontext, IDProperty *properties) { - char *found= NULL; + wmKeymapItem *found= NULL; /* look into multiple handler lists to find the item */ if(CTX_wm_window(C)) - if((found= wm_keymap_item_find(&CTX_wm_window(C)->handlers, opname, opcontext, properties, str, len))) - return found; - - if(CTX_wm_area(C)) - if((found= wm_keymap_item_find(&CTX_wm_area(C)->handlers, opname, opcontext, properties, str, len))) - return found; - - if(ELEM(opcontext, WM_OP_EXEC_REGION_WIN, WM_OP_INVOKE_REGION_WIN)) { - if(CTX_wm_area(C)) { - ARegion *ar= CTX_wm_area(C)->regionbase.first; - for(; ar; ar= ar->next) - if(ar->regiontype==RGN_TYPE_WINDOW) - break; - - if(ar) - if((found= wm_keymap_item_find(&ar->handlers, opname, opcontext, properties, str, len))) - return found; + found= wm_keymap_item_find_handlers(&CTX_wm_window(C)->handlers, opname, opcontext, properties); + + + if(CTX_wm_area(C) && found==NULL) + found= wm_keymap_item_find_handlers(&CTX_wm_area(C)->handlers, opname, opcontext, properties); + + if(found==NULL) { + if(ELEM(opcontext, WM_OP_EXEC_REGION_WIN, WM_OP_INVOKE_REGION_WIN)) { + if(CTX_wm_area(C)) { + ARegion *ar= CTX_wm_area(C)->regionbase.first; + for(; ar; ar= ar->next) + if(ar->regiontype==RGN_TYPE_WINDOW) + break; + + if(ar) + found= wm_keymap_item_find_handlers(&ar->handlers, opname, opcontext, properties); + } + } + else { + if(CTX_wm_region(C)) + found= wm_keymap_item_find_handlers(&CTX_wm_region(C)->handlers, opname, opcontext, properties); } } - else { - if(CTX_wm_region(C)) - if((found= wm_keymap_item_find(&CTX_wm_region(C)->handlers, opname, opcontext, properties, str, len))) - return found; + + return found; +} + +char *WM_key_event_operator_string(const bContext *C, const char *opname, int opcontext, IDProperty *properties, char *str, int len) +{ + wmKeymapItem *found= wm_keymap_item_find(C, opname, opcontext, properties); + + if(found) { + wm_keymap_item_to_string(found, str, len); + return str; } return NULL; } +/* searches context and changes keymap item, if found */ +void WM_key_event_operator_change(const bContext *C, const char *opname, int opcontext, IDProperty *properties, short key, short modifier) +{ + wmKeymapItem *found= wm_keymap_item_find(C, opname, opcontext, properties); + + if(found) { + keymap_event_set(found, key, KM_PRESS, modifier, 0); + } +} + /* ********************* */ int WM_key_event_is_tweak(short type) diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index 6e7186542de..ee18a0fb45b 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -196,6 +196,10 @@ /* only used for KM_TEXTINPUT, so assume that we want all user-inputtable ascii codes included */ #define ISKEYBOARD(event) (event >=' ' && event <=255) +/* test whether event type is acceptable as hotkey, excluding modifiers */ +#define ISHOTKEY(event) (event >=' ' && event <=320 && !(event>=LEFTCTRLKEY && event<=ESCKEY) && !(event>=UNKNOWNKEY && event<=GRLESSKEY)) + + /* **************** BLENDER GESTURE EVENTS ********************* */ #define EVT_ACTIONZONE_AREA 0x5000 |