Completely untested right nowpull/20/merge
| @@ -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) | |||
| }; | |||
| @@ -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<Modifier>(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<Modifier>(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() | |||
| @@ -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<Key>(special)); | |||
| if (index >= 0) | |||
| return fUI.handlePluginKeyboard(down, static_cast<uint>(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 | |||
| @@ -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) {} | |||