| @@ -42,7 +42,7 @@ public: | |||
| Constructor. | |||
| */ | |||
| NtkApp() | |||
| : fIsRunning(false), | |||
| : fIsRunning(true), | |||
| fWindows() | |||
| { | |||
| static bool initialized = false; | |||
| @@ -51,7 +51,9 @@ public: | |||
| { | |||
| initialized = true; | |||
| fl_register_images(); | |||
| #ifdef DISTRHO_OS_LINUX | |||
| fl_open_display(); | |||
| #endif | |||
| } | |||
| } | |||
| @@ -67,7 +69,7 @@ public: | |||
| /** | |||
| Idle function. | |||
| This calls the NTK event-loop once. | |||
| This calls the NTK event-loop once (and all idle callbacks). | |||
| */ | |||
| void idle() | |||
| { | |||
| @@ -115,6 +117,28 @@ private: | |||
| friend class NtkWindow; | |||
| /** @internal used by NtkWindow. */ | |||
| void addWindow(Fl_Double_Window* const window) | |||
| { | |||
| DISTRHO_SAFE_ASSERT_RETURN(window != nullptr,); | |||
| if (fWindows.size() == 0) | |||
| fIsRunning = true; | |||
| fWindows.push_back(window); | |||
| } | |||
| /** @internal used by NtkWindow. */ | |||
| void removeWindow(Fl_Double_Window* const window) | |||
| { | |||
| DISTRHO_SAFE_ASSERT_RETURN(window != nullptr,); | |||
| fWindows.remove(window); | |||
| if (fWindows.size() == 0) | |||
| fIsRunning = false; | |||
| } | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NtkApp) | |||
| }; | |||
| @@ -19,8 +19,6 @@ | |||
| #include "NtkWindow.hpp" | |||
| #include "../Geometry.hpp" | |||
| START_NAMESPACE_DGL | |||
| // ----------------------------------------------------------------------- | |||
| @@ -29,16 +27,18 @@ START_NAMESPACE_DGL | |||
| DGL compatible Widget class that uses NTK instead of OpenGL. | |||
| @see Widget | |||
| */ | |||
| class NtkWidget : public Fl_Group | |||
| class NtkWidget : public Fl_Double_Window | |||
| { | |||
| public: | |||
| /** | |||
| Constructor. | |||
| */ | |||
| explicit NtkWidget(NtkWindow& parent) | |||
| : Fl_Group(0, 0, 0, 0), | |||
| : Fl_Double_Window(100, 100), | |||
| fParent(parent) | |||
| { | |||
| fParent.add(this); | |||
| show(); | |||
| } | |||
| /** | |||
| @@ -46,6 +46,181 @@ public: | |||
| */ | |||
| ~NtkWidget() override | |||
| { | |||
| hide(); | |||
| fParent.remove(this); | |||
| } | |||
| /** | |||
| Check if this widget is visible within its parent window. | |||
| Invisible widgets do not receive events except resize. | |||
| */ | |||
| bool isVisible() const | |||
| { | |||
| return visible(); | |||
| } | |||
| /** | |||
| Set widget visible (or not) according to @a yesNo. | |||
| */ | |||
| void setVisible(bool yesNo) | |||
| { | |||
| if (yesNo) | |||
| show(); | |||
| else | |||
| hide(); | |||
| } | |||
| /** | |||
| Get width. | |||
| */ | |||
| int getWidth() const | |||
| { | |||
| return w(); | |||
| } | |||
| /** | |||
| Get height. | |||
| */ | |||
| int getHeight() const | |||
| { | |||
| return h(); | |||
| } | |||
| /** | |||
| Get size. | |||
| */ | |||
| Size<int> getSize() const | |||
| { | |||
| return Size<int>(w(), h()); | |||
| } | |||
| /** | |||
| Set width. | |||
| */ | |||
| void setWidth(int width) | |||
| { | |||
| resize(x(), y(), width, h()); | |||
| } | |||
| /** | |||
| Set height. | |||
| */ | |||
| void setHeight(int height) | |||
| { | |||
| resize(x(), y(), w(), height); | |||
| } | |||
| /** | |||
| Set size using @a width and @a height values. | |||
| */ | |||
| void setSize(int width, int height) | |||
| { | |||
| resize(x(), y(), width, height); | |||
| } | |||
| /** | |||
| Set size. | |||
| */ | |||
| void setSize(const Size<int>& size) | |||
| { | |||
| resize(x(), y(), size.getWidth(), size.getHeight()); | |||
| } | |||
| /** | |||
| Get absolute X. | |||
| */ | |||
| int getAbsoluteX() const | |||
| { | |||
| return x(); | |||
| } | |||
| /** | |||
| Get absolute Y. | |||
| */ | |||
| int getAbsoluteY() const | |||
| { | |||
| return y(); | |||
| } | |||
| /** | |||
| Get absolute position. | |||
| */ | |||
| Point<int> getAbsolutePos() const | |||
| { | |||
| return Point<int>(x(), y()); | |||
| } | |||
| /** | |||
| Set absolute X. | |||
| */ | |||
| void setAbsoluteX(int x) | |||
| { | |||
| resize(x, y(), w(), h()); | |||
| } | |||
| /** | |||
| Set absolute Y. | |||
| */ | |||
| void setAbsoluteY(int y) | |||
| { | |||
| resize(x(), y, w(), h()); | |||
| } | |||
| /** | |||
| Set absolute position using @a x and @a y values. | |||
| */ | |||
| void setAbsolutePos(int x, int y) | |||
| { | |||
| resize(x, y, w(), h()); | |||
| } | |||
| /** | |||
| Set absolute position. | |||
| */ | |||
| void setAbsolutePos(const Point<int>& pos) | |||
| { | |||
| resize(pos.getX(), pos.getY(), w(), h()); | |||
| } | |||
| /** | |||
| Get this widget's window application. | |||
| Same as calling getParentWindow().getApp(). | |||
| */ | |||
| NtkApp& getParentApp() const noexcept | |||
| { | |||
| return fParent.getApp(); | |||
| } | |||
| /** | |||
| Get parent window, as passed in the constructor. | |||
| */ | |||
| NtkWindow& getParentWindow() const noexcept | |||
| { | |||
| return fParent; | |||
| } | |||
| /** | |||
| Check if this widget contains the point defined by @a x and @a y. | |||
| */ | |||
| bool contains(int x, int y) const | |||
| { | |||
| return (x >= 0 && y >= 0 && x < w() && y < h()); | |||
| } | |||
| /** | |||
| Check if this widget contains the point @a pos. | |||
| */ | |||
| bool contains(const Point<int>& pos) const | |||
| { | |||
| return contains(pos.getX(), pos.getY()); | |||
| } | |||
| /** | |||
| Tell this widget's window to repaint itself. | |||
| */ | |||
| void repaint() | |||
| { | |||
| redraw(); | |||
| } | |||
| protected: | |||
| @@ -19,6 +19,8 @@ | |||
| #include "NtkApp.hpp" | |||
| #include "../Geometry.hpp" | |||
| START_NAMESPACE_DGL | |||
| class NtkWidget; | |||
| @@ -31,59 +33,147 @@ public: | |||
| explicit NtkWindow(NtkApp& app) | |||
| : Fl_Double_Window(100, 100), | |||
| fApp(app), | |||
| fIsVisible(false), | |||
| fUsingEmbed(false), | |||
| fParent(nullptr), | |||
| fWidgets() {} | |||
| fParent(nullptr) {} | |||
| explicit NtkWindow(NtkApp& app, NtkWindow& parent) | |||
| : Fl_Double_Window(100, 100), | |||
| fApp(app), | |||
| fIsVisible(false), | |||
| fUsingEmbed(false), | |||
| fParent(&parent), | |||
| fWidgets() {} | |||
| fParent(&parent) {} | |||
| explicit NtkWindow(NtkApp& app, intptr_t parentId) | |||
| : Fl_Double_Window(100, 100), | |||
| fApp(app), | |||
| fIsVisible(parentId != 0), | |||
| fUsingEmbed(parentId != 0), | |||
| fParent(nullptr), | |||
| fWidgets() | |||
| fParent(nullptr) | |||
| { | |||
| if (fUsingEmbed) | |||
| { | |||
| fl_embed(this, (Window)parentId); | |||
| Fl_Double_Window::show(); | |||
| fApp.addWindow(this); | |||
| } | |||
| } | |||
| ~NtkWindow() override | |||
| { | |||
| fWidgets.clear(); | |||
| if (fUsingEmbed) | |||
| { | |||
| fApp.removeWindow(this); | |||
| Fl_Double_Window::hide(); | |||
| } | |||
| } | |||
| void show() | |||
| void show() override | |||
| { | |||
| if (fUsingEmbed || fIsVisible) | |||
| return; | |||
| Fl_Double_Window::show(); | |||
| fApp.addWindow(this); | |||
| fIsVisible = true; | |||
| #ifdef DISTRHO_OS_LINUX | |||
| if (fParent == nullptr) | |||
| if (fParent != nullptr) | |||
| setTransientWinId((intptr_t)fl_xid(fParent)); | |||
| } | |||
| void hide() override | |||
| { | |||
| if (fUsingEmbed || ! fIsVisible) | |||
| return; | |||
| fIsVisible = false; | |||
| fApp.removeWindow(this); | |||
| Fl_Double_Window::hide(); | |||
| } | |||
| void close() | |||
| { | |||
| hide(); | |||
| } | |||
| bool isVisible() const | |||
| { | |||
| return visible(); | |||
| } | |||
| void setVisible(bool yesNo) | |||
| { | |||
| if (yesNo) | |||
| show(); | |||
| else | |||
| hide(); | |||
| } | |||
| bool isResizable() const | |||
| { | |||
| // TODO | |||
| return false; | |||
| } | |||
| void setResizable(bool /*yesNo*/) | |||
| { | |||
| // TODO | |||
| } | |||
| int getWidth() const noexcept | |||
| { | |||
| return w(); | |||
| } | |||
| int getHeight() const noexcept | |||
| { | |||
| return h(); | |||
| } | |||
| Size<uint> getSize() const noexcept | |||
| { | |||
| return Size<uint>(w(), h()); | |||
| } | |||
| void setSize(uint width, uint height) | |||
| { | |||
| resize(x(), y(), width, height); | |||
| } | |||
| void setSize(Size<uint> size) | |||
| { | |||
| resize(x(), y(), size.getWidth(), size.getHeight()); | |||
| } | |||
| void setTitle(const char* title) | |||
| { | |||
| label(title); | |||
| } | |||
| void setTransientWinId(intptr_t winId) | |||
| { | |||
| DISTRHO_SAFE_ASSERT_RETURN(winId != 0,); | |||
| #ifdef DISTRHO_OS_LINUX | |||
| DISTRHO_SAFE_ASSERT_RETURN(fl_display != nullptr,); | |||
| const ::Window ourWindow(fl_xid_(this)); | |||
| const ::Window ourWindow(fl_xid(this)); | |||
| DISTRHO_SAFE_ASSERT_RETURN(ourWindow != 0,); | |||
| const ::Window parentWindow(fl_xid_(fParent)); | |||
| DISTRHO_SAFE_ASSERT_RETURN(parentWindow != 0,); | |||
| XSetTransientForHint(fl_display, ourWindow, parentWindow); | |||
| XSetTransientForHint(fl_display, ourWindow, winId); | |||
| #endif | |||
| } | |||
| NtkApp& getApp() const noexcept | |||
| { | |||
| return fApp; | |||
| } | |||
| intptr_t getWindowId() const | |||
| { | |||
| return (intptr_t)fl_xid(this); | |||
| } | |||
| void addIdleCallback(IdleCallback* const callback) | |||
| { | |||
| DISTRHO_SAFE_ASSERT_RETURN(callback != nullptr,); | |||
| @@ -106,12 +196,12 @@ public: | |||
| private: | |||
| NtkApp& fApp; | |||
| bool fIsVisible; | |||
| bool fUsingEmbed; | |||
| // transient parent, may be null | |||
| NtkWindow* const fParent; | |||
| std::list<Fl_Group*> fWidgets; | |||
| std::list<IdleCallback*> fIdleCallbacks; | |||
| friend class NtkWidget; | |||
| @@ -95,7 +95,11 @@ protected: | |||
| // UI Callbacks (optional) | |||
| virtual void d_uiIdle() {} | |||
| #if ! DISTRHO_UI_USE_NTK | |||
| // updates window openGL state | |||
| virtual void d_uiReshape(int width, int height); | |||
| #endif | |||
| // ------------------------------------------------------------------- | |||
| @@ -106,6 +110,7 @@ private: | |||
| friend class UIExporterWindow; | |||
| // these should not be used | |||
| void position(int, int) noexcept {} | |||
| void setAbsoluteX(int) const noexcept {} | |||
| void setAbsoluteY(int) const noexcept {} | |||
| void setAbsolutePos(int, int) const noexcept {} | |||
| @@ -98,9 +98,9 @@ void UI::d_sampleRateChanged(double) {} | |||
| // ----------------------------------------------------------------------- | |||
| // UI Callbacks (optional) | |||
| #if ! DISTRHO_UI_USE_NTK | |||
| void UI::d_uiReshape(int width, int height) | |||
| { | |||
| #if ! DISTRHO_UI_USE_NTK | |||
| glEnable(GL_BLEND); | |||
| glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |||
| glMatrixMode(GL_PROJECTION); | |||
| @@ -109,10 +109,8 @@ void UI::d_uiReshape(int width, int height) | |||
| glViewport(0, 0, width, height); | |||
| glMatrixMode(GL_MODELVIEW); | |||
| glLoadIdentity(); | |||
| #else | |||
| (void)width; (void)height; | |||
| #endif | |||
| } | |||
| #endif | |||
| // ----------------------------------------------------------------------- | |||
| @@ -157,17 +157,15 @@ public: | |||
| { | |||
| DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); | |||
| #if ! DISTRHO_UI_USE_NTK | |||
| const int width = fUI->d_getWidth(); | |||
| const int height = fUI->d_getHeight(); | |||
| // set widget size | |||
| fUI->setSize(width, height); | |||
| // set this window size | |||
| // set window size | |||
| setResizable(false); | |||
| setSize(width, height); | |||
| #endif | |||
| } | |||
| ~UIExporterWindow() | |||
| @@ -185,8 +183,14 @@ public: | |||
| return fIsReady; | |||
| } | |||
| #if ! DISTRHO_UI_USE_NTK | |||
| protected: | |||
| #if DISTRHO_UI_USE_NTK | |||
| void resize(int x, int y, int width, int height) override | |||
| { | |||
| UIWindow::resize(x, y, width, height); | |||
| fIsReady = true; | |||
| } | |||
| #else | |||
| void onReshape(int width, int height) override | |||
| { | |||
| DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); | |||
| @@ -292,7 +296,6 @@ public: | |||
| } | |||
| #endif | |||
| #if ! DISTRHO_UI_USE_NTK | |||
| // ------------------------------------------------------------------- | |||
| void exec(IdleCallback* const cb) | |||
| @@ -355,7 +358,6 @@ public: | |||
| return ! glApp.isQuiting(); | |||
| } | |||
| #endif | |||
| void setSampleRate(const double sampleRate, const bool doCallback = false) | |||
| { | |||