[Bf-blender-cvs] [5be0e3430d1] master: GHOST/Keymap: support for detecting repeat events
Campbell Barton
noreply at git.blender.org
Fri Mar 6 07:33:35 CET 2020
Commit: 5be0e3430d13341feddee739997130239daf71d5
Author: Campbell Barton
Date: Fri Mar 6 17:24:12 2020 +1100
Branches: master
https://developer.blender.org/rB5be0e3430d13341feddee739997130239daf71d5
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.
===================================================================
M intern/ghost/GHOST_Types.h
M intern/ghost/intern/GHOST_EventKey.h
M intern/ghost/intern/GHOST_NDOFManager.cpp
M intern/ghost/intern/GHOST_SystemCocoa.mm
M intern/ghost/intern/GHOST_SystemSDL.cpp
M intern/ghost/intern/GHOST_SystemWin32.cpp
M intern/ghost/intern/GHOST_SystemWin32.h
M intern/ghost/intern/GHOST_SystemX11.cpp
M intern/ghost/intern/GHOST_SystemX11.h
M release/scripts/modules/rna_keymap_ui.py
M source/blender/makesdna/DNA_windowmanager_types.h
M source/blender/makesrna/intern/rna_wm.c
M source/blender/makesrna/intern/rna_wm_api.c
M source/blender/windowmanager/WM_types.h
M source/blender/windowmanager/intern/wm_event_system.c
M source/blender/windowmanager/intern/wm_keymap.c
===================================================================
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 38a6a0b04d2..8bc75d01b96 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -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 {
diff --git a/intern/ghost/intern/GHOST_EventKey.h b/intern/ghost/intern/GHOST_EventKey.h
index f42dc99aaa5..24e20b20659 100644
--- a/intern/ghost/intern/GHOST_EventKey.h
+++ b/intern/ghost/intern/GHOST_EventKey.h
@@ -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;
}
diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp
index 9999bfd7ea6..3fe61ee0aa9 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManager.cpp
@@ -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");
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index b65404cf9b1..ee05505f682 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -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],
diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp
index 7ed912b8218..656afb9d050 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.cpp
+++ b/intern/ghost/intern/GHOST_SystemSDL.cpp
@@ -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;
}
}
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 7d2a8f5810c..5bf40ba33d0 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -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);
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index c5af3e120be..bf9d18ca380 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -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. */
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index 60d08305621..05c311077f9 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -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_ve
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list