@@ -111,13 +111,37 @@ struct PositionBase { | |||||
/** An event prototype with a GLFW key. */ | /** An event prototype with a GLFW key. */ | ||||
struct KeyBase { | struct KeyBase { | ||||
/** GLFW_KEY_* */ | |||||
/** The key corresponding to what it would be called in its position on a QWERTY US keyboard. | |||||
For example, the WASD directional keys used for first-person shooters will always be reported as "WASD", regardless if they say "ZQSD" on an AZERTY keyboard. | |||||
You should usually not use these for printable characters such as "Ctrl+V" key commands. Instead, use `keyName`. | |||||
You *should* use these for non-printable keys, such as Escape, arrow keys, Home, F1-12, etc. | |||||
You should also use this for Enter, Tab, and Space. Although they are printable keys, they do not appear in `keyName`. | |||||
See GLFW_KEY_* for the list of possible values. | |||||
*/ | |||||
int key; | int key; | ||||
/** GLFW_KEY_*. You should usually use `key` instead. */ | |||||
/** Platform-dependent "software" key code. | |||||
This variable is only included for completion. There should be no reason for you to use this. | |||||
You should instead use `key` (for non-printable characters) or `keyName` (for printable characters). | |||||
Values are platform independent and can change between different keyboards or keyboard layouts on the same OS. | |||||
*/ | |||||
int scancode; | int scancode; | ||||
/** GLFW_RELEASE, GLFW_PRESS, GLFW_REPEAT, or RACK_HELD */ | |||||
/** String containing the lowercase key name, if it produces a printable character. | |||||
This is the only variable that correctly represents the label printed on any keyboard layout, whether it's QWERTY, AZERTY, QWERTZ, Dvorak, etc. | |||||
For example, if the user presses the key labeled "q" regardless of the key position, `keyName` will be "q". | |||||
For non-printable characters this is an empty string. | |||||
Enter, Tab, and Space do not give a `keyName`. Use `key` instead. | |||||
Shift has no effect on the key name. Shift+1 results in "1", Shift+q results in "q", etc. | |||||
*/ | |||||
std::string keyName; | |||||
/** The type of event occurring with the key. | |||||
Possible values are GLFW_RELEASE, GLFW_PRESS, GLFW_REPEAT, or RACK_HELD. | |||||
RACK_HELD is sent every frame while the key is held. | |||||
*/ | |||||
int action; | int action; | ||||
/** GLFW_MOD_* */ | |||||
/** Bitwise OR of key modifiers, such as Ctrl or Shift. | |||||
Use (mods & RACK_MOD_MASK) == RACK_MOD_CTRL to check for Ctrl on Linux and Windows but Cmd on Mac. | |||||
See GLFW_MOD_* for the list of possible values. | |||||
*/ | |||||
int mods; | int mods; | ||||
}; | }; | ||||
@@ -623,19 +623,17 @@ inline void TagItem::step() { | |||||
inline void BrowserSearchField::onSelectKey(const event::SelectKey& e) { | inline void BrowserSearchField::onSelectKey(const event::SelectKey& e) { | ||||
if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { | if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { | ||||
switch (e.key) { | |||||
case GLFW_KEY_ESCAPE: { | |||||
BrowserOverlay* overlay = getAncestorOfType<BrowserOverlay>(); | |||||
overlay->hide(); | |||||
if (e.key == GLFW_KEY_ESCAPE) { | |||||
BrowserOverlay* overlay = getAncestorOfType<BrowserOverlay>(); | |||||
overlay->hide(); | |||||
e.consume(this); | |||||
} | |||||
if (e.key == GLFW_KEY_BACKSPACE) { | |||||
if (text == "") { | |||||
ModuleBrowser* browser = getAncestorOfType<ModuleBrowser>(); | |||||
browser->clear(); | |||||
e.consume(this); | e.consume(this); | ||||
} break; | |||||
case GLFW_KEY_BACKSPACE: { | |||||
if (text == "") { | |||||
ModuleBrowser* browser = getAncestorOfType<ModuleBrowser>(); | |||||
browser->clear(); | |||||
e.consume(this); | |||||
} | |||||
} break; | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -397,61 +397,40 @@ void ModuleWidget::onHoverKey(const event::HoverKey& e) { | |||||
return; | return; | ||||
if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { | if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { | ||||
switch (e.key) { | |||||
case GLFW_KEY_I: { | |||||
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
resetAction(); | |||||
e.consume(this); | |||||
} | |||||
} break; | |||||
case GLFW_KEY_R: { | |||||
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
randomizeAction(); | |||||
e.consume(this); | |||||
} | |||||
} break; | |||||
case GLFW_KEY_C: { | |||||
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
copyClipboard(); | |||||
e.consume(this); | |||||
} | |||||
} break; | |||||
case GLFW_KEY_V: { | |||||
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
pasteClipboardAction(); | |||||
e.consume(this); | |||||
} | |||||
} break; | |||||
case GLFW_KEY_D: { | |||||
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
cloneAction(); | |||||
e.consume(this); | |||||
} | |||||
} break; | |||||
case GLFW_KEY_U: { | |||||
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
disconnectAction(); | |||||
e.consume(this); | |||||
} | |||||
} break; | |||||
case GLFW_KEY_E: { | |||||
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
bypassAction(); | |||||
e.consume(this); | |||||
} | |||||
} break; | |||||
if (e.keyName == "i" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
resetAction(); | |||||
e.consume(this); | |||||
} | |||||
if (e.keyName == "r" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
randomizeAction(); | |||||
e.consume(this); | |||||
} | |||||
if (e.keyName == "c" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
copyClipboard(); | |||||
e.consume(this); | |||||
} | |||||
if (e.keyName == "v" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
pasteClipboardAction(); | |||||
e.consume(this); | |||||
} | |||||
if (e.keyName == "d" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
cloneAction(); | |||||
e.consume(this); | |||||
} | |||||
if (e.keyName == "u" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
disconnectAction(); | |||||
e.consume(this); | |||||
} | |||||
if (e.keyName == "e" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
bypassAction(); | |||||
e.consume(this); | |||||
} | } | ||||
} | } | ||||
if (e.action == RACK_HELD) { | if (e.action == RACK_HELD) { | ||||
switch (e.key) { | |||||
case GLFW_KEY_DELETE: | |||||
case GLFW_KEY_BACKSPACE: { | |||||
if ((e.mods & RACK_MOD_MASK) == 0) { | |||||
removeAction(); | |||||
e.consume(NULL); | |||||
} | |||||
} break; | |||||
if ((e.key == GLFW_KEY_DELETE || e.key == GLFW_KEY_BACKSPACE) && (e.mods & RACK_MOD_MASK) == 0) { | |||||
removeAction(); | |||||
e.consume(NULL); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -108,23 +108,21 @@ void RackScrollWidget::onHoverKey(const event::HoverKey& e) { | |||||
arrowSpeed /= 4.0; | arrowSpeed /= 4.0; | ||||
if (e.action == RACK_HELD) { | if (e.action == RACK_HELD) { | ||||
switch (e.key) { | |||||
case GLFW_KEY_LEFT: { | |||||
offset.x -= arrowSpeed; | |||||
e.consume(this); | |||||
} break; | |||||
case GLFW_KEY_RIGHT: { | |||||
offset.x += arrowSpeed; | |||||
e.consume(this); | |||||
} break; | |||||
case GLFW_KEY_UP: { | |||||
offset.y -= arrowSpeed; | |||||
e.consume(this); | |||||
} break; | |||||
case GLFW_KEY_DOWN: { | |||||
offset.y += arrowSpeed; | |||||
e.consume(this); | |||||
} break; | |||||
if (e.key == GLFW_KEY_LEFT) { | |||||
offset.x -= arrowSpeed; | |||||
e.consume(this); | |||||
} | |||||
if (e.key == GLFW_KEY_RIGHT) { | |||||
offset.x += arrowSpeed; | |||||
e.consume(this); | |||||
} | |||||
if (e.key == GLFW_KEY_UP) { | |||||
offset.y -= arrowSpeed; | |||||
e.consume(this); | |||||
} | |||||
if (e.key == GLFW_KEY_DOWN) { | |||||
offset.y += arrowSpeed; | |||||
e.consume(this); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -121,13 +121,9 @@ void RackWidget::onHoverKey(const event::HoverKey& e) { | |||||
return; | return; | ||||
if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { | if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { | ||||
switch (e.key) { | |||||
case GLFW_KEY_V: { | |||||
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
pastePresetClipboardAction(); | |||||
e.consume(this); | |||||
} | |||||
} break; | |||||
if (e.keyName == "v" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
pastePresetClipboardAction(); | |||||
e.consume(this); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -97,39 +97,40 @@ void Scene::onHoverKey(const event::HoverKey& e) { | |||||
return; | return; | ||||
if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { | if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { | ||||
if (e.key == GLFW_KEY_N && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
// DEBUG("key '%d '%c' scancode %d '%c' keyName '%s'", e.key, e.key, e.scancode, e.scancode, e.keyName.c_str()); | |||||
if (e.keyName == "n" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
APP->patch->loadTemplateDialog(); | APP->patch->loadTemplateDialog(); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_Q && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
if (e.keyName == "q" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
APP->window->close(); | APP->window->close(); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_O && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
if (e.keyName == "o" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
APP->patch->loadDialog(); | APP->patch->loadDialog(); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_O && (e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) { | |||||
if (e.keyName == "o" && (e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) { | |||||
APP->patch->revertDialog(); | APP->patch->revertDialog(); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_S && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
if (e.keyName == "s" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
APP->patch->saveDialog(); | APP->patch->saveDialog(); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_S && (e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) { | |||||
if (e.keyName == "s" && (e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) { | |||||
APP->patch->saveAsDialog(); | APP->patch->saveAsDialog(); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_Z && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
if (e.keyName == "z" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
APP->history->undo(); | APP->history->undo(); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_Z && (e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) { | |||||
if (e.keyName == "z" && (e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) { | |||||
APP->history->redo(); | APP->history->redo(); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if ((e.key == GLFW_KEY_MINUS || e.key == GLFW_KEY_KP_SUBTRACT) && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
if (e.keyName == "-" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
float zoom = settings::zoom; | float zoom = settings::zoom; | ||||
zoom *= 2; | zoom *= 2; | ||||
zoom = std::ceil(zoom - 0.01f) - 1; | zoom = std::ceil(zoom - 0.01f) - 1; | ||||
@@ -137,7 +138,8 @@ void Scene::onHoverKey(const event::HoverKey& e) { | |||||
settings::zoom = zoom; | settings::zoom = zoom; | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if ((e.key == GLFW_KEY_EQUAL || e.key == GLFW_KEY_KP_ADD) && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
// Numpad has a "+" key, but the main keyboard section hides it under "=" | |||||
if ((e.keyName == "=" || e.keyName == "+") && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
float zoom = settings::zoom; | float zoom = settings::zoom; | ||||
zoom *= 2; | zoom *= 2; | ||||
zoom = std::floor(zoom + 0.01f) + 1; | zoom = std::floor(zoom + 0.01f) + 1; | ||||
@@ -145,31 +147,31 @@ void Scene::onHoverKey(const event::HoverKey& e) { | |||||
settings::zoom = zoom; | settings::zoom = zoom; | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if ((e.key == GLFW_KEY_0 || e.key == GLFW_KEY_KP_0) && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
if ((e.keyName == "0") && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
settings::zoom = 0.f; | settings::zoom = 0.f; | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if ((e.key == GLFW_KEY_ENTER || e.key == GLFW_KEY_KP_ENTER) && (e.mods & RACK_MOD_MASK) == 0) { | |||||
if ((e.key == GLFW_KEY_ENTER || e.key == GLFW_KEY_KP_ENTER) && (e.mods & RACK_MOD_MASK) == 0) { | |||||
moduleBrowser->show(); | moduleBrowser->show(); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_F1 && (e.mods & RACK_MOD_MASK) == 0) { | |||||
if (e.key == GLFW_KEY_F1 && (e.mods & RACK_MOD_MASK) == 0) { | |||||
std::thread t([] { | std::thread t([] { | ||||
system::openBrowser("https://vcvrack.com/manual/"); | system::openBrowser("https://vcvrack.com/manual/"); | ||||
}); | }); | ||||
t.detach(); | t.detach(); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_F3 && (e.mods & RACK_MOD_MASK) == 0) { | |||||
if (e.key == GLFW_KEY_F3 && (e.mods & RACK_MOD_MASK) == 0) { | |||||
settings::cpuMeter ^= true; | settings::cpuMeter ^= true; | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_F11 && (e.mods & RACK_MOD_MASK) == 0) { | |||||
if (e.key == GLFW_KEY_F11 && (e.mods & RACK_MOD_MASK) == 0) { | |||||
APP->window->setFullScreen(!APP->window->isFullScreen()); | APP->window->setFullScreen(!APP->window->isFullScreen()); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
// Alternate key command for exiting fullscreen, since F11 doesn't work reliably on Mac due to "Show desktop" OS binding. | // Alternate key command for exiting fullscreen, since F11 doesn't work reliably on Mac due to "Show desktop" OS binding. | ||||
else if (e.key == GLFW_KEY_ESCAPE && (e.mods & RACK_MOD_MASK) == 0) { | |||||
if (e.key == GLFW_KEY_ESCAPE && (e.mods & RACK_MOD_MASK) == 0) { | |||||
if (APP->window->isFullScreen()) | if (APP->window->isFullScreen()) | ||||
APP->window->setFullScreen(false); | APP->window->setFullScreen(false); | ||||
e.consume(this); | e.consume(this); | ||||
@@ -303,6 +303,9 @@ bool State::handleKey(math::Vec pos, int key, int scancode, int action, int mods | |||||
eSelectKey.context = &cSelectKey; | eSelectKey.context = &cSelectKey; | ||||
eSelectKey.key = key; | eSelectKey.key = key; | ||||
eSelectKey.scancode = scancode; | eSelectKey.scancode = scancode; | ||||
const char* keyName = glfwGetKeyName(key, scancode); | |||||
if (keyName) | |||||
eSelectKey.keyName = keyName; | |||||
eSelectKey.action = action; | eSelectKey.action = action; | ||||
eSelectKey.mods = mods; | eSelectKey.mods = mods; | ||||
selectedWidget->onSelectKey(eSelectKey); | selectedWidget->onSelectKey(eSelectKey); | ||||
@@ -317,6 +320,9 @@ bool State::handleKey(math::Vec pos, int key, int scancode, int action, int mods | |||||
eHoverKey.pos = pos; | eHoverKey.pos = pos; | ||||
eHoverKey.key = key; | eHoverKey.key = key; | ||||
eHoverKey.scancode = scancode; | eHoverKey.scancode = scancode; | ||||
const char* keyName = glfwGetKeyName(key, scancode); | |||||
if (keyName) | |||||
eHoverKey.keyName = keyName; | |||||
eHoverKey.action = action; | eHoverKey.action = action; | ||||
eHoverKey.mods = mods; | eHoverKey.mods = mods; | ||||
rootWidget->onHoverKey(eHoverKey); | rootWidget->onHoverKey(eHoverKey); | ||||
@@ -122,34 +122,34 @@ void ScrollWidget::onHoverKey(const event::HoverKey& e) { | |||||
offset.y -= box.size.y * 0.5; | offset.y -= box.size.y * 0.5; | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_PAGE_UP && (e.mods & RACK_MOD_MASK) == GLFW_MOD_SHIFT) { | |||||
if (e.key == GLFW_KEY_PAGE_UP && (e.mods & RACK_MOD_MASK) == GLFW_MOD_SHIFT) { | |||||
offset.x -= box.size.x * 0.5; | offset.x -= box.size.x * 0.5; | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_PAGE_DOWN && (e.mods & RACK_MOD_MASK) == 0) { | |||||
if (e.key == GLFW_KEY_PAGE_DOWN && (e.mods & RACK_MOD_MASK) == 0) { | |||||
offset.y += box.size.y * 0.5; | offset.y += box.size.y * 0.5; | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_PAGE_DOWN && (e.mods & RACK_MOD_MASK) == GLFW_MOD_SHIFT) { | |||||
if (e.key == GLFW_KEY_PAGE_DOWN && (e.mods & RACK_MOD_MASK) == GLFW_MOD_SHIFT) { | |||||
offset.x += box.size.x * 0.5; | offset.x += box.size.x * 0.5; | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_HOME && (e.mods & RACK_MOD_MASK) == 0) { | |||||
if (e.key == GLFW_KEY_HOME && (e.mods & RACK_MOD_MASK) == 0) { | |||||
math::Rect containerBox = container->getChildrenBoundingBox(); | math::Rect containerBox = container->getChildrenBoundingBox(); | ||||
offset.y = containerBox.getTop(); | offset.y = containerBox.getTop(); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_HOME && (e.mods & RACK_MOD_MASK) == GLFW_MOD_SHIFT) { | |||||
if (e.key == GLFW_KEY_HOME && (e.mods & RACK_MOD_MASK) == GLFW_MOD_SHIFT) { | |||||
math::Rect containerBox = container->getChildrenBoundingBox(); | math::Rect containerBox = container->getChildrenBoundingBox(); | ||||
offset.x = containerBox.getLeft(); | offset.x = containerBox.getLeft(); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_END && (e.mods & RACK_MOD_MASK) == 0) { | |||||
if (e.key == GLFW_KEY_END && (e.mods & RACK_MOD_MASK) == 0) { | |||||
math::Rect containerBox = container->getChildrenBoundingBox(); | math::Rect containerBox = container->getChildrenBoundingBox(); | ||||
offset.y = containerBox.getBottom(); | offset.y = containerBox.getBottom(); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_END && (e.mods & RACK_MOD_MASK) == GLFW_MOD_SHIFT) { | |||||
if (e.key == GLFW_KEY_END && (e.mods & RACK_MOD_MASK) == GLFW_MOD_SHIFT) { | |||||
math::Rect containerBox = container->getChildrenBoundingBox(); | math::Rect containerBox = container->getChildrenBoundingBox(); | ||||
offset.x = containerBox.getRight(); | offset.x = containerBox.getRight(); | ||||
e.consume(this); | e.consume(this); | ||||
@@ -76,7 +76,7 @@ void TextField::onSelectKey(const event::SelectKey& e) { | |||||
} | } | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_DELETE && (e.mods & RACK_MOD_MASK) == 0) { | |||||
if (e.key == GLFW_KEY_DELETE && (e.mods & RACK_MOD_MASK) == 0) { | |||||
if (cursor == selection) { | if (cursor == selection) { | ||||
text.erase(cursor, 1); | text.erase(cursor, 1); | ||||
event::Change eChange; | event::Change eChange; | ||||
@@ -91,7 +91,7 @@ void TextField::onSelectKey(const event::SelectKey& e) { | |||||
} | } | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_LEFT) { | |||||
if (e.key == GLFW_KEY_LEFT) { | |||||
if (e.mods & RACK_MOD_CTRL) { | if (e.mods & RACK_MOD_CTRL) { | ||||
while (--cursor > 0) { | while (--cursor > 0) { | ||||
if (text[cursor - 1] == ' ') | if (text[cursor - 1] == ' ') | ||||
@@ -106,7 +106,7 @@ void TextField::onSelectKey(const event::SelectKey& e) { | |||||
} | } | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_RIGHT) { | |||||
if (e.key == GLFW_KEY_RIGHT) { | |||||
if (e.mods & RACK_MOD_CTRL) { | if (e.mods & RACK_MOD_CTRL) { | ||||
while (++cursor < (int) text.size()) { | while (++cursor < (int) text.size()) { | ||||
if (text[cursor] == ' ') | if (text[cursor] == ' ') | ||||
@@ -121,29 +121,29 @@ void TextField::onSelectKey(const event::SelectKey& e) { | |||||
} | } | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_HOME && (e.mods & RACK_MOD_MASK) == 0) { | |||||
if (e.key == GLFW_KEY_HOME && (e.mods & RACK_MOD_MASK) == 0) { | |||||
selection = cursor = 0; | selection = cursor = 0; | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_HOME && (e.mods & RACK_MOD_MASK) == GLFW_MOD_SHIFT) { | |||||
if (e.key == GLFW_KEY_HOME && (e.mods & RACK_MOD_MASK) == GLFW_MOD_SHIFT) { | |||||
cursor = 0; | cursor = 0; | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_END && (e.mods & RACK_MOD_MASK) == 0) { | |||||
if (e.key == GLFW_KEY_END && (e.mods & RACK_MOD_MASK) == 0) { | |||||
selection = cursor = text.size(); | selection = cursor = text.size(); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_END && (e.mods & RACK_MOD_MASK) == GLFW_MOD_SHIFT) { | |||||
if (e.key == GLFW_KEY_END && (e.mods & RACK_MOD_MASK) == GLFW_MOD_SHIFT) { | |||||
cursor = text.size(); | cursor = text.size(); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_V && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
if (e.keyName == "v" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
const char* newText = glfwGetClipboardString(APP->window->win); | const char* newText = glfwGetClipboardString(APP->window->win); | ||||
if (newText) | if (newText) | ||||
insertText(newText); | insertText(newText); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_X && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
if (e.keyName == "x" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
if (cursor != selection) { | if (cursor != selection) { | ||||
int begin = std::min(cursor, selection); | int begin = std::min(cursor, selection); | ||||
std::string selectedText = text.substr(begin, std::abs(selection - cursor)); | std::string selectedText = text.substr(begin, std::abs(selection - cursor)); | ||||
@@ -152,7 +152,7 @@ void TextField::onSelectKey(const event::SelectKey& e) { | |||||
} | } | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_C && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
if (e.keyName == "c" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
if (cursor != selection) { | if (cursor != selection) { | ||||
int begin = std::min(cursor, selection); | int begin = std::min(cursor, selection); | ||||
std::string selectedText = text.substr(begin, std::abs(selection - cursor)); | std::string selectedText = text.substr(begin, std::abs(selection - cursor)); | ||||
@@ -160,11 +160,11 @@ void TextField::onSelectKey(const event::SelectKey& e) { | |||||
} | } | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_A && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
if (e.keyName == "a" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
selectAll(); | selectAll(); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if ((e.key == GLFW_KEY_ENTER || e.key == GLFW_KEY_KP_ENTER) && (e.mods & RACK_MOD_MASK) == 0) { | |||||
if ((e.key == GLFW_KEY_ENTER || e.key == GLFW_KEY_KP_ENTER) && (e.mods & RACK_MOD_MASK) == 0) { | |||||
if (multiline) { | if (multiline) { | ||||
insertText("\n"); | insertText("\n"); | ||||
} | } | ||||
@@ -175,10 +175,10 @@ void TextField::onSelectKey(const event::SelectKey& e) { | |||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
// Consume all printable keys | // Consume all printable keys | ||||
else if ((GLFW_KEY_SPACE <= e.key && e.key <= GLFW_KEY_WORLD_2) || (GLFW_KEY_KP_0 <= e.key && e.key <= GLFW_KEY_KP_EQUAL)) { | |||||
if (e.keyName != "") { | |||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
else if (e.key == GLFW_KEY_ESCAPE && (e.mods & RACK_MOD_MASK) == 0) { | |||||
if (e.key == GLFW_KEY_ESCAPE && (e.mods & RACK_MOD_MASK) == 0) { | |||||
APP->event->setSelected(NULL); | APP->event->setSelected(NULL); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||