diff --git a/dgl/Window.hpp b/dgl/Window.hpp index 25fa9b27..28d21a26 100644 --- a/dgl/Window.hpp +++ b/dgl/Window.hpp @@ -19,6 +19,10 @@ #include "Geometry.hpp" +START_NAMESPACE_DISTRHO +class UIExporter; +END_NAMESPACE_DISTRHO + START_NAMESPACE_DGL // ----------------------------------------------------------------------- @@ -119,11 +123,15 @@ private: friend class Application; friend class Widget; friend class StandaloneWindow; + friend class DISTRHO_NAMESPACE::UIExporter; virtual void _addWidget(Widget* const widget); virtual void _removeWidget(Widget* const widget); void _idle(); + bool handlePluginKeyboard(const bool press, const uint key); + bool handlePluginSpecial(const bool press, const Key key); + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Window) }; diff --git a/dgl/src/Window.cpp b/dgl/src/Window.cpp index 784fe89e..059eae89 100644 --- a/dgl/src/Window.cpp +++ b/dgl/src/Window.cpp @@ -845,6 +845,90 @@ struct Window::PrivateData { // ------------------------------------------------------------------- + bool handlePluginKeyboard(const bool press, const uint key) + { + DBGp("PUGL: handlePluginKeyboard : %i %i\n", press, key); + + if (fModal.childFocus != nullptr) + { + fModal.childFocus->focus(); + return true; + } + + Widget::KeyboardEvent ev; + ev.press = press; + ev.key = key; + ev.mod = static_cast(fView->mods); + ev.time = 0; + + if ((ev.mod & kModifierShift) != 0 && ev.key >= 'a' && ev.key <= 'z') + ev.key -= 'a' - 'A'; // a-z -> A-Z + + FOR_EACH_WIDGET_INV(rit) + { + Widget* const widget(*rit); + + if (widget->isVisible() && widget->onKeyboard(ev)) + return true; + } + + return false; + } + + bool handlePluginSpecial(const bool press, const Key key) + { + DBGp("PUGL: handlePluginSpecial : %i %i\n", press, key); + + if (fModal.childFocus != nullptr) + { + fModal.childFocus->focus(); + return true; + } + + int mods = 0x0; + + switch (key) + { + case kKeyShift: + mods |= kModifierShift; + break; + case kKeyControl: + mods |= kModifierControl; + break; + case kKeyAlt: + mods |= kModifierAlt; + break; + default: + break; + } + + if (mods != 0x0) + { + if (press) + fView->mods |= mods; + else + fView->mods &= ~(mods); + } + + Widget::SpecialEvent ev; + ev.press = press; + ev.key = key; + ev.mod = static_cast(fView->mods); + ev.time = 0; + + FOR_EACH_WIDGET_INV(rit) + { + Widget* const widget(*rit); + + if (widget->isVisible() && widget->onSpecial(ev)) + return true; + } + + return false; + } + + // ------------------------------------------------------------------- + Application& fApp; Window* fSelf; PuglView* fView; @@ -1200,6 +1284,16 @@ void Window::fileBrowserSelected(const char*) { } +bool Window::handlePluginKeyboard(const bool press, const uint key) +{ + return pData->handlePluginKeyboard(press, key); +} + +bool Window::handlePluginSpecial(const bool press, const Key key) +{ + return pData->handlePluginSpecial(press, key); +} + // ----------------------------------------------------------------------- StandaloneWindow::StandaloneWindow() diff --git a/distrho/src/DistrhoPluginVST.cpp b/distrho/src/DistrhoPluginVST.cpp index 2956021c..ce78b265 100644 --- a/distrho/src/DistrhoPluginVST.cpp +++ b/distrho/src/DistrhoPluginVST.cpp @@ -52,6 +52,8 @@ #define effGetProgramNameIndexed 29 #define effGetPlugCategory 35 #define effIdle 53 +#define effEditKeyDown 59 +#define effEditKeyUp 60 #define kPlugCategEffect 1 #define kPlugCategSynth 2 #define kVstVersion 2400 @@ -167,6 +169,56 @@ public: } # endif + int handlePluginKeyEvent(const bool down, int32_t index, const intptr_t value) + { + d_stdout("handlePluginKeyEvent %i %i %li\n", down, index, (long int)value); + + int special = 0; + switch (value) + { + // special casing (can be combined with normal keys) + case 54: fUI.handlePluginSpecial(down, kKeyShift); break; + case 55: fUI.handlePluginSpecial(down, kKeyControl); break; + case 56: fUI.handlePluginSpecial(down, kKeyAlt); break; + + // convert some specials to normal keys + case 1: index = kCharBackspace; break; + case 6: index = kCharEscape; break; + case 22: index = kCharDelete; break; + + // handle rest of special keys + case 40: special = kKeyF1; break; + case 41: special = kKeyF2; break; + case 42: special = kKeyF3; break; + case 43: special = kKeyF4; break; + case 44: special = kKeyF5; break; + case 45: special = kKeyF6; break; + case 46: special = kKeyF7; break; + case 47: special = kKeyF8; break; + case 48: special = kKeyF9; break; + case 49: special = kKeyF10; break; + case 50: special = kKeyF11; break; + case 51: special = kKeyF12; break; + case 11: special = kKeyLeft; break; + case 12: special = kKeyUp; break; + case 13: special = kKeyRight; break; + case 14: special = kKeyDown; break; + case 15: special = kKeyPageUp; break; + case 16: special = kKeyPageDown; break; + case 10: special = kKeyHome; break; + case 9: special = kKeyEnd; break; + case 21: special = kKeyInsert; break; + } + + if (special != 0) + return fUI.handlePluginSpecial(down, static_cast(special)); + + if (index >= 0) + return fUI.handlePluginKeyboard(down, static_cast(index)); + + return 0; + } + // ------------------------------------------------------------------- protected: @@ -499,6 +551,16 @@ public: if (fVstUI != nullptr) fVstUI->idle(); break; + + case effEditKeyDown: + if (fVstUI != nullptr) + return fVstUI->handlePluginKeyEvent(true, index, value); + break; + + case effEditKeyUp: + if (fVstUI != nullptr) + return fVstUI->handlePluginKeyEvent(false, index, value); + break; #endif // DISTRHO_PLUGIN_HAS_UI #if DISTRHO_PLUGIN_WANT_STATE diff --git a/distrho/src/DistrhoUIInternal.hpp b/distrho/src/DistrhoUIInternal.hpp index f771781b..a4c64ca5 100644 --- a/distrho/src/DistrhoUIInternal.hpp +++ b/distrho/src/DistrhoUIInternal.hpp @@ -416,6 +416,16 @@ public: return ! glApp.isQuiting(); } + + bool handlePluginKeyboard(const bool press, const uint key) + { + return glWindow.handlePluginKeyboard(press, key); + } + + bool handlePluginSpecial(const bool press, const Key key) + { + return glWindow.handlePluginKeyboard(press, key); + } #else void setWindowSize(const uint width, const uint height, const bool updateUI = false) {} void setWindowTransientWinId(const uintptr_t winId) {}