=== Better support for user defined modal keymaps ===

Fixing/Missing RNA properties:
- "virtual" property for "ANY" modifier for keymapitem
- modal property for keymap
- Look up modal_items in usermaps too

Lazy init usermaps needs to init modal_items too.

New function to initialize a user keymap (fill in modal_item and poll pointers).

Operator modal keymaps now look up if there's a user defined keymap that overwrites it.

Full Event UI buttons now show "Any" when modifier is set to that (instead of listing all of them).

Note: Having the modifiers as boolean still doesn't express the full breath of values possible for them. There is commented code in this commit to represent them as enum, which would solve this, but make the keymap editor more cryptic.
This commit is contained in:
Martin Poirier 2009-11-15 19:25:34 +00:00
parent 6ea605797c
commit 11cfdfa264
5 changed files with 137 additions and 19 deletions

@ -1197,7 +1197,11 @@ class USERPREF_PT_input(bpy.types.Panel):
itemcol = itemrow.column() itemcol = itemrow.column()
itemcol.active = kmi.active itemcol.active = kmi.active
row = itemcol.row() row = itemcol.row()
row.itemR(kmi, "idname", text="")
if km.modal:
row.itemR(kmi, "propvalue", text="")
else:
row.itemR(kmi, "idname", text="")
sub = row.row() sub = row.row()
sub.scale_x = 0.6 sub.scale_x = 0.6
@ -1233,6 +1237,7 @@ class USERPREF_PT_input(bpy.types.Panel):
subrow = sub.row() subrow = sub.row()
subrow.scale_x = 0.75 subrow.scale_x = 0.75
subrow.itemR(kmi, "any")
subrow.itemR(kmi, "shift") subrow.itemR(kmi, "shift")
subrow.itemR(kmi, "ctrl") subrow.itemR(kmi, "ctrl")
subrow.itemR(kmi, "alt") subrow.itemR(kmi, "alt")

@ -234,6 +234,13 @@ EnumPropertyItem keymap_propvalue_items[] = {
{0, "NONE", 0, "", ""}, {0, "NONE", 0, "", ""},
{0, NULL, 0, NULL, NULL}}; {0, NULL, 0, NULL, NULL}};
EnumPropertyItem keymap_modifiers_items[] = {
{KM_ANY, "ANY", 0, "Any", ""},
{0, "NONE", 0, "None", ""},
{1, "FIRST", 0, "First", ""},
{2, "SECOND", 0, "Second", ""},
{0, NULL, 0, NULL, NULL}};
#define KMI_TYPE_KEYBOARD 0 #define KMI_TYPE_KEYBOARD 0
#define KMI_TYPE_MOUSE 1 #define KMI_TYPE_MOUSE 1
#define KMI_TYPE_TWEAK 2 #define KMI_TYPE_TWEAK 2
@ -411,10 +418,25 @@ static EnumPropertyItem *rna_KeyMapItem_propvalue_itemf(bContext *C, PointerRNA
{ {
wmWindowManager *wm = CTX_wm_manager(C); wmWindowManager *wm = CTX_wm_manager(C);
wmKeyConfig *kc; wmKeyConfig *kc;
wmKeyMap *km;
/* check user keymaps */
for(km=U.keymaps.first; km; km=km->next) {
wmKeyMapItem *ki;
for (ki=km->items.first; ki; ki=ki->next) {
if (ki == ptr->data) {
if (!km->modal_items) {
if (!WM_keymap_user_init(wm, km)) {
return keymap_propvalue_items; /* ERROR */
}
}
return km->modal_items;
}
}
}
for(kc=wm->keyconfigs.first; kc; kc=kc->next) { for(kc=wm->keyconfigs.first; kc; kc=kc->next) {
wmKeyMap *km;
for(km=kc->keymaps.first; km; km=km->next) { for(km=kc->keymaps.first; km; km=km->next) {
/* only check if it's a modal keymap */ /* only check if it's a modal keymap */
if (km->modal_items) { if (km->modal_items) {
@ -428,9 +450,37 @@ static EnumPropertyItem *rna_KeyMapItem_propvalue_itemf(bContext *C, PointerRNA
} }
} }
return keymap_propvalue_items;
return keymap_propvalue_items; /* ERROR */
} }
static int rna_KeyMapItem_any_getf(PointerRNA *ptr)
{
wmKeyMapItem *kmi = (wmKeyMapItem*)ptr->data;
if (kmi->shift == KM_ANY &&
kmi->ctrl == KM_ANY &&
kmi->alt == KM_ANY &&
kmi->oskey == KM_ANY)
return 1;
else
return 0;
}
static void rna_KeyMapItem_any_setf(PointerRNA *ptr, int value)
{
wmKeyMapItem *kmi = (wmKeyMapItem*)ptr->data;
if(value) {
kmi->shift= kmi->ctrl= kmi->alt= kmi->oskey= KM_ANY;
}
else {
kmi->shift= kmi->ctrl= kmi->alt= kmi->oskey= 0;
}
}
static PointerRNA rna_WindowManager_active_keyconfig_get(PointerRNA *ptr) static PointerRNA rna_WindowManager_active_keyconfig_get(PointerRNA *ptr)
{ {
wmWindowManager *wm= ptr->data; wmWindowManager *wm= ptr->data;
@ -762,6 +812,10 @@ static void rna_def_keyconfig(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", KEYMAP_USER); RNA_def_property_boolean_sdna(prop, NULL, "flag", KEYMAP_USER);
RNA_def_property_ui_text(prop, "User Defined", "Keymap is defined by the user."); RNA_def_property_ui_text(prop, "User Defined", "Keymap is defined by the user.");
prop= RNA_def_property(srna, "modal", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", KEYMAP_MODAL);
RNA_def_property_ui_text(prop, "Modal Keymap", "Indicates that a keymap is used for translate modal events for an operator.");
RNA_api_keymap(srna); RNA_api_keymap(srna);
/* KeyMapItem */ /* KeyMapItem */
@ -798,20 +852,32 @@ static void rna_def_keyconfig(BlenderRNA *brna)
RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_KeyMapItem_value_itemf"); RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_KeyMapItem_value_itemf");
RNA_def_property_ui_text(prop, "Value", ""); RNA_def_property_ui_text(prop, "Value", "");
prop= RNA_def_property(srna, "any", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_KeyMapItem_any_getf", "rna_KeyMapItem_any_setf");
RNA_def_property_ui_text(prop, "Any", "Any modifier keys pressed.");
prop= RNA_def_property(srna, "shift", PROP_BOOLEAN, PROP_NONE); prop= RNA_def_property(srna, "shift", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "shift", 0); RNA_def_property_boolean_sdna(prop, NULL, "shift", 0);
// RNA_def_property_enum_sdna(prop, NULL, "shift");
// RNA_def_property_enum_items(prop, keymap_modifiers_items);
RNA_def_property_ui_text(prop, "Shift", "Shift key pressed."); RNA_def_property_ui_text(prop, "Shift", "Shift key pressed.");
prop= RNA_def_property(srna, "ctrl", PROP_BOOLEAN, PROP_NONE); prop= RNA_def_property(srna, "ctrl", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "ctrl", 0); RNA_def_property_boolean_sdna(prop, NULL, "ctrl", 0);
// RNA_def_property_enum_sdna(prop, NULL, "ctrl");
// RNA_def_property_enum_items(prop, keymap_modifiers_items);
RNA_def_property_ui_text(prop, "Ctrl", "Control key pressed."); RNA_def_property_ui_text(prop, "Ctrl", "Control key pressed.");
prop= RNA_def_property(srna, "alt", PROP_BOOLEAN, PROP_NONE); prop= RNA_def_property(srna, "alt", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "alt", 0); RNA_def_property_boolean_sdna(prop, NULL, "alt", 0);
// RNA_def_property_enum_sdna(prop, NULL, "alt");
// RNA_def_property_enum_items(prop, keymap_modifiers_items);
RNA_def_property_ui_text(prop, "Alt", "Alt key pressed."); RNA_def_property_ui_text(prop, "Alt", "Alt key pressed.");
prop= RNA_def_property(srna, "oskey", PROP_BOOLEAN, PROP_NONE); prop= RNA_def_property(srna, "oskey", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "oskey", 0); RNA_def_property_boolean_sdna(prop, NULL, "oskey", 0);
// RNA_def_property_enum_sdna(prop, NULL, "oskey");
// RNA_def_property_enum_items(prop, keymap_modifiers_items);
RNA_def_property_ui_text(prop, "OS Key", "Operating system key pressed."); RNA_def_property_ui_text(prop, "OS Key", "Operating system key pressed.");
prop= RNA_def_property(srna, "key_modifier", PROP_ENUM, PROP_NONE); prop= RNA_def_property(srna, "key_modifier", PROP_ENUM, PROP_NONE);

@ -105,6 +105,7 @@ char *WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len);
wmKeyMap *WM_keymap_find(struct wmKeyConfig *keyconf, char *idname, int spaceid, int regionid); wmKeyMap *WM_keymap_find(struct wmKeyConfig *keyconf, char *idname, int spaceid, int regionid);
wmKeyMap *WM_keymap_active(struct wmWindowManager *wm, struct wmKeyMap *keymap); wmKeyMap *WM_keymap_active(struct wmWindowManager *wm, struct wmKeyMap *keymap);
int WM_keymap_user_init(struct wmWindowManager *wm, struct wmKeyMap *keymap);
wmKeyMap *WM_keymap_copy_to_user(struct wmKeyMap *keymap); wmKeyMap *WM_keymap_copy_to_user(struct wmKeyMap *keymap);
void WM_keymap_restore_to_default(struct wmKeyMap *keymap); void WM_keymap_restore_to_default(struct wmKeyMap *keymap);

@ -805,12 +805,13 @@ static int wm_event_always_pass(wmEvent *event)
} }
/* operator exists */ /* operator exists */
static void wm_event_modalkeymap(wmOperator *op, wmEvent *event) static void wm_event_modalkeymap(const bContext *C, wmOperator *op, wmEvent *event)
{ {
if(op->type->modalkeymap) { if(op->type->modalkeymap) {
wmKeyMap *keymap= WM_keymap_active(CTX_wm_manager(C), op->type->modalkeymap);
wmKeyMapItem *kmi; wmKeyMapItem *kmi;
for(kmi= op->type->modalkeymap->items.first; kmi; kmi= kmi->next) { for(kmi= keymap->items.first; kmi; kmi= kmi->next) {
if(wm_eventmatch(event, kmi)) { if(wm_eventmatch(event, kmi)) {
event->type= EVT_MODAL_MAP; event->type= EVT_MODAL_MAP;
@ -837,7 +838,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
wm_handler_op_context(C, handler); wm_handler_op_context(C, handler);
wm_region_mouse_co(C, event); wm_region_mouse_co(C, event);
wm_event_modalkeymap(op, event); wm_event_modalkeymap(C, op, event);
retval= ot->modal(C, op, event); retval= ot->modal(C, op, event);

@ -88,9 +88,14 @@ void WM_keyconfig_userdef(wmWindowManager *wm)
wmKeyMap *km; wmKeyMap *km;
wmKeyMapItem *kmi; wmKeyMapItem *kmi;
for(km=U.keymaps.first; km; km=km->next) for(km=U.keymaps.first; km; km=km->next) {
for(kmi=km->items.first; kmi; kmi=kmi->next) /* modal keymaps don't have operator properties */
keymap_properties_set(kmi); if ((km->flag & KEYMAP_MODAL) == 0) {
for(kmi=km->items.first; kmi; kmi=kmi->next) {
keymap_properties_set(kmi);
}
}
}
} }
static wmKeyConfig *wm_keyconfig_list_find(ListBase *lb, char *idname) static wmKeyConfig *wm_keyconfig_list_find(ListBase *lb, char *idname)
@ -295,17 +300,25 @@ char *WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len)
buf[0]= 0; buf[0]= 0;
if(kmi->shift) if (kmi->shift == KM_ANY &&
strcat(buf, "Shift "); kmi->ctrl == KM_ANY &&
kmi->alt == KM_ANY &&
kmi->oskey == KM_ANY) {
if(kmi->ctrl) strcat(buf, "Any ");
strcat(buf, "Ctrl "); } else {
if(kmi->shift)
strcat(buf, "Shift ");
if(kmi->alt) if(kmi->ctrl)
strcat(buf, "Alt "); strcat(buf, "Ctrl ");
if(kmi->oskey) if(kmi->alt)
strcat(buf, "Cmd "); strcat(buf, "Alt ");
if(kmi->oskey)
strcat(buf, "Cmd ");
}
if(kmi->keymodifier) { if(kmi->keymodifier) {
strcat(buf, WM_key_event_string(kmi->keymodifier)); strcat(buf, WM_key_event_string(kmi->keymodifier));
@ -410,6 +423,36 @@ char *WM_key_event_operator_string(const bContext *C, const char *opname, int op
/* ***************** user preferences ******************* */ /* ***************** user preferences ******************* */
int WM_keymap_user_init(wmWindowManager *wm, wmKeyMap *keymap)
{
wmKeyConfig *keyconf;
wmKeyMap *km;
if(!keymap)
return 0;
/* init from user key config */
keyconf= wm_keyconfig_list_find(&wm->keyconfigs, U.keyconfigstr);
if(keyconf) {
km= wm_keymap_list_find(&keyconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
if(km) {
keymap->poll= km->poll; /* lazy init */
keymap->modal_items= km->modal_items;
return 1;
}
}
/* or from default */
km= wm_keymap_list_find(&wm->defaultconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
if(km) {
keymap->poll= km->poll; /* lazy init */
keymap->modal_items= km->modal_items;
return 1;
}
return 0;
}
wmKeyMap *WM_keymap_active(wmWindowManager *wm, wmKeyMap *keymap) wmKeyMap *WM_keymap_active(wmWindowManager *wm, wmKeyMap *keymap)
{ {
wmKeyConfig *keyconf; wmKeyConfig *keyconf;
@ -422,6 +465,7 @@ wmKeyMap *WM_keymap_active(wmWindowManager *wm, wmKeyMap *keymap)
km= wm_keymap_list_find(&U.keymaps, keymap->idname, keymap->spaceid, keymap->regionid); km= wm_keymap_list_find(&U.keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
if(km) { if(km) {
km->poll= keymap->poll; /* lazy init */ km->poll= keymap->poll; /* lazy init */
km->modal_items= keymap->modal_items;
return km; return km;
} }
@ -431,6 +475,7 @@ wmKeyMap *WM_keymap_active(wmWindowManager *wm, wmKeyMap *keymap)
km= wm_keymap_list_find(&keyconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); km= wm_keymap_list_find(&keyconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
if(km) { if(km) {
km->poll= keymap->poll; /* lazy init */ km->poll= keymap->poll; /* lazy init */
km->modal_items= keymap->modal_items;
return km; return km;
} }
} }