Completely untested right nowpull/24/head
| @@ -19,6 +19,10 @@ | |||||
| #include "Geometry.hpp" | #include "Geometry.hpp" | ||||
| START_NAMESPACE_DISTRHO | |||||
| class UIExporter; | |||||
| END_NAMESPACE_DISTRHO | |||||
| START_NAMESPACE_DGL | START_NAMESPACE_DGL | ||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| @@ -119,11 +123,15 @@ private: | |||||
| friend class Application; | friend class Application; | ||||
| friend class Widget; | friend class Widget; | ||||
| friend class StandaloneWindow; | friend class StandaloneWindow; | ||||
| friend class DISTRHO_NAMESPACE::UIExporter; | |||||
| virtual void _addWidget(Widget* const widget); | virtual void _addWidget(Widget* const widget); | ||||
| virtual void _removeWidget(Widget* const widget); | virtual void _removeWidget(Widget* const widget); | ||||
| void _idle(); | 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) | 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; | Application& fApp; | ||||
| Window* fSelf; | Window* fSelf; | ||||
| PuglView* fView; | 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() | StandaloneWindow::StandaloneWindow() | ||||
| @@ -52,6 +52,8 @@ | |||||
| #define effGetProgramNameIndexed 29 | #define effGetProgramNameIndexed 29 | ||||
| #define effGetPlugCategory 35 | #define effGetPlugCategory 35 | ||||
| #define effIdle 53 | #define effIdle 53 | ||||
| #define effEditKeyDown 59 | |||||
| #define effEditKeyUp 60 | |||||
| #define kPlugCategEffect 1 | #define kPlugCategEffect 1 | ||||
| #define kPlugCategSynth 2 | #define kPlugCategSynth 2 | ||||
| #define kVstVersion 2400 | #define kVstVersion 2400 | ||||
| @@ -167,6 +169,56 @@ public: | |||||
| } | } | ||||
| # endif | # 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: | protected: | ||||
| @@ -499,6 +551,16 @@ public: | |||||
| if (fVstUI != nullptr) | if (fVstUI != nullptr) | ||||
| fVstUI->idle(); | fVstUI->idle(); | ||||
| break; | 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 | #endif // DISTRHO_PLUGIN_HAS_UI | ||||
| #if DISTRHO_PLUGIN_WANT_STATE | #if DISTRHO_PLUGIN_WANT_STATE | ||||
| @@ -416,6 +416,16 @@ public: | |||||
| return ! glApp.isQuiting(); | 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 | #else | ||||
| void setWindowSize(const uint width, const uint height, const bool updateUI = false) {} | void setWindowSize(const uint width, const uint height, const bool updateUI = false) {} | ||||
| void setWindowTransientWinId(const uintptr_t winId) {} | void setWindowTransientWinId(const uintptr_t winId) {} | ||||