WM: expose the "any" state of KeyMapItem modifiers

Change KeyMapItem.alt/ctrl/shift/oskey to integer types,
where -1 is used to ignore the modifier when matching key-map items.

It was only possible to set all modifiers to -1 at once from RNA
using the 'any' property.
Afterwards individual modifiers could be set back to true/false.
Although these key-map items could not be exported/imported.

Exposing the values directly avoids the need for cumbersome workarounds.
This commit is contained in:
Campbell Barton 2021-09-16 23:20:57 +10:00
parent 6dca61b91c
commit 06ac655b8d
7 changed files with 132 additions and 90 deletions

View File

@ -63,16 +63,11 @@ def kmi_args_as_data(kmi):
if kmi.any:
s.append("\"any\": True")
else:
if kmi.shift:
s.append("\"shift\": True")
if kmi.ctrl:
s.append("\"ctrl\": True")
if kmi.alt:
s.append("\"alt\": True")
if kmi.oskey:
s.append("\"oskey\": True")
if kmi.key_modifier and kmi.key_modifier != 'NONE':
s.append(f"\"key_modifier\": '{kmi.key_modifier}'")
for attr in ("shift", "ctrl", "alt", "oskey"):
if mod := getattr(kmi, attr):
s.append(f"\"{attr:s}\": " + ("-1" if mod == -1 else "True"))
if (mod := kmi.key_modifier) and (mod != 'NONE'):
s.append(f"\"key_modifier\": '{mod:s}'")
if kmi.repeat:
if (

View File

@ -199,10 +199,12 @@ def draw_kmi(display_keymaps, kc, km, kmi, layout, level):
subrow = sub.row()
subrow.scale_x = 0.75
subrow.prop(kmi, "any", toggle=True)
subrow.prop(kmi, "shift", toggle=True)
subrow.prop(kmi, "ctrl", toggle=True)
subrow.prop(kmi, "alt", toggle=True)
subrow.prop(kmi, "oskey", text="Cmd", toggle=True)
# Use `*_ui` properties as integers aren't practical.
subrow.prop(kmi, "shift_ui", toggle=True)
subrow.prop(kmi, "ctrl_ui", toggle=True)
subrow.prop(kmi, "alt_ui", toggle=True)
subrow.prop(kmi, "oskey_ui", text="Cmd", toggle=True)
subrow.prop(kmi, "key_modifier", text="", event=True)
# Operator properties

View File

@ -921,10 +921,10 @@ static void ui_keymap_but_cb(bContext *UNUSED(C), void *but_v, void *UNUSED(key_
{
uiBut *but = but_v;
RNA_boolean_set(&but->rnapoin, "shift", (but->modifier_key & KM_SHIFT) != 0);
RNA_boolean_set(&but->rnapoin, "ctrl", (but->modifier_key & KM_CTRL) != 0);
RNA_boolean_set(&but->rnapoin, "alt", (but->modifier_key & KM_ALT) != 0);
RNA_boolean_set(&but->rnapoin, "oskey", (but->modifier_key & KM_OSKEY) != 0);
RNA_int_set(&but->rnapoin, "shift", (but->modifier_key & KM_SHIFT) ? KM_MOD_HELD : KM_NOTHING);
RNA_int_set(&but->rnapoin, "ctrl", (but->modifier_key & KM_CTRL) ? KM_MOD_HELD : KM_NOTHING);
RNA_int_set(&but->rnapoin, "alt", (but->modifier_key & KM_ALT) ? KM_MOD_HELD : KM_NOTHING);
RNA_int_set(&but->rnapoin, "oskey", (but->modifier_key & KM_OSKEY) ? KM_MOD_HELD : KM_NOTHING);
}
/**

View File

@ -440,8 +440,7 @@ const EnumPropertyItem rna_enum_event_type_mask_items[] = {
static const EnumPropertyItem keymap_modifiers_items[] = {
{KM_ANY, "ANY", 0, "Any", ""},
{0, "NONE", 0, "None", ""},
{1, "FIRST", 0, "First", ""},
{2, "SECOND", 0, "Second", ""},
{KM_MOD_HELD, "HELD", 0, "Held", ""},
{0, NULL, 0, NULL, NULL},
};
#endif
@ -2732,38 +2731,62 @@ static void rna_def_keyconfig(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Any", "Any modifier keys pressed");
RNA_def_property_update(prop, 0, "rna_KeyMapItem_update");
prop = RNA_def_property(srna, "shift", PROP_BOOLEAN, PROP_NONE);
prop = RNA_def_property(srna, "shift", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "shift");
RNA_def_property_range(prop, KM_ANY, KM_MOD_HELD);
RNA_def_property_ui_text(prop, "Shift", "Shift key pressed, -1 for any state");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_WINDOWMANAGER);
RNA_def_property_update(prop, 0, "rna_KeyMapItem_update");
prop = RNA_def_property(srna, "ctrl", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "ctrl");
RNA_def_property_range(prop, KM_ANY, KM_MOD_HELD);
RNA_def_property_ui_text(prop, "Ctrl", "Control key pressed, -1 for any state");
RNA_def_property_update(prop, 0, "rna_KeyMapItem_update");
prop = RNA_def_property(srna, "alt", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "alt");
RNA_def_property_range(prop, KM_ANY, KM_MOD_HELD);
RNA_def_property_ui_text(prop, "Alt", "Alt key pressed, -1 for any state");
RNA_def_property_update(prop, 0, "rna_KeyMapItem_update");
prop = RNA_def_property(srna, "oskey", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "oskey");
RNA_def_property_range(prop, KM_ANY, KM_MOD_HELD);
RNA_def_property_ui_text(prop, "OS Key", "Operating system key pressed, -1 for any state");
RNA_def_property_update(prop, 0, "rna_KeyMapItem_update");
/* XXX(@campbellbarton): the `*_ui` suffix is only for the UI, may be removed,
* since this is only exposed so the UI can show these settings as toggle-buttons. */
prop = RNA_def_property(srna, "shift_ui", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "shift", 0);
RNA_def_property_boolean_funcs(prop, "rna_KeyMapItem_shift_get", NULL);
/* 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_translation_context(prop, BLT_I18NCONTEXT_ID_WINDOWMANAGER);
RNA_def_property_update(prop, 0, "rna_KeyMapItem_update");
prop = RNA_def_property(srna, "ctrl", PROP_BOOLEAN, PROP_NONE);
prop = RNA_def_property(srna, "ctrl_ui", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "ctrl", 0);
RNA_def_property_boolean_funcs(prop, "rna_KeyMapItem_ctrl_get", NULL);
/* 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_update(prop, 0, "rna_KeyMapItem_update");
prop = RNA_def_property(srna, "alt", PROP_BOOLEAN, PROP_NONE);
prop = RNA_def_property(srna, "alt_ui", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "alt", 0);
RNA_def_property_boolean_funcs(prop, "rna_KeyMapItem_alt_get", NULL);
/* 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_update(prop, 0, "rna_KeyMapItem_update");
prop = RNA_def_property(srna, "oskey", PROP_BOOLEAN, PROP_NONE);
prop = RNA_def_property(srna, "oskey_ui", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "oskey", 0);
RNA_def_property_boolean_funcs(prop, "rna_KeyMapItem_oskey_get", NULL);
/* 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_update(prop, 0, "rna_KeyMapItem_update");
/* End `_ui` modifiers. */
prop = RNA_def_property(srna, "key_modifier", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "keymodifier");

View File

@ -39,6 +39,8 @@
#include "wm_cursors.h"
#include "wm_event_types.h"
#include "WM_types.h"
#include "rna_internal.h" /* own include */
/* confusing 2 enums mixed up here */
@ -216,50 +218,71 @@ static int rna_Operator_props_popup(bContext *C, wmOperator *op, wmEvent *event)
return WM_operator_props_popup(C, op, event);
}
static int keymap_item_modifier_flag_from_args(bool any, int shift, int ctrl, int alt, int oskey)
{
int modifier = 0;
if (any) {
modifier = KM_ANY;
}
else {
if (shift == KM_MOD_HELD) {
modifier |= KM_SHIFT;
}
else if (shift == KM_ANY) {
modifier |= KM_SHIFT_ANY;
}
if (ctrl == KM_MOD_HELD) {
modifier |= KM_CTRL;
}
else if (ctrl == KM_ANY) {
modifier |= KM_CTRL_ANY;
}
if (alt == KM_MOD_HELD) {
modifier |= KM_ALT;
}
else if (alt == KM_ANY) {
modifier |= KM_ALT_ANY;
}
if (oskey == KM_MOD_HELD) {
modifier |= KM_OSKEY;
}
else if (oskey == KM_ANY) {
modifier |= KM_OSKEY_ANY;
}
}
return modifier;
}
static wmKeyMapItem *rna_KeyMap_item_new(wmKeyMap *km,
ReportList *reports,
const char *idname,
int type,
int value,
bool any,
bool shift,
bool ctrl,
bool alt,
bool oskey,
int shift,
int ctrl,
int alt,
int oskey,
int keymodifier,
bool repeat,
bool head)
{
// wmWindowManager *wm = CTX_wm_manager(C);
wmKeyMapItem *kmi = NULL;
char idname_bl[OP_MAX_TYPENAME];
int modifier = 0;
/* only on non-modal maps */
if (km->flag & KEYMAP_MODAL) {
BKE_report(reports, RPT_ERROR, "Not a non-modal keymap");
return NULL;
}
// wmWindowManager *wm = CTX_wm_manager(C);
wmKeyMapItem *kmi = NULL;
char idname_bl[OP_MAX_TYPENAME];
const int modifier = keymap_item_modifier_flag_from_args(any, shift, ctrl, alt, oskey);
WM_operator_bl_idname(idname_bl, idname);
if (shift) {
modifier |= KM_SHIFT;
}
if (ctrl) {
modifier |= KM_CTRL;
}
if (alt) {
modifier |= KM_ALT;
}
if (oskey) {
modifier |= KM_OSKEY;
}
if (any) {
modifier = KM_ANY;
}
/* create keymap item */
kmi = WM_keymap_add_item(km, idname_bl, type, value, modifier, keymodifier);
@ -305,39 +328,22 @@ static wmKeyMapItem *rna_KeyMap_item_new_modal(wmKeyMap *km,
int type,
int value,
bool any,
bool shift,
bool ctrl,
bool alt,
bool oskey,
int shift,
int ctrl,
int alt,
int oskey,
int keymodifier,
bool repeat)
{
wmKeyMapItem *kmi = NULL;
int modifier = 0;
int propvalue = 0;
/* only modal maps */
if ((km->flag & KEYMAP_MODAL) == 0) {
BKE_report(reports, RPT_ERROR, "Not a modal keymap");
return NULL;
}
if (shift) {
modifier |= KM_SHIFT;
}
if (ctrl) {
modifier |= KM_CTRL;
}
if (alt) {
modifier |= KM_ALT;
}
if (oskey) {
modifier |= KM_OSKEY;
}
if (any) {
modifier = KM_ANY;
}
wmKeyMapItem *kmi = NULL;
const int modifier = keymap_item_modifier_flag_from_args(any, shift, ctrl, alt, oskey);
int propvalue = 0;
/* not initialized yet, do delayed lookup */
if (!km->modal_items) {
@ -1131,10 +1137,10 @@ void RNA_api_keymapitems(StructRNA *srna)
parm = RNA_def_enum(func, "value", rna_enum_event_value_all_items, 0, "Value", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
RNA_def_boolean(func, "any", 0, "Any", "");
RNA_def_boolean(func, "shift", 0, "Shift", "");
RNA_def_boolean(func, "ctrl", 0, "Ctrl", "");
RNA_def_boolean(func, "alt", 0, "Alt", "");
RNA_def_boolean(func, "oskey", 0, "OS Key", "");
RNA_def_int(func, "shift", KM_NOTHING, KM_ANY, KM_MOD_HELD, "Shift", "", KM_ANY, KM_MOD_HELD);
RNA_def_int(func, "ctrl", KM_NOTHING, KM_ANY, KM_MOD_HELD, "Ctrl", "", KM_ANY, KM_MOD_HELD);
RNA_def_int(func, "alt", KM_NOTHING, KM_ANY, KM_MOD_HELD, "Alt", "", KM_ANY, KM_MOD_HELD);
RNA_def_int(func, "oskey", KM_NOTHING, KM_ANY, KM_MOD_HELD, "OS Key", "", KM_ANY, KM_MOD_HELD);
RNA_def_enum(func, "key_modifier", rna_enum_event_type_items, 0, "Key Modifier", "");
RNA_def_boolean(func, "repeat", false, "Repeat", "When set, accept key-repeat events");
RNA_def_boolean(func,
@ -1155,10 +1161,10 @@ void RNA_api_keymapitems(StructRNA *srna)
parm = RNA_def_enum(func, "value", rna_enum_event_value_all_items, 0, "Value", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
RNA_def_boolean(func, "any", 0, "Any", "");
RNA_def_boolean(func, "shift", 0, "Shift", "");
RNA_def_boolean(func, "ctrl", 0, "Ctrl", "");
RNA_def_boolean(func, "alt", 0, "Alt", "");
RNA_def_boolean(func, "oskey", 0, "OS Key", "");
RNA_def_int(func, "shift", KM_NOTHING, KM_ANY, KM_MOD_HELD, "Shift", "", KM_ANY, KM_MOD_HELD);
RNA_def_int(func, "ctrl", KM_NOTHING, KM_ANY, KM_MOD_HELD, "Ctrl", "", KM_ANY, KM_MOD_HELD);
RNA_def_int(func, "alt", KM_NOTHING, KM_ANY, KM_MOD_HELD, "Alt", "", KM_ANY, KM_MOD_HELD);
RNA_def_int(func, "oskey", KM_NOTHING, KM_ANY, KM_MOD_HELD, "OS Key", "", KM_ANY, KM_MOD_HELD);
RNA_def_enum(func, "key_modifier", rna_enum_event_type_items, 0, "Key Modifier", "");
RNA_def_boolean(func, "repeat", false, "Repeat", "When set, accept key-repeat events");
parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", "Added key map item");

View File

@ -240,6 +240,12 @@ typedef enum eOperatorPropTags {
#define KM_ALT 4
#define KM_OSKEY 8
/* Used for key-map item creation function arguments (never stored in DNA). */
#define KM_SHIFT_ANY 16
#define KM_CTRL_ANY 32
#define KM_ALT_ANY 64
#define KM_OSKEY_ANY 128
/* KM_MOD_ flags for `wmKeyMapItem` and `wmEvent.alt/shift/oskey/ctrl`. */
/* note that KM_ANY and KM_NOTHING are used with these defines too */
#define KM_MOD_HELD 1

View File

@ -484,10 +484,20 @@ static void keymap_event_set(
kmi->shift = kmi->ctrl = kmi->alt = kmi->oskey = KM_ANY;
}
else {
kmi->shift = (modifier & KM_SHIFT) ? KM_MOD_HELD : KM_NOTHING;
kmi->ctrl = (modifier & KM_CTRL) ? KM_MOD_HELD : KM_NOTHING;
kmi->alt = (modifier & KM_ALT) ? KM_MOD_HELD : KM_NOTHING;
kmi->oskey = (modifier & KM_OSKEY) ? KM_MOD_HELD : KM_NOTHING;
/* Only one of the flags should be set. */
BLI_assert(((modifier & (KM_SHIFT | KM_SHIFT_ANY)) != (KM_SHIFT | KM_SHIFT_ANY)) &&
((modifier & (KM_CTRL | KM_CTRL_ANY)) != (KM_CTRL | KM_CTRL_ANY)) &&
((modifier & (KM_ALT | KM_ALT_ANY)) != (KM_ALT | KM_ALT_ANY)) &&
((modifier & (KM_OSKEY | KM_OSKEY_ANY)) != (KM_OSKEY | KM_OSKEY_ANY)));
kmi->shift = ((modifier & KM_SHIFT) ? KM_MOD_HELD :
((modifier & KM_SHIFT_ANY) ? KM_ANY : KM_NOTHING));
kmi->ctrl = ((modifier & KM_CTRL) ? KM_MOD_HELD :
((modifier & KM_CTRL_ANY) ? KM_ANY : KM_NOTHING));
kmi->alt = ((modifier & KM_ALT) ? KM_MOD_HELD :
((modifier & KM_ALT_ANY) ? KM_ANY : KM_NOTHING));
kmi->oskey = ((modifier & KM_OSKEY) ? KM_MOD_HELD :
((modifier & KM_OSKEY_ANY) ? KM_ANY : KM_NOTHING));
}
}