Browse Source

Add Widget::KeyBaseEvent::isKeyCommand() for checking a key command correctly on all keyboard layouts. Make getKeyName() directly convert GLFW key to name, ignoring current keyboard layout.

tags/v2.6.1
Andrew Belt 5 months ago
parent
commit
363c9e48e5
3 changed files with 37 additions and 11 deletions
  1. +6
    -0
      include/widget/Widget.hpp
  2. +3
    -3
      include/widget/event.hpp
  3. +28
    -8
      src/widget/event.cpp

+ 6
- 0
include/widget/Widget.hpp View File

@@ -286,6 +286,12 @@ struct Widget : WeakBase {
See GLFW_MOD_* for the list of possible values.
*/
int mods;
/** Checks whether this KeyBaseEvent is the given key command. `mods` is OR'd GLFW modifier keys.
On Latin keyboards such as QWERTY, AZERTY, QWERTZ, and Dvorak, the key name is checked regardless of position. For example, pressing Q with key=GLFW_KEY_Q returns true for all of these layouts.
On non-Latin keyboards such as JCUKEN (ЙЦУКЕН), the layout is assumed to match QWERTY. For example, pressing Й with key=GLFW_KEY_Q returns true.
Implemented in event.cpp.
*/
bool isKeyCommand(int key, int mods = 0) const;
};

/** Occurs when a key is pressed, released, or repeated while the mouse is hovering a Widget.


+ 3
- 3
include/widget/event.hpp View File

@@ -40,11 +40,11 @@ namespace rack {
namespace widget {


std::string getKeyName(int key);
std::string getKeyCommandName(int key, int mods);
struct Widget;


struct Widget;
std::string getKeyName(int key);
std::string getKeyCommandName(int key, int mods = 0);


/** A per-event state shared and writable by all widgets that recursively handle an event. */


+ 28
- 8
src/widget/event.cpp View File

@@ -15,12 +15,9 @@ std::string getKeyName(int key) {
case GLFW_KEY_SPACE: return "Space";
}

const char* keyNameC = glfwGetKeyName(key, GLFW_KEY_UNKNOWN);
if (keyNameC) {
std::string keyName = keyNameC;
if (keyName.size() == 1)
keyName[0] = std::toupper((unsigned char) keyName[0]);
return keyName;
// Printable characters
if (key < 128) {
return std::string(1, (char) key);
}

// Unprintable keys with names
@@ -64,6 +61,29 @@ std::string getKeyCommandName(int key, int mods) {
}


bool Widget::KeyBaseEvent::isKeyCommand(int key, int mods) const {
// Reject if mods don't match
if ((this->mods & RACK_MOD_MASK) != mods)
return false;
// Reject invalid keys
if (this->key < 32)
return false;
// Are both keys printable?
if (this->key < 128 && key < 128) {
// Is the event a printable ASCII character?
if (this->keyName.size() == 1) {
// Uppercase event key name
char k = this->keyName[0];
if (k >= 'a' && k <= 'z')
k += 'A' - 'a';
return k == key;
}
}
// Check equal QWERTY keys, printable or not
return this->key == key;
}


void EventState::setHoveredWidget(widget::Widget* w) {
if (w == hoveredWidget)
return;
@@ -364,7 +384,7 @@ bool EventState::handleKey(math::Vec pos, int key, int scancode, int action, int
eSelectKey.context = &cSelectKey;
eSelectKey.key = key;
eSelectKey.scancode = scancode;
const char* keyName = glfwGetKeyName(key, scancode);
const char* keyName = glfwGetKeyName(key, GLFW_KEY_UNKNOWN);
if (keyName)
eSelectKey.keyName = keyName;
eSelectKey.action = action;
@@ -381,7 +401,7 @@ bool EventState::handleKey(math::Vec pos, int key, int scancode, int action, int
eHoverKey.pos = pos;
eHoverKey.key = key;
eHoverKey.scancode = scancode;
const char* keyName = glfwGetKeyName(key, scancode);
const char* keyName = glfwGetKeyName(key, GLFW_KEY_UNKNOWN);
if (keyName)
eHoverKey.keyName = keyName;
eHoverKey.action = action;


Loading…
Cancel
Save