Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTon Roosendaal <ton@blender.org>2009-07-28 20:48:02 +0400
committerTon Roosendaal <ton@blender.org>2009-07-28 20:48:02 +0400
commit347a1f4376e08ef56d932175669402b3eeb99948 (patch)
treef73517c70b36dbe346b86ee79b7fee4e82ed64a7
parentaa44603146e87f29f08cee2abab7e0ddd89222c5 (diff)
2.5
Keymap feature: RightMouse in pulldown menus allows to assign a new hotkey.
-rw-r--r--source/blender/editors/include/UI_interface.h3
-rw-r--r--source/blender/editors/interface/interface.c40
-rw-r--r--source/blender/editors/interface/interface_handlers.c144
-rw-r--r--source/blender/editors/space_outliner/outliner.c3
-rw-r--r--source/blender/windowmanager/WM_api.h1
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c75
-rw-r--r--source/blender/windowmanager/wm_event_types.h4
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