GHOST/Keymap: support for detecting repeat events
- Keymap items now have 'repeat' boolean which can be set to make keymap items respond to key repeat events or not. - Support for X11 & WIN32 (not macOS currently). This allows for the possibility to perform actions while a key is held and finish the action upon release. Thanks to @Severin for review and WIN32 support.
This commit is contained in:
parent
73ef27f156
commit
5be0e3430d
Notes:
blender-bot
2023-02-13 23:13:45 +01:00
Referenced by commit c72317943b
, Attempt to fix build errors on macOS
Referenced by issue #74622, Face Sets visibility glitches
|
@ -542,6 +542,9 @@ typedef struct {
|
|||
char ascii;
|
||||
/** The unicode character. if the length is 6, not NULL terminated if all 6 are set */
|
||||
char utf8_buf[6];
|
||||
|
||||
/** Generated by auto-repeat. */
|
||||
char is_repeat;
|
||||
} GHOST_TEventKeyData;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -38,12 +38,17 @@ class GHOST_EventKey : public GHOST_Event {
|
|||
* \param type The type of key event.
|
||||
* \param key The key code of the key.
|
||||
*/
|
||||
GHOST_EventKey(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow *window, GHOST_TKey key)
|
||||
GHOST_EventKey(GHOST_TUns64 msec,
|
||||
GHOST_TEventType type,
|
||||
GHOST_IWindow *window,
|
||||
GHOST_TKey key,
|
||||
bool is_repeat)
|
||||
: GHOST_Event(msec, type, window)
|
||||
{
|
||||
m_keyEventData.key = key;
|
||||
m_keyEventData.ascii = '\0';
|
||||
m_keyEventData.utf8_buf[0] = '\0';
|
||||
m_keyEventData.is_repeat = is_repeat;
|
||||
m_data = &m_keyEventData;
|
||||
}
|
||||
|
||||
|
@ -59,7 +64,8 @@ class GHOST_EventKey : public GHOST_Event {
|
|||
GHOST_IWindow *window,
|
||||
GHOST_TKey key,
|
||||
char ascii,
|
||||
const char utf8_buf[6])
|
||||
const char utf8_buf[6],
|
||||
bool is_repeat)
|
||||
: GHOST_Event(msec, type, window)
|
||||
{
|
||||
m_keyEventData.key = key;
|
||||
|
@ -68,6 +74,7 @@ class GHOST_EventKey : public GHOST_Event {
|
|||
memcpy(m_keyEventData.utf8_buf, utf8_buf, sizeof(m_keyEventData.utf8_buf));
|
||||
else
|
||||
m_keyEventData.utf8_buf[0] = '\0';
|
||||
m_keyEventData.is_repeat = is_repeat;
|
||||
m_data = &m_keyEventData;
|
||||
}
|
||||
|
||||
|
|
|
@ -318,7 +318,7 @@ void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key,
|
|||
GHOST_IWindow *window)
|
||||
{
|
||||
GHOST_TEventType type = press ? GHOST_kEventKeyDown : GHOST_kEventKeyUp;
|
||||
GHOST_EventKey *event = new GHOST_EventKey(time, type, window, key);
|
||||
GHOST_EventKey *event = new GHOST_EventKey(time, type, window, key, false);
|
||||
|
||||
#ifdef DEBUG_NDOF_BUTTONS
|
||||
printf("keyboard %s\n", press ? "down" : "up");
|
||||
|
|
|
@ -1806,7 +1806,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
|
|||
|
||||
if ([event type] == NSEventTypeKeyDown) {
|
||||
pushEvent(new GHOST_EventKey(
|
||||
[event timestamp] * 1000, GHOST_kEventKeyDown, window, keyCode, ascii, utf8_buf));
|
||||
[event timestamp] * 1000, GHOST_kEventKeyDown, window, keyCode, ascii, utf8_buf, false));
|
||||
#if 0
|
||||
printf("Key down rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u ascii=%i %c utf8=%s\n",
|
||||
[event keyCode],
|
||||
|
@ -1820,7 +1820,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
|
|||
}
|
||||
else {
|
||||
pushEvent(new GHOST_EventKey(
|
||||
[event timestamp] * 1000, GHOST_kEventKeyUp, window, keyCode, 0, NULL));
|
||||
[event timestamp] * 1000, GHOST_kEventKeyUp, window, keyCode, 0, NULL, false));
|
||||
#if 0
|
||||
printf("Key up rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u ascii=%i %c utf8=%s\n",
|
||||
[event keyCode],
|
||||
|
|
|
@ -591,7 +591,7 @@ void GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
|
|||
}
|
||||
}
|
||||
|
||||
g_event = new GHOST_EventKey(getMilliSeconds(), type, window, gkey, sym, NULL);
|
||||
g_event = new GHOST_EventKey(getMilliSeconds(), type, window, gkey, sym, NULL, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1047,6 +1047,20 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RA
|
|||
if (key != GHOST_kKeyUnknown) {
|
||||
char utf8_char[6] = {0};
|
||||
char ascii = 0;
|
||||
bool is_repeat = false;
|
||||
|
||||
/* Unlike on Linux, not all keys can send repeat events. E.g. modifier keys don't. */
|
||||
if (keyDown) {
|
||||
if (system->m_keycode_last_repeat_key == vk) {
|
||||
is_repeat = true;
|
||||
}
|
||||
system->m_keycode_last_repeat_key = vk;
|
||||
}
|
||||
else {
|
||||
if (system->m_keycode_last_repeat_key == vk) {
|
||||
system->m_keycode_last_repeat_key = 0;
|
||||
}
|
||||
}
|
||||
|
||||
wchar_t utf16[3] = {0};
|
||||
BYTE state[256] = {0};
|
||||
|
@ -1083,7 +1097,8 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RA
|
|||
window,
|
||||
key,
|
||||
ascii,
|
||||
utf8_char);
|
||||
utf8_char,
|
||||
is_repeat);
|
||||
|
||||
// GHOST_PRINTF("%c\n", ascii); // we already get this info via EventPrinter
|
||||
}
|
||||
|
@ -1520,6 +1535,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|||
modifiers.clear();
|
||||
system->storeModifierKeys(modifiers);
|
||||
system->m_wheelDeltaAccum = 0;
|
||||
system->m_keycode_last_repeat_key = 0;
|
||||
event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate :
|
||||
GHOST_kEventWindowDeactivate,
|
||||
window);
|
||||
|
|
|
@ -414,6 +414,8 @@ class GHOST_SystemWin32 : public GHOST_System {
|
|||
|
||||
/** The current state of the modifier keys. */
|
||||
GHOST_ModifierKeys m_modifierKeys;
|
||||
/** The virtual-key code (VKey) of the last press event. Used to detect repeat events. */
|
||||
unsigned short m_keycode_last_repeat_key;
|
||||
/** State variable set at initialization. */
|
||||
bool m_hasPerformanceCounter;
|
||||
/** High frequency timer variable. */
|
||||
|
|
|
@ -93,6 +93,11 @@
|
|||
* instead of active one. See T47228 and D1746 */
|
||||
#define USE_NON_LATIN_KB_WORKAROUND
|
||||
|
||||
static uchar bit_is_on(const uchar *ptr, int bit)
|
||||
{
|
||||
return ptr[bit >> 3] & (1 << (bit & 7));
|
||||
}
|
||||
|
||||
static GHOST_TKey ghost_key_from_keysym(const KeySym key);
|
||||
static GHOST_TKey ghost_key_from_keycode(const XkbDescPtr xkb_descr, const KeyCode keycode);
|
||||
static GHOST_TKey ghost_key_from_keysym_or_keycode(const KeySym key,
|
||||
|
@ -196,6 +201,7 @@ GHOST_SystemX11::GHOST_SystemX11() : GHOST_System(), m_xkb_descr(NULL), m_start_
|
|||
m_xkb_descr = XkbGetMap(m_display, 0, XkbUseCoreKbd);
|
||||
if (m_xkb_descr) {
|
||||
XkbGetNames(m_display, XkbKeyNamesMask, m_xkb_descr);
|
||||
XkbGetControls(m_display, XkbPerKeyRepeatMask | XkbRepeatKeysMask, m_xkb_descr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -747,7 +753,8 @@ bool GHOST_SystemX11::processEvents(bool waitForEvent)
|
|||
window,
|
||||
ghost_key_from_keysym(modifiers[i]),
|
||||
'\0',
|
||||
NULL));
|
||||
NULL,
|
||||
false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -822,6 +829,64 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
|
|||
GHOST_WindowX11 *window = findGhostWindow(xe->xany.window);
|
||||
GHOST_Event *g_event = NULL;
|
||||
|
||||
/* Detect auto-repeat. */
|
||||
bool is_repeat = false;
|
||||
if (xe->type == KeyPress || xe->type == KeyRelease) {
|
||||
XKeyEvent *xke = &(xe->xkey);
|
||||
|
||||
/* Set to true if this key will repeat. */
|
||||
bool is_repeat_keycode = false;
|
||||
|
||||
if (m_xkb_descr != NULL) {
|
||||
/* Use XKB support. */
|
||||
is_repeat_keycode = (
|
||||
/* Should always be true, check just in case. */
|
||||
(xke->keycode < (XkbPerKeyBitArraySize << 3)) &&
|
||||
bit_is_on(m_xkb_descr->ctrls->per_key_repeat, xke->keycode));
|
||||
}
|
||||
else {
|
||||
/* No XKB support (filter by modifier). */
|
||||
switch (XLookupKeysym(xke, 0)) {
|
||||
case XK_Shift_L:
|
||||
case XK_Shift_R:
|
||||
case XK_Control_L:
|
||||
case XK_Control_R:
|
||||
case XK_Alt_L:
|
||||
case XK_Alt_R:
|
||||
case XK_Super_L:
|
||||
case XK_Super_R:
|
||||
case XK_Hyper_L:
|
||||
case XK_Hyper_R:
|
||||
case XK_Caps_Lock:
|
||||
case XK_Scroll_Lock:
|
||||
case XK_Num_Lock: {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
is_repeat_keycode = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_repeat_keycode) {
|
||||
if (xe->type == KeyPress) {
|
||||
if (m_keycode_last_repeat_key == xke->keycode) {
|
||||
is_repeat = true;
|
||||
}
|
||||
m_keycode_last_repeat_key = xke->keycode;
|
||||
}
|
||||
else {
|
||||
if (m_keycode_last_repeat_key == xke->keycode) {
|
||||
m_keycode_last_repeat_key = (uint)-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (xe->type == EnterNotify) {
|
||||
/* We can't tell how the key state changed, clear it to avoid stuck keys. */
|
||||
m_keycode_last_repeat_key = (uint)-1;
|
||||
}
|
||||
|
||||
#ifdef USE_XINPUT_HOTPLUG
|
||||
/* Hot-Plug support */
|
||||
if (m_xinput_version.present) {
|
||||
|
@ -1129,7 +1194,8 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
|
|||
}
|
||||
#endif
|
||||
|
||||
g_event = new GHOST_EventKey(getMilliSeconds(), type, window, gkey, ascii, utf8_buf);
|
||||
g_event = new GHOST_EventKey(
|
||||
getMilliSeconds(), type, window, gkey, ascii, utf8_buf, is_repeat);
|
||||
|
||||
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
|
||||
/* when using IM for some languages such as Japanese,
|
||||
|
@ -1153,7 +1219,8 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
|
|||
/* enqueue previous character */
|
||||
pushEvent(g_event);
|
||||
|
||||
g_event = new GHOST_EventKey(getMilliSeconds(), type, window, gkey, '\0', &utf8_buf[i]);
|
||||
g_event = new GHOST_EventKey(
|
||||
getMilliSeconds(), type, window, gkey, '\0', &utf8_buf[i], is_repeat);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -366,6 +366,8 @@ class GHOST_SystemX11 : public GHOST_System {
|
|||
unsigned int m_last_release_keycode;
|
||||
Time m_last_release_time;
|
||||
|
||||
uint m_keycode_last_repeat_key;
|
||||
|
||||
/**
|
||||
* Return the ghost window associated with the
|
||||
* X11 window xwind
|
||||
|
|
|
@ -184,6 +184,9 @@ def draw_kmi(display_keymaps, kc, km, kmi, layout, level):
|
|||
if map_type == 'KEYBOARD':
|
||||
subrow.prop(kmi, "type", text="", event=True)
|
||||
subrow.prop(kmi, "value", text="")
|
||||
subrow_repeat = subrow.row(align=True)
|
||||
subrow_repeat.active = kmi.value in {'ANY', 'PRESS'}
|
||||
subrow_repeat.prop(kmi, "repeat", text="Repeat")
|
||||
elif map_type in {'MOUSE', 'NDOF'}:
|
||||
subrow.prop(kmi, "type", text="")
|
||||
subrow.prop(kmi, "value", text="")
|
||||
|
|
|
@ -370,6 +370,7 @@ enum {
|
|||
KMI_EXPANDED = (1 << 1),
|
||||
KMI_USER_MODIFIED = (1 << 2),
|
||||
KMI_UPDATE = (1 << 3),
|
||||
KMI_REPEAT_IGNORE = (1 << 4),
|
||||
};
|
||||
|
||||
/** #wmKeyMapItem.maptype */
|
||||
|
|
|
@ -652,6 +652,12 @@ static int rna_Event_unicode_length(PointerRNA *ptr)
|
|||
}
|
||||
}
|
||||
|
||||
static bool rna_Event_is_repeat_get(PointerRNA *ptr)
|
||||
{
|
||||
const wmEvent *event = ptr->data;
|
||||
return event->is_repeat;
|
||||
}
|
||||
|
||||
static float rna_Event_pressure_get(PointerRNA *ptr)
|
||||
{
|
||||
const wmEvent *event = ptr->data;
|
||||
|
@ -2131,6 +2137,12 @@ static void rna_def_event(BlenderRNA *brna)
|
|||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Type", "");
|
||||
|
||||
/* keyboard */
|
||||
prop = RNA_def_property(srna, "is_repeat", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_boolean_funcs(prop, "rna_Event_is_repeat_get", NULL);
|
||||
RNA_def_property_ui_text(prop, "Is Repeat", "The event is generated by holding a key down");
|
||||
|
||||
/* mouse */
|
||||
prop = RNA_def_property(srna, "mouse_x", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "x");
|
||||
|
@ -2728,6 +2740,12 @@ static void rna_def_keyconfig(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "Key Modifier", "Regular key pressed as a modifier");
|
||||
RNA_def_property_update(prop, 0, "rna_KeyMapItem_update");
|
||||
|
||||
prop = RNA_def_property(srna, "repeat", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", KMI_REPEAT_IGNORE);
|
||||
RNA_def_property_ui_text(prop, "Repeat", "Active on key-repeat events (when a key is held)");
|
||||
RNA_def_property_update(prop, 0, "rna_KeyMapItem_update");
|
||||
|
||||
prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", KMI_EXPANDED);
|
||||
|
|
|
@ -216,6 +216,7 @@ static wmKeyMapItem *rna_KeyMap_item_new(wmKeyMap *km,
|
|||
bool alt,
|
||||
bool oskey,
|
||||
int keymodifier,
|
||||
bool repeat,
|
||||
bool head)
|
||||
{
|
||||
/* wmWindowManager *wm = CTX_wm_manager(C); */
|
||||
|
@ -251,6 +252,10 @@ static wmKeyMapItem *rna_KeyMap_item_new(wmKeyMap *km,
|
|||
/* create keymap item */
|
||||
kmi = WM_keymap_add_item(km, idname_bl, type, value, modifier, keymodifier);
|
||||
|
||||
if (!repeat) {
|
||||
kmi->flag |= KMI_REPEAT_IGNORE;
|
||||
}
|
||||
|
||||
/* [#32437] allow scripts to define hotkeys that get added to start of keymap
|
||||
* so that they stand a chance against catch-all defines later on
|
||||
*/
|
||||
|
@ -293,8 +298,10 @@ static wmKeyMapItem *rna_KeyMap_item_new_modal(wmKeyMap *km,
|
|||
bool ctrl,
|
||||
bool alt,
|
||||
bool oskey,
|
||||
int keymodifier)
|
||||
int keymodifier,
|
||||
bool repeat)
|
||||
{
|
||||
wmKeyMapItem *kmi = NULL;
|
||||
int modifier = 0;
|
||||
int propvalue = 0;
|
||||
|
||||
|
@ -323,14 +330,20 @@ static wmKeyMapItem *rna_KeyMap_item_new_modal(wmKeyMap *km,
|
|||
|
||||
/* not initialized yet, do delayed lookup */
|
||||
if (!km->modal_items) {
|
||||
return WM_modalkeymap_add_item_str(km, type, value, modifier, keymodifier, propvalue_str);
|
||||
kmi = WM_modalkeymap_add_item_str(km, type, value, modifier, keymodifier, propvalue_str);
|
||||
}
|
||||
else {
|
||||
if (RNA_enum_value_from_id(km->modal_items, propvalue_str, &propvalue) == 0) {
|
||||
BKE_report(reports, RPT_WARNING, "Property value not in enumeration");
|
||||
}
|
||||
kmi = WM_modalkeymap_add_item(km, type, value, modifier, keymodifier, propvalue);
|
||||
}
|
||||
|
||||
if (RNA_enum_value_from_id(km->modal_items, propvalue_str, &propvalue) == 0) {
|
||||
BKE_report(reports, RPT_WARNING, "Property value not in enumeration");
|
||||
if (!repeat) {
|
||||
kmi->flag |= KMI_REPEAT_IGNORE;
|
||||
}
|
||||
|
||||
return WM_modalkeymap_add_item(km, type, value, modifier, keymodifier, propvalue);
|
||||
return kmi;
|
||||
}
|
||||
|
||||
static void rna_KeyMap_item_remove(wmKeyMap *km, ReportList *reports, PointerRNA *kmi_ptr)
|
||||
|
@ -1083,6 +1096,7 @@ void RNA_api_keymapitems(StructRNA *srna)
|
|||
RNA_def_boolean(func, "alt", 0, "Alt", "");
|
||||
RNA_def_boolean(func, "oskey", 0, "OS Key", "");
|
||||
RNA_def_enum(func, "key_modifier", rna_enum_event_type_items, 0, "Key Modifier", "");
|
||||
RNA_def_boolean(func, "repeat", true, "Repeat", "When set, accept key-repeat events");
|
||||
RNA_def_boolean(func,
|
||||
"head",
|
||||
0,
|
||||
|
@ -1106,6 +1120,7 @@ void RNA_api_keymapitems(StructRNA *srna)
|
|||
RNA_def_boolean(func, "alt", 0, "Alt", "");
|
||||
RNA_def_boolean(func, "oskey", 0, "OS Key", "");
|
||||
RNA_def_enum(func, "key_modifier", rna_enum_event_type_items, 0, "Key Modifier", "");
|
||||
RNA_def_boolean(func, "repeat", true, "Repeat", "When set, accept key-repeat events");
|
||||
parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", "Added key map item");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
|
|
|
@ -540,7 +540,9 @@ typedef struct wmEvent {
|
|||
char utf8_buf[6];
|
||||
/** From ghost, fallback if utf8 isn't set. */
|
||||
char ascii;
|
||||
char pad;
|
||||
|
||||
/** Generated by auto-repeat. */
|
||||
char is_repeat;
|
||||
|
||||
/** Previous state, used for double click and the 'click'. */
|
||||
short prevtype;
|
||||
|
|
|
@ -1772,6 +1772,12 @@ static bool wm_eventmatch(const wmEvent *winevent, const wmKeyMapItem *kmi)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (winevent->is_repeat) {
|
||||
if (kmi->flag & KMI_REPEAT_IGNORE) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const int kmitype = WM_userdef_event_map(kmi->type);
|
||||
|
||||
/* the matching rules */
|
||||
|
@ -4254,6 +4260,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
|
|||
|
||||
/* initialize and copy state (only mouse x y and modifiers) */
|
||||
event = *evt;
|
||||
event.is_repeat = false;
|
||||
|
||||
switch (type) {
|
||||
/* mouse move, also to inactive window (X11 does this) */
|
||||
|
@ -4407,6 +4414,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
|
|||
event.ascii = kd->ascii;
|
||||
memcpy(
|
||||
event.utf8_buf, kd->utf8_buf, sizeof(event.utf8_buf)); /* might be not null terminated*/
|
||||
event.is_repeat = kd->is_repeat;
|
||||
event.val = (type == GHOST_kEventKeyDown) ? KM_PRESS : KM_RELEASE;
|
||||
|
||||
wm_eventemulation(&event, false);
|
||||
|
@ -4418,6 +4426,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
|
|||
/* copy to event state */
|
||||
evt->val = event.val;
|
||||
evt->type = event.type;
|
||||
evt->is_repeat = event.is_repeat;
|
||||
|
||||
/* exclude arrow keys, esc, etc from text input */
|
||||
if (type == GHOST_kEventKeyUp) {
|
||||
|
|
|
@ -180,7 +180,9 @@ static bool wm_keymap_item_equals(wmKeyMapItem *a, wmKeyMapItem *b)
|
|||
{
|
||||
return (wm_keymap_item_equals_result(a, b) && a->type == b->type && a->val == b->val &&
|
||||
a->shift == b->shift && a->ctrl == b->ctrl && a->alt == b->alt && a->oskey == b->oskey &&
|
||||
a->keymodifier == b->keymodifier && a->maptype == b->maptype);
|
||||
a->keymodifier == b->keymodifier && a->maptype == b->maptype &&
|
||||
((ISKEYBOARD(a->type) == 0) ||
|
||||
(a->flag & KMI_REPEAT_IGNORE) == (b->flag & KMI_REPEAT_IGNORE)));
|
||||
}
|
||||
|
||||
/* properties can be NULL, otherwise the arg passed is used and ownership is given to the kmi */
|
||||
|
@ -2012,6 +2014,7 @@ void WM_keymap_item_restore_to_default(bContext *C, wmKeyMap *keymap, wmKeyMapIt
|
|||
kmi->oskey = orig->oskey;
|
||||
kmi->keymodifier = orig->keymodifier;
|
||||
kmi->maptype = orig->maptype;
|
||||
kmi->flag = (kmi->flag & ~KMI_REPEAT_IGNORE) | (orig->flag & KMI_REPEAT_IGNORE);
|
||||
|
||||
WM_keyconfig_update_tag(keymap, kmi);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue