From c01e3a1c079812e1def34147941ac3b6878ba2b1 Mon Sep 17 00:00:00 2001 From: falkTX Date: Mon, 25 Feb 2013 07:28:41 +0000 Subject: [PATCH] Continue work for DISTRHO UI, now OpenGL --- source/libs/distrho/DistrhoUI.hpp | 5 - source/libs/distrho/DistrhoUIOpenGL.hpp | 70 +++ source/libs/distrho/DistrhoUIQt4.hpp | 2 +- source/libs/distrho/dgl/App.hpp | 45 ++ source/libs/distrho/dgl/Base.hpp | 79 +++ source/libs/distrho/dgl/Geometry.hpp | 131 +++++ source/libs/distrho/dgl/Image.hpp | 56 ++ source/libs/distrho/dgl/Widget.hpp | 54 ++ source/libs/distrho/dgl/Window.hpp | 65 +++ source/libs/distrho/dgl/src/App.cpp | 56 ++ source/libs/distrho/dgl/src/AppPrivate.hpp | 82 +++ source/libs/distrho/dgl/src/Geometry.cpp | 380 +++++++++++++ source/libs/distrho/dgl/src/Widget.cpp | 115 ++++ source/libs/distrho/dgl/src/Window.cpp | 497 ++++++++++++++++++ source/libs/distrho/dgl/src/pugl/pugl.h | 341 ++++++++++++ .../libs/distrho/dgl/src/pugl/pugl_internal.h | 135 +++++ source/libs/distrho/dgl/src/pugl/pugl_osx.m | 331 ++++++++++++ source/libs/distrho/dgl/src/pugl/pugl_win.cpp | 344 ++++++++++++ source/libs/distrho/dgl/src/pugl/pugl_x11.c | 379 +++++++++++++ source/libs/distrho/dgl/src/pugl/pugl_x11.h | 46 ++ source/libs/distrho/src/DistrhoUI.cpp | 4 +- source/libs/distrho/src/DistrhoUIInternal.hpp | 155 +++--- source/libs/distrho/src/DistrhoUIOpenGL.cpp | 41 ++ source/libs/distrho/src/DistrhoUIQt4.cpp | 7 - 24 files changed, 3327 insertions(+), 93 deletions(-) create mode 100644 source/libs/distrho/DistrhoUIOpenGL.hpp create mode 100644 source/libs/distrho/dgl/App.hpp create mode 100644 source/libs/distrho/dgl/Base.hpp create mode 100644 source/libs/distrho/dgl/Geometry.hpp create mode 100644 source/libs/distrho/dgl/Image.hpp create mode 100644 source/libs/distrho/dgl/Widget.hpp create mode 100644 source/libs/distrho/dgl/Window.hpp create mode 100644 source/libs/distrho/dgl/src/App.cpp create mode 100644 source/libs/distrho/dgl/src/AppPrivate.hpp create mode 100644 source/libs/distrho/dgl/src/Geometry.cpp create mode 100644 source/libs/distrho/dgl/src/Widget.cpp create mode 100644 source/libs/distrho/dgl/src/Window.cpp create mode 100644 source/libs/distrho/dgl/src/pugl/pugl.h create mode 100644 source/libs/distrho/dgl/src/pugl/pugl_internal.h create mode 100644 source/libs/distrho/dgl/src/pugl/pugl_osx.m create mode 100644 source/libs/distrho/dgl/src/pugl/pugl_win.cpp create mode 100644 source/libs/distrho/dgl/src/pugl/pugl_x11.c create mode 100644 source/libs/distrho/dgl/src/pugl/pugl_x11.h create mode 100644 source/libs/distrho/src/DistrhoUIOpenGL.cpp diff --git a/source/libs/distrho/DistrhoUI.hpp b/source/libs/distrho/DistrhoUI.hpp index 42072dd21..0475c5bcf 100644 --- a/source/libs/distrho/DistrhoUI.hpp +++ b/source/libs/distrho/DistrhoUI.hpp @@ -82,11 +82,6 @@ protected: private: UIPrivateData* const pData; friend class UIInternal; -#ifdef DISTRHO_UI_QT4 - friend class Qt4UI; -#else - friend class OpenGLUI; -#endif }; // ------------------------------------------------- diff --git a/source/libs/distrho/DistrhoUIOpenGL.hpp b/source/libs/distrho/DistrhoUIOpenGL.hpp new file mode 100644 index 000000000..d0ebeac91 --- /dev/null +++ b/source/libs/distrho/DistrhoUIOpenGL.hpp @@ -0,0 +1,70 @@ +/* + * DISTRHO Plugin Toolkit (DPT) + * Copyright (C) 2012-2013 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * For a full copy of the license see the LGPL.txt file + */ + +#ifndef __DISTRHO_UI_OPENGL_HPP__ +#define __DISTRHO_UI_OPENGL_HPP__ + +#include "DistrhoUI.hpp" + +#include "dgl/Widget.hpp" + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- +// OpenGL UI + +class OpenGLUI : public UI, + public Widget +{ +public: + OpenGLUI(); + virtual ~OpenGLUI(); + +protected: + // --------------------------------------------- + // Information + + virtual unsigned int d_width() const = 0; + virtual unsigned int d_height() const = 0; + + // --------------------------------------------- + // DSP Callbacks + + virtual void d_parameterChanged(uint32_t index, float value) = 0; +#if DISTRHO_PLUGIN_WANT_PROGRAMS + virtual void d_programChanged(uint32_t index) = 0; +#endif +#if DISTRHO_PLUGIN_WANT_STATE + virtual void d_stateChanged(const char* key, const char* value) = 0; +#endif +#if DISTRHO_PLUGIN_IS_SYNTH + virtual void d_noteReceived(bool onOff, uint8_t channel, uint8_t note, uint8_t velocity) = 0; +#endif + + // --------------------------------------------- + // UI Callbacks + + virtual void d_uiIdle() = 0; + +private: + friend class UIInternal; +}; + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // __DISTRHO_UI_OPENGL_HPP__ diff --git a/source/libs/distrho/DistrhoUIQt4.hpp b/source/libs/distrho/DistrhoUIQt4.hpp index e60bcf99b..119c690ac 100644 --- a/source/libs/distrho/DistrhoUIQt4.hpp +++ b/source/libs/distrho/DistrhoUIQt4.hpp @@ -58,7 +58,7 @@ protected: // --------------------------------------------- // UI Callbacks - virtual void d_uiIdle(); + virtual void d_uiIdle() {} private: friend class UIInternal; diff --git a/source/libs/distrho/dgl/App.hpp b/source/libs/distrho/dgl/App.hpp new file mode 100644 index 000000000..8a8c62e90 --- /dev/null +++ b/source/libs/distrho/dgl/App.hpp @@ -0,0 +1,45 @@ +/* + * DISTRHO Plugin Toolkit (DPT) + * Copyright (C) 2012-2013 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * For a full copy of the license see the LGPL.txt file + */ + +#ifndef __DGL_APP_HPP__ +#define __DGL_APP_HPP__ + +#include "Base.hpp" + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- + +class App +{ +public: + App(); + ~App(); + + void idle(); + void exec(); + +private: + class Private; + Private* const kPrivate; + friend class Window; +}; + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // __DGL_APP_HPP__ diff --git a/source/libs/distrho/dgl/Base.hpp b/source/libs/distrho/dgl/Base.hpp new file mode 100644 index 000000000..cdc10d6de --- /dev/null +++ b/source/libs/distrho/dgl/Base.hpp @@ -0,0 +1,79 @@ +/* + * DISTRHO Plugin Toolkit (DPT) + * Copyright (C) 2012-2013 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * For a full copy of the license see the LGPL.txt file + */ + +#ifndef __DGL_BASE_HPP__ +#define __DGL_BASE_HPP__ + +#include "../src/DistrhoDefines.h" + +#if DISTRHO_OS_MAC +# include +#else +# include +#endif + +#if defined(GL_BGR_EXT) && ! defined(GL_BGR) +# define GL_BGR GL_BGR_EXT +#endif + +#if defined(GL_BGRA_EXT) && ! defined(GL_BGRA) +# define GL_BGRA GL_BGRA_EXT +#endif + +// ------------------------------------------------- + +enum Char { + CHAR_BACKSPACE = 0x08, + CHAR_ESCAPE = 0x1B, + CHAR_DELETE = 0x7F +}; + +enum Key { + KEY_F1 = 1, + KEY_F2, + KEY_F3, + KEY_F4, + KEY_F5, + KEY_F6, + KEY_F7, + KEY_F8, + KEY_F9, + KEY_F10, + KEY_F11, + KEY_F12, + KEY_LEFT, + KEY_UP, + KEY_RIGHT, + KEY_DOWN, + KEY_PAGE_UP, + KEY_PAGE_DOWN, + KEY_HOME, + KEY_END, + KEY_INSERT, + KEY_SHIFT, + KEY_CTRL, + KEY_ALT, + KEY_SUPER +}; + +enum Modifier { + MODIFIER_SHIFT = 1 << 0, /**< Shift key */ + MODIFIER_CTRL = 1 << 1, /**< Control key */ + MODIFIER_ALT = 1 << 2, /**< Alt/Option key */ + MODIFIER_SUPER = 1 << 3 /**< Mod4/Command/Windows key */ +}; + +#endif // __DGL_BASE_HPP__ diff --git a/source/libs/distrho/dgl/Geometry.hpp b/source/libs/distrho/dgl/Geometry.hpp new file mode 100644 index 000000000..c8b0abbee --- /dev/null +++ b/source/libs/distrho/dgl/Geometry.hpp @@ -0,0 +1,131 @@ +/* + * DISTRHO Plugin Toolkit (DPT) + * Copyright (C) 2012-2013 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * For a full copy of the license see the LGPL.txt file + */ + +#ifndef __DGL_GEOMETRY_HPP__ +#define __DGL_GEOMETRY_HPP__ + +#include "Base.hpp" + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- + +template +class Point +{ +public: + Point(); + Point(T x, T y); + Point(const Point& pos); + + T getX() const; + T getY() const; + + void setX(T x); + void setY(T y); + + void move(T x, T y); + void move(const Point& pos); + + Point& operator=(const Point& pos); + Point& operator+=(const Point& pos); + Point& operator-=(const Point& pos); + bool operator==(const Point& pos) const; + bool operator!=(const Point& pos) const; + +private: + T fX, fY; + template friend class Rectangle; +}; + +// ------------------------------------------------- + +template +class Size +{ +public: + Size(); + Size(T width, T height); + Size(const Size& size); + + T getWidth() const; + T getHeight() const; + + void setWidth(T width); + void setHeight(T height); + + Size& operator=(const Size& size); + Size& operator+=(const Size& size); + Size& operator-=(const Size& size); + Size& operator*=(T m); + Size& operator/=(T d); + bool operator==(const Size& size) const; + bool operator!=(const Size& size) const; + +private: + T fWidth, fHeight; + template friend class Rectangle; +}; + +// ------------------------------------------------- + +template +class Rectangle +{ +public: + Rectangle(); + Rectangle(T x, T y, T width, T height); + Rectangle(T x, T y, const Size& size); + Rectangle(const Point& pos, T width, T height); + Rectangle(const Point& pos, const Size& size); + Rectangle(const Rectangle& rect); + + T getX() const; + T getY() const; + T getWidth() const; + T getHeight() const; + + const Point& getPos() const; + const Size& getSize() const; + + bool contains(T x, T y) const; + bool contains(const Point& pos) const; + + void setX(T x); + void setY(T y); + void setPos(T x, T y); + void setPos(const Point& pos); + + void move(T x, T y); + void move(const Point& pos); + + void setWidth(T width); + void setHeight(T height); + void setSize(T width, T height); + void setSize(const Size& size); + + Rectangle& operator=(const Rectangle& rect); + +private: + Point fPos; + Size fSize; +}; + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // __DGL_GEOMETRY_HPP__ diff --git a/source/libs/distrho/dgl/Image.hpp b/source/libs/distrho/dgl/Image.hpp new file mode 100644 index 000000000..84b09c690 --- /dev/null +++ b/source/libs/distrho/dgl/Image.hpp @@ -0,0 +1,56 @@ +/* + * DISTRHO Plugin Toolkit (DPT) + * Copyright (C) 2012-2013 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * For a full copy of the license see the LGPL.txt file + */ + +#ifndef __DGL_IMAGE_HPP__ +#define __DGL_IMAGE_HPP__ + +#include "Geometry.hpp" + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- + +class Image +{ +public: + Image(); + Image(const char* data, const Size& size, GLenum format = GL_BGRA, GLenum type = GL_UNSIGNED_BYTE); + Image(const Image& image); + + void loadFromMemory(const char* data, const Size& size, GLenum format = GL_BGRA, GLenum type = GL_UNSIGNED_BYTE); + + bool isValid() const; + + int getWidth() const; + int getHeight() const; + const Size& getSize() const; + + const char* getData() const; + GLenum getFormat() const; + GLenum getType() const; + +private: + const char* fData; + Size fSize; + GLenum fFormat; + GLenum fType; +}; + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // __DGL_IMAGE_HPP__ diff --git a/source/libs/distrho/dgl/Widget.hpp b/source/libs/distrho/dgl/Widget.hpp new file mode 100644 index 000000000..16061566e --- /dev/null +++ b/source/libs/distrho/dgl/Widget.hpp @@ -0,0 +1,54 @@ +/* + * DISTRHO Plugin Toolkit (DPT) + * Copyright (C) 2012-2013 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * For a full copy of the license see the LGPL.txt file + */ + +#ifndef __DGL_WIDGET_HPP__ +#define __DGL_WIDGET_HPP__ + +#include "Base.hpp" + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- + +class Window; + +class Widget +{ +public: + Widget(Window* parent = nullptr); + virtual ~Widget(); + +protected: + void onDisplay(); + void onKeyboard(bool press, uint32_t key); + void onMouse(int button, bool press, int x, int y); + void onMotion(int x, int y); + void onScroll(float dx, float dy); + void onSpecial(bool press, Key key); + void onReshape(int width, int height); + void onClose(); + +private: + class Private; + Private* const kPrivate; + friend class Window; +}; + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // __DGL_WIDGET_HPP__ diff --git a/source/libs/distrho/dgl/Window.hpp b/source/libs/distrho/dgl/Window.hpp new file mode 100644 index 000000000..4448d0c2a --- /dev/null +++ b/source/libs/distrho/dgl/Window.hpp @@ -0,0 +1,65 @@ +/* + * DISTRHO Plugin Toolkit (DPT) + * Copyright (C) 2012-2013 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * For a full copy of the license see the LGPL.txt file + */ + +#ifndef __DGL_WINDOW_HPP__ +#define __DGL_WINDOW_HPP__ + +#include "Base.hpp" + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- + +class App; + +class Window +{ +public: + Window(App* app, Window* parent = nullptr); + Window(App* app, intptr_t parentId); + virtual ~Window(); + + void exec(); + void focus(); + void idle(); + void repaint(); + + bool isVisible(); + void setVisible(bool yesNo); + void setWindowTitle(const char* title); + + intptr_t getWindowId(); + + void show() + { + setVisible(true); + } + + void hide() + { + setVisible(false); + } + +private: + class Private; + Private* const kPrivate; +}; + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // __DGL_WINDOW_HPP__ diff --git a/source/libs/distrho/dgl/src/App.cpp b/source/libs/distrho/dgl/src/App.cpp new file mode 100644 index 000000000..0085880d1 --- /dev/null +++ b/source/libs/distrho/dgl/src/App.cpp @@ -0,0 +1,56 @@ +/* + * DISTRHO Plugin Toolkit (DPT) + * Copyright (C) 2012-2013 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * For a full copy of the license see the LGPL.txt file + */ + +#include "AppPrivate.hpp" + +#include "../Window.hpp" +#include "../../DistrhoUtils.hpp" + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- + +App::App() + : kPrivate(new Private) +{ +} + +App::~App() +{ + delete kPrivate; +} + +void App::idle() +{ + for (auto it = kPrivate->fWindows.begin(); it != kPrivate->fWindows.end(); it++) + { + Window* window = *it; + window->idle(); + } +} + +void App::exec() +{ + while (kPrivate->fDoLoop) + { + idle(); + d_msleep(10); + } +} + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO diff --git a/source/libs/distrho/dgl/src/AppPrivate.hpp b/source/libs/distrho/dgl/src/AppPrivate.hpp new file mode 100644 index 000000000..d48ea58d4 --- /dev/null +++ b/source/libs/distrho/dgl/src/AppPrivate.hpp @@ -0,0 +1,82 @@ +/* + * DISTRHO Plugin Toolkit (DPT) + * Copyright (C) 2012-2013 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * For a full copy of the license see the LGPL.txt file + */ + +#ifndef __APP_PRIVATE_HPP__ +#define __APP_PRIVATE_HPP__ + +#include "../App.hpp" + +#include + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- + +class Window; + +class App::Private +{ +public: + Private() + : fDoLoop(true), + fVisibleWindows(0) + { + } + + ~Private() + { + fWindows.clear(); + } + + void addWindow(Window* window) + { + if (window != nullptr) + fWindows.push_back(window); + } + + void removeWindow(Window* window) + { + if (window != nullptr) + fWindows.remove(window); + } + + void oneShown() + { + fVisibleWindows++; + } + + void oneHidden() + { + fVisibleWindows--; + + if (fVisibleWindows == 0) + fDoLoop = false; + } + +private: + bool fDoLoop; + unsigned fVisibleWindows; + + std::list fWindows; + + friend class App; +}; + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // __APP_PRIVATE_HPP__ diff --git a/source/libs/distrho/dgl/src/Geometry.cpp b/source/libs/distrho/dgl/src/Geometry.cpp new file mode 100644 index 000000000..b05cc935b --- /dev/null +++ b/source/libs/distrho/dgl/src/Geometry.cpp @@ -0,0 +1,380 @@ +/* + * DISTRHO Plugin Toolkit (DPT) + * Copyright (C) 2012-2013 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * For a full copy of the license see the LGPL.txt file + */ + +#include "../Geometry.hpp" + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- +// Point + +template +Point::Point() + : fX(0), + fY(0) +{ +} + +template +Point::Point(T x, T y) + : fX(x), + fY(y) +{ +} + +template +Point::Point(const Point& pos) + : fX(pos.fX), + fY(pos.fY) +{ +} + +template +T Point::getX() const +{ + return fX; +} + +template +T Point::getY() const +{ + return fY; +} + +template +void Point::setX(T x) +{ + fX = x; +} + +template +void Point::setY(T y) +{ + fY = y; +} + +template +void Point::move(T x, T y) +{ + fX += x; + fY += y; +} + +template +void Point::move(const Point& pos) +{ + fX += pos.fX; + fY += pos.fY; +} + +template +Point& Point::operator=(const Point& pos) +{ + fX = pos.fX; + fY = pos.fY; + return *this; +} + +template +Point& Point::operator+=(const Point& pos) +{ + fX += pos.fX; + fY += pos.fY; + return *this; +} + +template +Point& Point::operator-=(const Point& pos) +{ + fX -= pos.fX; + fY -= pos.fY; + return *this; +} + +template +bool Point::operator==(const Point& pos) const +{ + return (fX == pos.fX && fY== pos.fY); +} + +template +bool Point::operator!=(const Point& pos) const +{ + return !operator==(pos); +} + +// ------------------------------------------------- +// Size + +template +Size::Size() + : fWidth(0), + fHeight(0) +{ +} + +template +Size::Size(T width, T height) + : fWidth(width), + fHeight(height) +{ +} + +template +Size::Size(const Size& size) + : fWidth(size.fWidth), + fHeight(size.fHeight) +{ +} + +template +T Size::getWidth() const +{ + return fWidth; +} + +template +T Size::getHeight() const +{ + return fHeight; +} + +template +void Size::setWidth(T width) +{ + fWidth = width; +} + +template +void Size::setHeight(T height) +{ + fHeight = height; +} + +template +Size& Size::operator=(const Size& size) +{ + fWidth = size.fWidth; + fHeight = size.fHeight; + return *this; +} + +template +Size& Size::operator+=(const Size& size) +{ + fWidth += size.fWidth; + fHeight += size.fHeight; + return *this; +} + +template +Size& Size::operator-=(const Size& size) +{ + fWidth -= size.fWidth; + fHeight -= size.fHeight; + return *this; +} + +template +Size& Size::operator*=(T m) +{ + fWidth *= m; + fHeight *= m; + return *this; +} + +template +Size& Size::operator/=(T d) +{ + fWidth /= d; + fHeight /= d; + return *this; +} + +template +bool Size::operator==(const Size& size) const +{ + return (fWidth == size.fWidth && fHeight == size.fHeight); +} + +template +bool Size::operator!=(const Size& size) const +{ + return !operator==(size); +} + +// ------------------------------------------------- +// Rectangle + +template +Rectangle::Rectangle() + : fPos(0, 0), + fSize(0, 0) +{ +} + +template +Rectangle::Rectangle(T x, T y, T width, T height) + : fPos(x, y), + fSize(width, height) +{ +} + +template +Rectangle::Rectangle(T x, T y, const Size& size) + : fPos(x, y), + fSize(size) +{ +} + +template +Rectangle::Rectangle(const Point& pos, T width, T height) + : fPos(pos), + fSize(width, height) +{ +} + +template +Rectangle::Rectangle(const Point& pos, const Size& size) + : fPos(pos), + fSize(size) +{ +} + +template +Rectangle::Rectangle(const Rectangle& rect) + : fPos(rect._pos), + fSize(rect._size) +{ +} + +template +T Rectangle::getX() const +{ + return fPos.fX; +} + +template +T Rectangle::getY() const +{ + return fPos.fY; +} + +template +T Rectangle::getWidth() const +{ + return fSize.fWidth; +} + +template +T Rectangle::getHeight() const +{ + return fSize.fHeight; +} + +template +const Point& Rectangle::getPos() const +{ + return fPos; +} + +template +const Size& Rectangle::getSize() const +{ + return fSize; +} + +template +bool Rectangle::contains(T x, T y) const +{ + return (x >= fPos.fX && y >= fPos.fY && x <= fPos.fX+fSize.fWidth && y <= fPos.fY+fSize.fHeight); +} + +template +bool Rectangle::contains(const Point& pos) const +{ + return contains(pos.fX, pos.fY); +} + +#if 0 +template +void Rectangle::setX(int x) +{ + _pos._x = x; +} + +template +void Rectangle::setY(int y) +{ + _pos._y = y; +} + +void Rectangle::setPos(int x, int y) +{ + _pos._x = x; + _pos._y = y; +} + +void Rectangle::setPos(const Point& pos) +{ + _pos = pos; +} + +void Rectangle::move(int x, int y) +{ + _pos._x += x; + _pos._y += y; +} + +void Rectangle::move(const Point& pos) +{ + _pos += pos; +} + +void Rectangle::setWidth(int width) +{ + _size._width = width; +} + +void Rectangle::setHeight(int height) +{ + _size._height = height; +} + +void Rectangle::setSize(int width, int height) +{ + _size._width = width; + _size._height = height; +} + +void Rectangle::setSize(const Size& size) +{ + _size = size; +} + +Rectangle& Rectangle::operator=(const Rectangle& rect) +{ + _pos = rect._pos; + _size = rect._size; + return *this; +} + +#endif + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO + diff --git a/source/libs/distrho/dgl/src/Widget.cpp b/source/libs/distrho/dgl/src/Widget.cpp new file mode 100644 index 000000000..6c390f6c5 --- /dev/null +++ b/source/libs/distrho/dgl/src/Widget.cpp @@ -0,0 +1,115 @@ +/* + * DISTRHO Plugin Toolkit (DPT) + * Copyright (C) 2012-2013 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * For a full copy of the license see the LGPL.txt file + */ + +#include "../App.hpp" +#include "../Widget.hpp" +#include "../Window.hpp" + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- +// Window Private + +class Widget::Private +{ +public: + Private(Window* parent) + : fApp(nullptr), + fWindow(nullptr) + { + if (parent == nullptr) + { + fApp = new App; + fWindow = new Window(fApp); + } + } + + ~Private() + { + if (fWindow != nullptr) + delete fWindow; + if (fApp != nullptr) + delete fApp; + } + +private: + App* fApp; + Window* fWindow; +}; + +// ------------------------------------------------- +// Widget + +Widget::Widget(Window* parent) + : kPrivate(new Private(parent)) +{ +} + +Widget::~Widget() +{ +} + +void Widget::onDisplay() +{ + //if (fParent == nullptr) + // glColor3f(0.0f, 1.0f, 0.0f); + //else + glColor3f(0.0f, 0.0f, 1.0f); + glRectf(-0.75f, 0.75f, 0.75f, -0.75f); + +} + +void Widget::onKeyboard(bool, uint32_t) +{ +} + +void Widget::onMouse(int, bool, int, int) +{ +} + +void Widget::onMotion(int, int) +{ +} + +void Widget::onScroll(float, float) +{ +} + +void Widget::onSpecial(bool, Key) +{ +} + +void Widget::onReshape(int width, int height) +{ + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, width, height, 0, 0, 1); + glViewport(0, 0, width, height); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + +void Widget::onClose() +{ +} + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO diff --git a/source/libs/distrho/dgl/src/Window.cpp b/source/libs/distrho/dgl/src/Window.cpp new file mode 100644 index 000000000..bf61309ff --- /dev/null +++ b/source/libs/distrho/dgl/src/Window.cpp @@ -0,0 +1,497 @@ +/* + * DISTRHO Plugin Toolkit (DPT) + * Copyright (C) 2012-2013 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * For a full copy of the license see the LGPL.txt file + */ + +#include "AppPrivate.hpp" + +#include "../Widget.hpp" +#include "../Window.hpp" +#include "../../DistrhoUtils.hpp" + +#if DISTRHO_OS_WINDOWS +# include "pugl/pugl_win.cpp" +#elif DISTRHO_OS_MAC +# include "pugl/pugl_osx.m" +#elif DISTRHO_OS_LINUX +# include "pugl/pugl_x11.c" +#else +# error Unsupported platform! +#endif + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- +// Utils + +#if DISTRHO_OS_LINUX +static Bool isMapNotify(Display*, XEvent* ev, XPointer win) +{ + return (ev->type == MapNotify && ev->xmap.window == *((::Window*)win)); +} +static Bool isUnmapNotify(Display*, XEvent* ev, XPointer win) +{ + return (ev->type == UnmapNotify && ev->xunmap.window == *((::Window*)win)); +} +#endif + +#define FOR_EACH_WIDGET(it) \ + for (auto it = fWidgets.begin(); it != fWidgets.end(); it++) + +// ------------------------------------------------- +// Window Private + +class Window::Private +{ +public: + Private(Window* self, App::Private* app, Private* parent, intptr_t parentId = 0) + : kApp(app), + kSelf(self), + kView(puglCreate(parentId, "test", 300, 100, false, false)), + fParent(parent), + fChildFocus(nullptr), + fVisible(false), + fClosed(false), +#if DISTRHO_OS_WINDOWS + hwnd(0) +#elif DISTRHO_OS_LINUX + xDisplay(nullptr), + xWindow(0) +#else + _dummy(0) +#endif + { + if (kView == nullptr) + return; + + puglSetHandle(kView, this); + puglSetDisplayFunc(kView, onDisplayCallback); + puglSetKeyboardFunc(kView, onKeyboardCallback); + puglSetMotionFunc(kView, onMotionCallback); + puglSetMouseFunc(kView, onMouseCallback); + puglSetScrollFunc(kView, onScrollCallback); + puglSetSpecialFunc(kView, onSpecialCallback); + puglSetReshapeFunc(kView, onReshapeCallback); + puglSetCloseFunc(kView, onCloseCallback); + + PuglInternals* impl = kView->impl; + +#if DISTRHO_OS_WINDOWS + //hwnd = impl->hwnd; + + if (parent != nullptr) + { + //PuglInternals* parentImpl = parent->kView->impl; + //SetParent(parentImpl->hwnd, hwnd); + } +#elif DISTRHO_OS_LINUX + xDisplay = impl->display; + xWindow = impl->win; + + if (parent != nullptr) + { + PuglInternals* parentImpl = parent->kView->impl; + bool parentWasVisible = parent->isVisible(); + + if (parentWasVisible) + { + XEvent event; + XUnmapWindow(xDisplay, xWindow); + XIfEvent(xDisplay, &event, &isUnmapNotify, (XPointer)&xWindow); + } + + XSetTransientForHint(xDisplay, xWindow, parentImpl->win); + + if (parentWasVisible) + { + XEvent event; + XMapWindow(xDisplay, xWindow); + XIfEvent(xDisplay, &event, &isMapNotify, (XPointer)&xWindow); + } + + XFlush(xDisplay); + } +#endif + + kApp->addWindow(kSelf); + } + + ~Private() + { + fWidgets.clear(); + + if (kView != nullptr) + { + kApp->removeWindow(kSelf); + puglDestroy(kView); + } + } + + void exec() + { + fClosed = false; + show(); + + if (fParent != nullptr) + { +#if DISTRHO_OS_WINDOWS + EnableWindow(fParent->hwnd, FALSE); +#endif + fParent->fChildFocus = this; + fParent->show(); + } + + focus(); + + while (! fClosed) + { + idle(); + + if (fParent != nullptr) + fParent->idle(); + + d_msleep(10); + } + + if (fParent != nullptr) + { + fParent->fChildFocus = nullptr; +#if DISTRHO_OS_WINDOWS + EnableWindow(fParent->hwnd, TRUE); +#endif + } + } + + void focus() + { +#if DISTRHO_OS_WINDOWS + SetForegroundWindow(hwnd); + SetActiveWindow(hwnd); + SetFocus(hwnd); +#elif DISTRHO_OS_LINUX + XRaiseWindow(xDisplay, xWindow); + XSetInputFocus(xDisplay, xWindow, RevertToPointerRoot, CurrentTime); + XFlush(xDisplay); +#endif + } + + void idle() + { + puglProcessEvents(kView); + } + + void repaint() + { + puglPostRedisplay(kView); + } + + void show() + { + setVisible(true); + } + + void hide() + { + setVisible(false); + } + + bool isVisible() + { + return fVisible; + } + + void setVisible(bool yesNo) + { + if (fVisible == yesNo) + return; + + fVisible = yesNo; + +#if DISTRHO_OS_WINDOWS + if (yesNo) + { + ShowWindow(hwnd, WS_VISIBLE); + ShowWindow(hwnd, SW_RESTORE); + //SetForegroundWindow(hwnd); + } + else + { + ShowWindow(hwnd, SW_HIDE); + } + + UpdateWindow(hwnd); +#elif DISTRHO_OS_LINUX + XEvent event; + + if (yesNo) + { + XMapRaised(xDisplay, xWindow); + XIfEvent(xDisplay, &event, &isMapNotify, (XPointer)&xWindow); + } + else + { + XUnmapWindow(xDisplay, xWindow); + XIfEvent(xDisplay, &event, &isUnmapNotify, (XPointer)&xWindow); + } + + XFlush(xDisplay); +#endif + + if (yesNo) + kApp->oneShown(); + else + kApp->oneHidden(); + } + + void setWindowTitle(const char* title) + { +#if DISTRHO_OS_WINDOWS + SetWindowTextA(hwnd, title); +#elif DISTRHO_OS_LINUX + XStoreName(xDisplay, xWindow, title); + XFlush(xDisplay); +#endif + } + + intptr_t getWindowId() + { + return puglGetNativeWindow(kView); + } + +protected: + void onDisplay() + { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + FOR_EACH_WIDGET(it) + { + Widget* widget = *it; + widget->onDisplay(); + } + } + + void onKeyboard(bool press, uint32_t key) + { + if (fChildFocus != nullptr) + return fChildFocus->focus(); + + FOR_EACH_WIDGET(it) + { + Widget* widget = *it; + widget->onKeyboard(press, key); + } + } + + void onMouse(int button, bool press, int x, int y) + { + if (fChildFocus != nullptr) + return fChildFocus->focus(); + + FOR_EACH_WIDGET(it) + { + Widget* widget = *it; + widget->onMouse(button, press, x, y); + } + } + + void onMotion(int x, int y) + { + if (fChildFocus != nullptr) + return; + + FOR_EACH_WIDGET(it) + { + Widget* widget = *it; + widget->onMotion(x, y); + } + } + + void onScroll(float dx, float dy) + { + if (fChildFocus != nullptr) + return; + + FOR_EACH_WIDGET(it) + { + Widget* widget = *it; + widget->onScroll(dx, dy); + } + } + + void onSpecial(bool press, Key key) + { + if (fChildFocus != nullptr) + return; + + FOR_EACH_WIDGET(it) + { + Widget* widget = *it; + widget->onSpecial(press, key); + } + } + + void onReshape(int width, int height) + { + + FOR_EACH_WIDGET(it) + { + Widget* widget = *it; + widget->onReshape(width, height); + } + } + + void onClose() + { + fClosed = true; + + if (fChildFocus != nullptr) + fChildFocus->onClose(); + + FOR_EACH_WIDGET(it) + { + Widget* widget = *it; + widget->onClose(); + } + + hide(); + } + +private: + App::Private* const kApp; + Window* const kSelf; + PuglView* const kView; + + Private* fParent; + Private* fChildFocus; + bool fVisible; + bool fClosed; + + std::list fWidgets; + +#if DISTRHO_OS_WINDOWS + HWND hwnd; +#elif DISTRHO_OS_LINUX + Display* xDisplay; + ::Window xWindow; +#else + int _dummy; +#endif + + // Callbacks + #define handlePtr ((Private*)puglGetHandle(view)) + + static void onDisplayCallback(PuglView* view) + { + handlePtr->onDisplay(); + } + + static void onKeyboardCallback(PuglView* view, bool press, uint32_t key) + { + handlePtr->onKeyboard(press, key); + } + + static void onMouseCallback(PuglView* view, int button, bool press, int x, int y) + { + handlePtr->onMouse(button, press, x, y); + } + + static void onMotionCallback(PuglView* view, int x, int y) + { + handlePtr->onMotion(x, y); + } + + static void onScrollCallback(PuglView* view, float dx, float dy) + { + handlePtr->onScroll(dx, dy); + } + + static void onSpecialCallback(PuglView* view, bool press, PuglKey key) + { + handlePtr->onSpecial(press, static_cast(key)); + } + + static void onReshapeCallback(PuglView* view, int width, int height) + { + handlePtr->onReshape(width, height); + } + + static void onCloseCallback(PuglView* view) + { + handlePtr->onClose(); + } + + #undef handlePtr +}; + +// ------------------------------------------------- +// Window + +Window::Window(App* app, Window* parent) + : kPrivate(new Private(this, app->kPrivate, (parent != nullptr) ? parent->kPrivate : nullptr)) +{ +} + +Window::Window(App* app, intptr_t parentId) + : kPrivate(new Private(this, app->kPrivate, nullptr, parentId)) +{ +} + +Window::~Window() +{ + delete kPrivate; +} + +void Window::exec() +{ + kPrivate->exec(); +} + +void Window::focus() +{ + kPrivate->focus(); +} + +void Window::idle() +{ + kPrivate->idle(); +} + +void Window::repaint() +{ + kPrivate->repaint(); +} + +bool Window::isVisible() +{ + return kPrivate->isVisible(); +} + +void Window::setVisible(bool yesNo) +{ + kPrivate->setVisible(yesNo); +} + +void Window::setWindowTitle(const char* title) +{ + kPrivate->setWindowTitle(title); +} + +intptr_t Window::getWindowId() +{ + return kPrivate->getWindowId(); +} + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO diff --git a/source/libs/distrho/dgl/src/pugl/pugl.h b/source/libs/distrho/dgl/src/pugl/pugl.h new file mode 100644 index 000000000..4c4366fa1 --- /dev/null +++ b/source/libs/distrho/dgl/src/pugl/pugl.h @@ -0,0 +1,341 @@ +/* + Copyright 2012 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file pugl.h API for Pugl, a minimal portable API for OpenGL. +*/ + +#ifndef PUGL_H_INCLUDED +#define PUGL_H_INCLUDED + +#include + +/* + This API is pure portable C and contains no platform specific elements, or + even a GL dependency. However, unfortunately GL includes vary across + platforms so they are included here to allow for pure portable programs. +*/ +#ifdef __APPLE__ +# include "OpenGL/gl.h" +#else +# ifdef _WIN32 +# include /* Broken Windows GL headers require this */ +# endif +# include "GL/gl.h" +#endif + +#ifdef PUGL_SHARED +# ifdef _WIN32 +# define PUGL_LIB_IMPORT __declspec(dllimport) +# define PUGL_LIB_EXPORT __declspec(dllexport) +# else +# define PUGL_LIB_IMPORT __attribute__((visibility("default"))) +# define PUGL_LIB_EXPORT __attribute__((visibility("default"))) +# endif +# ifdef PUGL_INTERNAL +# define PUGL_API PUGL_LIB_EXPORT +# else +# define PUGL_API PUGL_LIB_IMPORT +# endif +#else +# define PUGL_API +#endif + +#ifndef __cplusplus +# include +#endif + +/** + @defgroup pugl Pugl + A minimal portable API for OpenGL. + @{ +*/ + +/** + An OpenGL view. +*/ +typedef struct PuglViewImpl PuglView; + +/** + A native window handle. + + On X11, this is a Window. + On OSX, this is an NSView*. + On Windows, this is a HWND. +*/ +typedef intptr_t PuglNativeWindow; + +/** + Return status code. +*/ +typedef enum { + PUGL_SUCCESS = 0 +} PuglStatus; + +/** + Convenience symbols for ASCII control characters. +*/ +typedef enum { + PUGL_CHAR_BACKSPACE = 0x08, + PUGL_CHAR_ESCAPE = 0x1B, + PUGL_CHAR_DELETE = 0x7F +} PuglChar; + +/** + Special (non-Unicode) keyboard keys. +*/ +typedef enum { + PUGL_KEY_F1 = 1, + PUGL_KEY_F2, + PUGL_KEY_F3, + PUGL_KEY_F4, + PUGL_KEY_F5, + PUGL_KEY_F6, + PUGL_KEY_F7, + PUGL_KEY_F8, + PUGL_KEY_F9, + PUGL_KEY_F10, + PUGL_KEY_F11, + PUGL_KEY_F12, + PUGL_KEY_LEFT, + PUGL_KEY_UP, + PUGL_KEY_RIGHT, + PUGL_KEY_DOWN, + PUGL_KEY_PAGE_UP, + PUGL_KEY_PAGE_DOWN, + PUGL_KEY_HOME, + PUGL_KEY_END, + PUGL_KEY_INSERT, + PUGL_KEY_SHIFT, + PUGL_KEY_CTRL, + PUGL_KEY_ALT, + PUGL_KEY_SUPER +} PuglKey; + +/** + Keyboard modifier flags. +*/ +typedef enum { + PUGL_MOD_SHIFT = 1, /**< Shift key */ + PUGL_MOD_CTRL = 1 << 1, /**< Control key */ + PUGL_MOD_ALT = 1 << 2, /**< Alt/Option key */ + PUGL_MOD_SUPER = 1 << 3 /**< Mod4/Command/Windows key */ +} PuglMod; + +/** + Handle for opaque user data. +*/ +typedef void* PuglHandle; + +/** + A function called when the window is closed. +*/ +typedef void (*PuglCloseFunc)(PuglView* view); + +/** + A function called to draw the view contents with OpenGL. +*/ +typedef void (*PuglDisplayFunc)(PuglView* view); + +/** + A function called when a key is pressed or released. + @param view The view the event occured in. + @param press True if the key was pressed, false if released. + @param key Unicode point of the key pressed. +*/ +typedef void (*PuglKeyboardFunc)(PuglView* view, bool press, uint32_t key); + +/** + A function called when the pointer moves. + @param view The view the event occured in. + @param x The window-relative x coordinate of the pointer. + @param y The window-relative y coordinate of the pointer. +*/ +typedef void (*PuglMotionFunc)(PuglView* view, int x, int y); + +/** + A function called when a mouse button is pressed or released. + @param view The view the event occured in. + @param button The button number (1 = left, 2 = middle, 3 = right). + @param press True if the key was pressed, false if released. + @param x The window-relative x coordinate of the pointer. + @param y The window-relative y coordinate of the pointer. +*/ +typedef void (*PuglMouseFunc)( + PuglView* view, int button, bool press, int x, int y); + +/** + A function called when the view is resized. + @param view The view being resized. + @param width The new view width. + @param height The new view height. +*/ +typedef void (*PuglReshapeFunc)(PuglView* view, int width, int height); + +/** + A function called on scrolling (e.g. mouse wheel or track pad). + + The distances used here are in "lines", a single tick of a clicking mouse + wheel. For example, @p dy = 1.0 scrolls 1 line up. Some systems and + devices support finer resolution and/or higher values for fast scrolls, + so programs should handle any value gracefully. + + @param view The view being scrolled. + @param dx The scroll x distance. + @param dx The scroll y distance. +*/ +typedef void (*PuglScrollFunc)(PuglView* view, float dx, float dy); + +/** + A function called when a special key is pressed or released. + + This callback allows the use of keys that do not have unicode points. Note + that some non-printable keys + @param view The view the event occured in. + @param press True if the key was pressed, false if released. + @param key The key pressed. +*/ +typedef void (*PuglSpecialFunc)(PuglView* view, bool press, PuglKey key); + +/** + Create a new GL window. + @param parent Parent window, or 0 for top level. + @param title Window title, or NULL. + @param width Window width in pixels. + @param height Window height in pixels. + @param resizable Whether window should be user resizable. +*/ +PUGL_API PuglView* +puglCreate(PuglNativeWindow parent, + const char* title, + int width, + int height, + bool resizable, + bool addToDesktop = true, + const char* x11Display = nullptr); + +/** + Set the handle to be passed to all callbacks. + + This is generally a pointer to a struct which contains all necessary state. + Everything needed in callbacks should be here, not in static variables. + + Note the lack of this facility makes GLUT unsuitable for plugins or + non-trivial programs; this mistake is largely why Pugl exists. +*/ +PUGL_API void +puglSetHandle(PuglView* view, PuglHandle handle); + +/** + Get the handle to be passed to all callbacks. +*/ +PUGL_API PuglHandle +puglGetHandle(PuglView* view); + +/** + Get the currently active modifiers (PuglMod flags). + + This should only be called from an event handler. +*/ +PUGL_API int +puglGetModifiers(PuglView* view); + +/** + Ignore synthetic repeated key events. +*/ +PUGL_API void +puglIgnoreKeyRepeat(PuglView* view, bool ignore); + +/** + Set the function to call when the window is closed. +*/ +PUGL_API void +puglSetCloseFunc(PuglView* view, PuglCloseFunc closeFunc); + +/** + Set the display function which should draw the UI using GL. +*/ +PUGL_API void +puglSetDisplayFunc(PuglView* view, PuglDisplayFunc displayFunc); + +/** + Set the function to call on keyboard events. +*/ +PUGL_API void +puglSetKeyboardFunc(PuglView* view, PuglKeyboardFunc keyboardFunc); + +/** + Set the function to call on mouse motion. +*/ +PUGL_API void +puglSetMotionFunc(PuglView* view, PuglMotionFunc motionFunc); + +/** + Set the function to call on mouse button events. +*/ +PUGL_API void +puglSetMouseFunc(PuglView* view, PuglMouseFunc mouseFunc); + +/** + Set the function to call on scroll events. +*/ +PUGL_API void +puglSetScrollFunc(PuglView* view, PuglScrollFunc scrollFunc); + +/** + Set the function to call on special events. +*/ +PUGL_API void +puglSetSpecialFunc(PuglView* view, PuglSpecialFunc specialFunc); + +/** + Set the function to call when the window size changes. +*/ +PUGL_API void +puglSetReshapeFunc(PuglView* view, PuglReshapeFunc reshapeFunc); + +/** + Return the native window handle. +*/ +PUGL_API PuglNativeWindow +puglGetNativeWindow(PuglView* view); + +/** + Process all pending window events. + + This handles input events as well as rendering, so it should be called + regularly and rapidly enough to keep the UI responsive. +*/ +PUGL_API PuglStatus +puglProcessEvents(PuglView* view); + +/** + Request a redisplay on the next call to puglProcessEvents(). +*/ +PUGL_API void +puglPostRedisplay(PuglView* view); + +/** + Destroy a GL window. +*/ +PUGL_API void +puglDestroy(PuglView* view); + +/** + @} +*/ + +#endif /* PUGL_H_INCLUDED */ diff --git a/source/libs/distrho/dgl/src/pugl/pugl_internal.h b/source/libs/distrho/dgl/src/pugl/pugl_internal.h new file mode 100644 index 000000000..a94b6cc95 --- /dev/null +++ b/source/libs/distrho/dgl/src/pugl/pugl_internal.h @@ -0,0 +1,135 @@ +/* + Copyright 2012 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file pugl_internal.h Private platform-independent definitions. + + Note this file contains function definitions, so it must be compiled into + the final binary exactly once. Each platform specific implementation file + including it once should achieve this. +*/ + +#include "pugl.h" + +typedef struct PuglInternalsImpl PuglInternals; + +struct PuglViewImpl { + PuglHandle handle; + PuglCloseFunc closeFunc; + PuglDisplayFunc displayFunc; + PuglKeyboardFunc keyboardFunc; + PuglMotionFunc motionFunc; + PuglMouseFunc mouseFunc; + PuglReshapeFunc reshapeFunc; + PuglScrollFunc scrollFunc; + PuglSpecialFunc specialFunc; + + PuglInternals* impl; + + int width; + int height; + int mods; + bool ignoreKeyRepeat; + bool redisplay; +}; + +void +puglSetHandle(PuglView* view, PuglHandle handle) +{ + view->handle = handle; +} + +PuglHandle +puglGetHandle(PuglView* view) +{ + return view->handle; +} + +int +puglGetModifiers(PuglView* view) +{ + return view->mods; +} + +static inline void +puglDefaultReshape(PuglView* view, int width, int height) +{ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, width, height, 0, 0, 1); + glViewport(0, 0, width, height); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + return; + + // unused + (void)view; +} + +void +puglIgnoreKeyRepeat(PuglView* view, bool ignore) +{ + view->ignoreKeyRepeat = ignore; +} + +void +puglSetCloseFunc(PuglView* view, PuglCloseFunc closeFunc) +{ + view->closeFunc = closeFunc; +} + +void +puglSetDisplayFunc(PuglView* view, PuglDisplayFunc displayFunc) +{ + view->displayFunc = displayFunc; +} + +void +puglSetKeyboardFunc(PuglView* view, PuglKeyboardFunc keyboardFunc) +{ + view->keyboardFunc = keyboardFunc; +} + +void +puglSetMotionFunc(PuglView* view, PuglMotionFunc motionFunc) +{ + view->motionFunc = motionFunc; +} + +void +puglSetMouseFunc(PuglView* view, PuglMouseFunc mouseFunc) +{ + view->mouseFunc = mouseFunc; +} + +void +puglSetReshapeFunc(PuglView* view, PuglReshapeFunc reshapeFunc) +{ + view->reshapeFunc = reshapeFunc; +} + +void +puglSetScrollFunc(PuglView* view, PuglScrollFunc scrollFunc) +{ + view->scrollFunc = scrollFunc; +} + +void +puglSetSpecialFunc(PuglView* view, PuglSpecialFunc specialFunc) +{ + view->specialFunc = specialFunc; +} diff --git a/source/libs/distrho/dgl/src/pugl/pugl_osx.m b/source/libs/distrho/dgl/src/pugl/pugl_osx.m new file mode 100644 index 000000000..7b1c17588 --- /dev/null +++ b/source/libs/distrho/dgl/src/pugl/pugl_osx.m @@ -0,0 +1,331 @@ +/* + Copyright 2012 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file pugl_osx.m OSX/Cocoa Pugl Implementation. +*/ + +#include + +#import + +#include "pugl_internal.h" + +@interface PuglOpenGLView : NSOpenGLView +{ + int colorBits; + int depthBits; +@public + PuglView* view; +} + +- (id) initWithFrame:(NSRect)frame + colorBits:(int)numColorBits + depthBits:(int)numDepthBits; +- (void) reshape; +- (void) drawRect:(NSRect)rect; +- (void) mouseMoved:(NSEvent*)event; +- (void) mouseDown:(NSEvent*)event; +- (void) mouseUp:(NSEvent*)event; +- (void) rightMouseDown:(NSEvent*)event; +- (void) rightMouseUp:(NSEvent*)event; +- (void) keyDown:(NSEvent*)event; +- (void) keyUp:(NSEvent*)event; +- (void) flagsChanged:(NSEvent*)event; + +@end + +@implementation PuglOpenGLView + +- (id) initWithFrame:(NSRect)frame + colorBits:(int)numColorBits + depthBits:(int)numDepthBits +{ + colorBits = numColorBits; + depthBits = numDepthBits; + + NSOpenGLPixelFormatAttribute pixelAttribs[16] = { + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAAccelerated, + NSOpenGLPFAColorSize, + colorBits, + NSOpenGLPFADepthSize, + depthBits, + 0 + }; + + NSOpenGLPixelFormat* pixelFormat = [[NSOpenGLPixelFormat alloc] + initWithAttributes:pixelAttribs]; + + if (pixelFormat) { + self = [super initWithFrame:frame pixelFormat:pixelFormat]; + [pixelFormat release]; + if (self) { + [[self openGLContext] makeCurrentContext]; + [self reshape]; + } + } else { + self = nil; + } + + return self; +} + +- (void) reshape +{ + [[self openGLContext] update]; + + NSRect bounds = [self bounds]; + int width = bounds.size.width; + int height = bounds.size.height; + + if (view->reshapeFunc) { + view->reshapeFunc(view, width, height); + } else { + puglDefaultReshape(view, width, height); + } + + view->width = width; + view->height = height; +} + +- (void) drawRect:(NSRect)rect +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glLoadIdentity(); + + if (self->view->displayFunc) { + self->view->displayFunc(self->view); + } + + glFlush(); + glSwapAPPLE(); +} + +static int +getModifiers(unsigned modifierFlags) +{ + int mods = 0; + mods |= (modifierFlags & NSShiftKeyMask) ? PUGL_MOD_SHIFT : 0; + mods |= (modifierFlags & NSControlKeyMask) ? PUGL_MOD_CTRL : 0; + mods |= (modifierFlags & NSAlternateKeyMask) ? PUGL_MOD_ALT : 0; + mods |= (modifierFlags & NSCommandKeyMask) ? PUGL_MOD_SUPER : 0; + return mods; +} + +- (void) mouseMoved:(NSEvent*)event +{ + if (view->motionFunc) { + NSPoint loc = [event locationInWindow]; + view->mods = getModifiers([event modifierFlags]); + view->motionFunc(view, loc.x, loc.y); + } +} + +- (void) mouseDown:(NSEvent*)event +{ + if (view->mouseFunc) { + NSPoint loc = [event locationInWindow]; + view->mods = getModifiers([event modifierFlags]); + view->mouseFunc(view, 1, true, loc.x, loc.y); + } +} + +- (void) mouseUp:(NSEvent*)event +{ + if (view->mouseFunc) { + NSPoint loc = [event locationInWindow]; + view->mods = getModifiers([event modifierFlags]); + view->mouseFunc(view, 1, false, loc.x, loc.y); + } +} + +- (void) rightMouseDown:(NSEvent*)event +{ + if (view->mouseFunc) { + NSPoint loc = [event locationInWindow]; + view->mods = getModifiers([event modifierFlags]); + view->mouseFunc(view, 3, true, loc.x, loc.y); + } +} + +- (void) rightMouseUp:(NSEvent*)event +{ + if (view->mouseFunc) { + NSPoint loc = [event locationInWindow]; + view->mods = getModifiers([event modifierFlags]); + view->mouseFunc(view, 3, false, loc.x, loc.y); + } +} + +- (void) scrollWheel:(NSEvent*)event +{ + if (view->scrollFunc) { + view->mods = getModifiers([event modifierFlags]); + view->scrollFunc(view, [event deltaX], [event deltaY]); + } +} + +- (void) keyDown:(NSEvent*)event +{ + if (view->keyboardFunc && !(view->ignoreKeyRepeat && [event isARepeat])) { + NSString* chars = [event characters]; + view->mods = getModifiers([event modifierFlags]); + view->keyboardFunc(view, true, [chars characterAtIndex:0]); + } +} + +- (void) keyUp:(NSEvent*)event +{ + if (view->keyboardFunc) { + NSString* chars = [event characters]; + view->mods = getModifiers([event modifierFlags]); + view->keyboardFunc(view, false, [chars characterAtIndex:0]); + } +} + +- (void) flagsChanged:(NSEvent*)event +{ + if (view->specialFunc) { + int mods = getModifiers([event modifierFlags]); + if ((mods & PUGL_MOD_SHIFT) != (view->mods & PUGL_MOD_SHIFT)) { + view->specialFunc(view, mods & PUGL_MOD_SHIFT, PUGL_KEY_SHIFT); + } else if ((mods & PUGL_MOD_CTRL) != (view->mods & PUGL_MOD_CTRL)) { + view->specialFunc(view, mods & PUGL_MOD_CTRL, PUGL_KEY_CTRL); + } else if ((mods & PUGL_MOD_ALT) != (view->mods & PUGL_MOD_ALT)) { + view->specialFunc(view, mods & PUGL_MOD_ALT, PUGL_KEY_ALT); + } else if ((mods & PUGL_MOD_SUPER) != (view->mods & PUGL_MOD_SUPER)) { + view->specialFunc(view, mods & PUGL_MOD_SUPER, PUGL_KEY_SUPER); + } + view->mods = mods; + } +} + +@end + +struct PuglInternalsImpl { + PuglOpenGLView* view; + NSModalSession session; + id window; +}; + +PuglView* +puglCreate(PuglNativeWindow parent, + const char* title, + int width, + int height, + bool resizable, + bool addToDesktop, + const char* x11Display) +{ + PuglView* view = (PuglView*)calloc(1, sizeof(PuglView)); + PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); + if (!view || !impl) { + return NULL; + } + + view->impl = impl; + view->width = width; + view->height = height; + + [NSAutoreleasePool new]; + [NSApplication sharedApplication]; + [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; + + NSString* titleString = [[NSString alloc] + initWithBytes:title + length:strlen(title) + encoding:NSUTF8StringEncoding]; + + id window = [[[NSWindow alloc] + initWithContentRect:NSMakeRect(0, 0, 512, 512) + styleMask:NSTitledWindowMask + backing:NSBackingStoreBuffered + defer:NO] + autorelease]; + + [window cascadeTopLeftFromPoint:NSMakePoint(20, 20)]; + [window setTitle:titleString]; + [window setAcceptsMouseMovedEvents:YES]; + + impl->view = [PuglOpenGLView new]; + impl->window = window; + impl->view->view = view; + + [window setContentView:impl->view]; + [NSApp activateIgnoringOtherApps:YES]; + [window makeFirstResponder:impl->view]; + + impl->session = [NSApp beginModalSessionForWindow:view->impl->window]; + + return view; + + // unused + (void)addToDesktop; + (void)x11Display; +} + +void +puglDestroy(PuglView* view) +{ + [NSApp endModalSession:view->impl->session]; + [view->impl->view release]; + free(view->impl); + free(view); +} + +void +puglDisplay(PuglView* view) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glLoadIdentity(); + + if (view->displayFunc) { + view->displayFunc(view); + } + + glFlush(); + view->redisplay = false; +} + +PuglStatus +puglProcessEvents(PuglView* view) +{ + NSInteger response = [NSApp runModalSession:view->impl->session]; + if (response != NSRunContinuesResponse) { + if (view->closeFunc) { + view->closeFunc(view); + } + } + + if (view->redisplay) { + puglDisplay(view); + } + + return PUGL_SUCCESS; +} + +void +puglPostRedisplay(PuglView* view) +{ + view->redisplay = true; +} + +PuglNativeWindow +puglGetNativeWindow(PuglView* view) +{ + return (PuglNativeWindow)view->impl->view; +} diff --git a/source/libs/distrho/dgl/src/pugl/pugl_win.cpp b/source/libs/distrho/dgl/src/pugl/pugl_win.cpp new file mode 100644 index 000000000..a5d71912d --- /dev/null +++ b/source/libs/distrho/dgl/src/pugl/pugl_win.cpp @@ -0,0 +1,344 @@ +/* + Copyright 2012 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file pugl_win.cpp Windows/WGL Pugl Implementation. +*/ + +#include +#include +#include + +#include "pugl_internal.h" + +#ifndef WM_MOUSEWHEEL +# define WM_MOUSEWHEEL 0x020A +#endif +#ifndef WM_MOUSEHWHEEL +# define WM_MOUSEHWHEEL 0x020E +#endif + +struct PuglInternalsImpl { + HWND hwnd; + HDC hdc; + HGLRC hglrc; +}; + +LRESULT CALLBACK +wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); + +PuglView* +puglCreate(PuglNativeWindow parent, + const char* title, + int width, + int height, + bool resizable, + bool addToDesktop, + const char* x11Display) +{ + PuglView* view = (PuglView*)calloc(1, sizeof(PuglView)); + PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); + if (!view || !impl) { + return NULL; + } + + view->impl = impl; + view->width = width; + view->height = height; + + WNDCLASS wc; + wc.style = CS_OWNDC; + wc.lpfnWndProc = wndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = 0; + wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + wc.lpszMenuName = NULL; + wc.lpszClassName = "Pugl"; + RegisterClass(&wc); + + impl->hwnd = CreateWindow( + "Pugl", title, + (addToDesktop ? WS_VISIBLE : 0) | (parent ? WS_CHILD : (WS_POPUPWINDOW | WS_CAPTION)), + 0, 0, width, height, + (HWND)parent, NULL, NULL, NULL); + if (!impl->hwnd) { + free(impl); + free(view); + return NULL; + } + + SetWindowLongPtr(impl->hwnd, GWL_USERDATA, (LONG)view); + + impl->hdc = GetDC(impl->hwnd); + + PIXELFORMATDESCRIPTOR pfd; + ZeroMemory(&pfd, sizeof(pfd)); + pfd.nSize = sizeof(pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 24; + pfd.cDepthBits = 16; + pfd.iLayerType = PFD_MAIN_PLANE; + + int format = ChoosePixelFormat(impl->hdc, &pfd); + SetPixelFormat(impl->hdc, format, &pfd); + + impl->hglrc = wglCreateContext(impl->hdc); + wglMakeCurrent(impl->hdc, impl->hglrc); + + view->width = width; + view->height = height; + + return view; + + // unused + (void)resizable; + (void)x11Display; +} + +void +puglDestroy(PuglView* view) +{ + wglMakeCurrent(NULL, NULL); + wglDeleteContext(view->impl->hglrc); + ReleaseDC(view->impl->hwnd, view->impl->hdc); + DestroyWindow(view->impl->hwnd); + free(view->impl); + free(view); +} + +void +puglReshape(PuglView* view, int width, int height) +{ + wglMakeCurrent(view->impl->hdc, view->impl->hglrc); + + if (view->reshapeFunc) { + view->reshapeFunc(view, width, height); + } else { + puglDefaultReshape(view, width, height); + } + + view->width = width; + view->height = height; +} + +void +puglDisplay(PuglView* view) +{ + wglMakeCurrent(view->impl->hdc, view->impl->hglrc); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glLoadIdentity(); + + if (view->displayFunc) { + view->displayFunc(view); + } + + glFlush(); + SwapBuffers(view->impl->hdc); + view->redisplay = false; +} + +static PuglKey +keySymToSpecial(int sym) +{ + switch (sym) { + case VK_F1: return PUGL_KEY_F1; + case VK_F2: return PUGL_KEY_F2; + case VK_F3: return PUGL_KEY_F3; + case VK_F4: return PUGL_KEY_F4; + case VK_F5: return PUGL_KEY_F5; + case VK_F6: return PUGL_KEY_F6; + case VK_F7: return PUGL_KEY_F7; + case VK_F8: return PUGL_KEY_F8; + case VK_F9: return PUGL_KEY_F9; + case VK_F10: return PUGL_KEY_F10; + case VK_F11: return PUGL_KEY_F11; + case VK_F12: return PUGL_KEY_F12; + case VK_LEFT: return PUGL_KEY_LEFT; + case VK_UP: return PUGL_KEY_UP; + case VK_RIGHT: return PUGL_KEY_RIGHT; + case VK_DOWN: return PUGL_KEY_DOWN; + case VK_PRIOR: return PUGL_KEY_PAGE_UP; + case VK_NEXT: return PUGL_KEY_PAGE_DOWN; + case VK_HOME: return PUGL_KEY_HOME; + case VK_END: return PUGL_KEY_END; + case VK_INSERT: return PUGL_KEY_INSERT; + case VK_SHIFT: return PUGL_KEY_SHIFT; + case VK_CONTROL: return PUGL_KEY_CTRL; + case VK_MENU: return PUGL_KEY_ALT; + case VK_LWIN: return PUGL_KEY_SUPER; + case VK_RWIN: return PUGL_KEY_SUPER; + } + return (PuglKey)0; +} + +static void +processMouseEvent(PuglView* view, int button, bool press, LPARAM lParam) +{ + if (view->mouseFunc) { + view->mouseFunc(view, button, press, + GET_X_LPARAM(lParam), + GET_Y_LPARAM(lParam)); + } +} + +static void +setModifiers(PuglView* view) +{ + view->mods = 0; + view->mods |= (GetKeyState(VK_SHIFT) < 0) ? PUGL_MOD_SHIFT : 0; + view->mods |= (GetKeyState(VK_CONTROL) < 0) ? PUGL_MOD_CTRL : 0; + view->mods |= (GetKeyState(VK_MENU) < 0) ? PUGL_MOD_ALT : 0; + view->mods |= (GetKeyState(VK_LWIN) < 0) ? PUGL_MOD_SUPER : 0; + view->mods |= (GetKeyState(VK_RWIN) < 0) ? PUGL_MOD_SUPER : 0; +} + +static LRESULT +handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) +{ + PAINTSTRUCT ps; + PuglKey key; + + setModifiers(view); + switch (message) { + case WM_CREATE: + case WM_SHOWWINDOW: + case WM_SIZE: + puglReshape(view, view->width, view->height); + break; + case WM_PAINT: + BeginPaint(view->impl->hwnd, &ps); + puglDisplay(view); + EndPaint(view->impl->hwnd, &ps); + break; + case WM_MOUSEMOVE: + if (view->motionFunc) { + view->motionFunc( + view, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); + } + break; + case WM_LBUTTONDOWN: + processMouseEvent(view, 1, true, lParam); + break; + case WM_MBUTTONDOWN: + processMouseEvent(view, 2, true, lParam); + break; + case WM_RBUTTONDOWN: + processMouseEvent(view, 3, true, lParam); + break; + case WM_LBUTTONUP: + processMouseEvent(view, 1, false, lParam); + break; + case WM_MBUTTONUP: + processMouseEvent(view, 2, false, lParam); + break; + case WM_RBUTTONUP: + processMouseEvent(view, 3, false, lParam); + break; + case WM_MOUSEWHEEL: + if (view->scrollFunc) { + view->scrollFunc( + view, 0, (int16_t)HIWORD(wParam) / (float)WHEEL_DELTA); + } + break; + case WM_MOUSEHWHEEL: + if (view->scrollFunc) { + view->scrollFunc( + view, (int16_t)HIWORD(wParam) / float(WHEEL_DELTA), 0); + } + break; + case WM_KEYDOWN: + if (view->ignoreKeyRepeat && (lParam & (1 << 30))) { + break; + } // else nobreak + case WM_KEYUP: + if ((key = keySymToSpecial(wParam))) { + if (view->specialFunc) { + view->specialFunc(view, message == WM_KEYDOWN, key); + } + } else if (view->keyboardFunc) { + view->keyboardFunc(view, message == WM_KEYDOWN, wParam); + } + break; + case WM_QUIT: + if (view->closeFunc) { + view->closeFunc(view); + } + break; + default: + return DefWindowProc( + view->impl->hwnd, message, wParam, lParam); + } + + return 0; +} + +PuglStatus +puglProcessEvents(PuglView* view) +{ + MSG msg; + while (PeekMessage(&msg, view->impl->hwnd, 0, 0, PM_REMOVE)) { + handleMessage(view, msg.message, msg.wParam, msg.lParam); + } + + if (view->redisplay) { + puglDisplay(view); + } + + return PUGL_SUCCESS; +} + +LRESULT CALLBACK +wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + PuglView* view = (PuglView*)GetWindowLongPtr(hwnd, GWL_USERDATA); + switch (message) { + case WM_CREATE: + PostMessage(hwnd, WM_SHOWWINDOW, TRUE, 0); + return 0; + case WM_CLOSE: + PostQuitMessage(0); + return 0; + case WM_DESTROY: + return 0; + case WM_MOUSEWHEEL: + case WM_MOUSEHWHEEL: + PostMessage(hwnd, message, wParam, lParam); + return 0; + default: + if (view) { + return handleMessage(view, message, wParam, lParam); + } else { + return DefWindowProc(hwnd, message, wParam, lParam); + } + } +} + +void +puglPostRedisplay(PuglView* view) +{ + view->redisplay = true; +} + +PuglNativeWindow +puglGetNativeWindow(PuglView* view) +{ + return (PuglNativeWindow)view->impl->hwnd; +} diff --git a/source/libs/distrho/dgl/src/pugl/pugl_x11.c b/source/libs/distrho/dgl/src/pugl/pugl_x11.c new file mode 100644 index 000000000..759cd8801 --- /dev/null +++ b/source/libs/distrho/dgl/src/pugl/pugl_x11.c @@ -0,0 +1,379 @@ +/* + Copyright 2012 David Robillard + Copyright 2011-2012 Ben Loftis, Harrison Consoles + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file pugl_x11.c X11 Pugl Implementation. +*/ + +#include +#include +#include + +#include "pugl_x11.h" +#include "pugl_internal.h" + +/** + Attributes for single-buffered RGBA with at least + 4 bits per color and a 16 bit depth buffer. +*/ +static int attrListSgl[] = { + GLX_RGBA, + GLX_RED_SIZE, 4, + GLX_GREEN_SIZE, 4, + GLX_BLUE_SIZE, 4, + GLX_DEPTH_SIZE, 16, + None +}; + +/** + Attributes for double-buffered RGBA with at least + 4 bits per color and a 16 bit depth buffer. +*/ +static int attrListDbl[] = { + GLX_RGBA, GLX_DOUBLEBUFFER, + GLX_RED_SIZE, 4, + GLX_GREEN_SIZE, 4, + GLX_BLUE_SIZE, 4, + GLX_DEPTH_SIZE, 16, + None +}; + +PuglView* +puglCreate(PuglNativeWindow parent, + const char* title, + int width, + int height, + bool resizable, + bool addToDesktop, + const char* x11Display) +{ + PuglView* view = (PuglView*)calloc(1, sizeof(PuglView)); + PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); + if (!view || !impl) { + return nullptr; + } + + view->impl = impl; + view->width = width; + view->height = height; + + impl->display = XOpenDisplay(x11Display); + impl->screen = DefaultScreen(impl->display); + + XVisualInfo* vi = glXChooseVisual(impl->display, impl->screen, attrListDbl); + if (!vi) { + vi = glXChooseVisual(impl->display, impl->screen, attrListSgl); + impl->doubleBuffered = False; + printf("singlebuffered rendering will be used, no doublebuffering available\n"); + } else { + impl->doubleBuffered = True; + printf("doublebuffered rendering available\n"); + } + + int glxMajor, glxMinor; + glXQueryVersion(impl->display, &glxMajor, &glxMinor); + printf("GLX-Version %d.%d\n", glxMajor, glxMinor); + + impl->ctx = glXCreateContext(impl->display, vi, nullptr, GL_TRUE); + + Window xParent = parent + ? (Window)parent + : RootWindow(impl->display, impl->screen); + + Colormap cmap = XCreateColormap( + impl->display, xParent, vi->visual, AllocNone); + + XSetWindowAttributes attr; + memset(&attr, 0, sizeof(XSetWindowAttributes)); + attr.colormap = cmap; + attr.border_pixel = 0; + + attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask + | ButtonPressMask | ButtonReleaseMask + | PointerMotionMask | StructureNotifyMask; + + impl->win = XCreateWindow( + impl->display, xParent, + 0, 0, (unsigned int)view->width, (unsigned int)view->height, 0, vi->depth, InputOutput, vi->visual, + CWBorderPixel | CWColormap | CWEventMask, &attr); + + XSizeHints sizeHints; + memset(&sizeHints, 0, sizeof(sizeHints)); + if (!resizable) { + sizeHints.flags = PMinSize|PMaxSize; + sizeHints.min_width = width; + sizeHints.min_height = height; + sizeHints.max_width = width; + sizeHints.max_height = height; + XSetNormalHints(impl->display, impl->win, &sizeHints); + } + + if (title) { + XStoreName(impl->display, impl->win, title); + } + + if (!parent) { + Atom wmDelete = XInternAtom(impl->display, "WM_DELETE_WINDOW", True); + XSetWMProtocols(impl->display, impl->win, &wmDelete, 1); + } + + if (addToDesktop) { + XMapRaised(impl->display, impl->win); + } + + if (glXIsDirect(impl->display, impl->ctx)) { + printf("DRI enabled\n"); + } else { + printf("no DRI available\n"); + } + + XFree(vi); + + return view; +} + +void +puglDestroy(PuglView* view) +{ + if (!view) { + return; + } + + glXDestroyContext(view->impl->display, view->impl->ctx); + XDestroyWindow(view->impl->display, view->impl->win); + XCloseDisplay(view->impl->display); + free(view->impl); + free(view); +} + +static void +puglReshape(PuglView* view, int width, int height) +{ + glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx); + + if (view->reshapeFunc) { + view->reshapeFunc(view, width, height); + } else { + puglDefaultReshape(view, width, height); + } + + view->width = width; + view->height = height; +} + +static void +puglDisplay(PuglView* view) +{ + glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glLoadIdentity(); + + if (view->displayFunc) { + view->displayFunc(view); + } + + glFlush(); + if (view->impl->doubleBuffered) { + glXSwapBuffers(view->impl->display, view->impl->win); + } + + view->redisplay = false; +} + +static PuglKey +keySymToSpecial(KeySym sym) +{ + switch (sym) { + case XK_F1: return PUGL_KEY_F1; + case XK_F2: return PUGL_KEY_F2; + case XK_F3: return PUGL_KEY_F3; + case XK_F4: return PUGL_KEY_F4; + case XK_F5: return PUGL_KEY_F5; + case XK_F6: return PUGL_KEY_F6; + case XK_F7: return PUGL_KEY_F7; + case XK_F8: return PUGL_KEY_F8; + case XK_F9: return PUGL_KEY_F9; + case XK_F10: return PUGL_KEY_F10; + case XK_F11: return PUGL_KEY_F11; + case XK_F12: return PUGL_KEY_F12; + case XK_Left: return PUGL_KEY_LEFT; + case XK_Up: return PUGL_KEY_UP; + case XK_Right: return PUGL_KEY_RIGHT; + case XK_Down: return PUGL_KEY_DOWN; + case XK_Page_Up: return PUGL_KEY_PAGE_UP; + case XK_Page_Down: return PUGL_KEY_PAGE_DOWN; + case XK_Home: return PUGL_KEY_HOME; + case XK_End: return PUGL_KEY_END; + case XK_Insert: return PUGL_KEY_INSERT; + case XK_Shift_L: return PUGL_KEY_SHIFT; + case XK_Shift_R: return PUGL_KEY_SHIFT; + case XK_Control_L: return PUGL_KEY_CTRL; + case XK_Control_R: return PUGL_KEY_CTRL; + case XK_Alt_L: return PUGL_KEY_ALT; + case XK_Alt_R: return PUGL_KEY_ALT; + case XK_Super_L: return PUGL_KEY_SUPER; + case XK_Super_R: return PUGL_KEY_SUPER; + } + return (PuglKey)0; +} + +static void +setModifiers(PuglView* view, int xstate) +{ + view->mods = 0; + view->mods |= (xstate & ShiftMask) ? PUGL_MOD_SHIFT : 0; + view->mods |= (xstate & ControlMask) ? PUGL_MOD_CTRL : 0; + view->mods |= (xstate & Mod1Mask) ? PUGL_MOD_ALT : 0; + view->mods |= (xstate & Mod4Mask) ? PUGL_MOD_SUPER : 0; +} + +PuglStatus +puglProcessEvents(PuglView* view) +{ + XEvent event; + while (XPending(view->impl->display) > 0) { + XNextEvent(view->impl->display, &event); + switch (event.type) { + case MapNotify: + puglReshape(view, view->width, view->height); + break; + case ConfigureNotify: + if ((event.xconfigure.width != view->width) || + (event.xconfigure.height != view->height)) { + puglReshape(view, + event.xconfigure.width, + event.xconfigure.height); + } + break; + case Expose: + if (event.xexpose.count != 0) { + break; + } + puglDisplay(view); + view->redisplay = false; + break; + case MotionNotify: + setModifiers(view, (int)event.xmotion.state); + if (view->motionFunc) { + view->motionFunc(view, event.xmotion.x, event.xmotion.y); + } + break; + case ButtonPress: + setModifiers(view, (int)event.xbutton.state); + if (event.xbutton.button >= 4 && event.xbutton.button <= 7) { + if (view->scrollFunc) { + float dx = 0, dy = 0; + switch (event.xbutton.button) { + case 4: dy = 1.0f; break; + case 5: dy = -1.0f; break; + case 6: dx = -1.0f; break; + case 7: dx = 1.0f; break; + } + view->scrollFunc(view, dx, dy); + } + break; + } + // nobreak + case ButtonRelease: + setModifiers(view, (int)event.xbutton.state); + if (view->mouseFunc && + (event.xbutton.button < 4 || event.xbutton.button > 7)) { + view->mouseFunc(view, + (int)event.xbutton.button, event.type == ButtonPress, + event.xbutton.x, event.xbutton.y); + } + break; + case KeyPress: { + setModifiers(view, (int)event.xkey.state); + KeySym sym; + char str[5]; + int n = XLookupString(&event.xkey, str, 4, &sym, nullptr); + PuglKey key = keySymToSpecial(sym); + if (!key && view->keyboardFunc) { + if (n == 1) { + view->keyboardFunc(view, true, (uint32_t)str[0]); + } else { + fprintf(stderr, "warning: Unknown key %X\n", (int)sym); + } + } else if (view->specialFunc) { + view->specialFunc(view, true, key); + } + } break; + case KeyRelease: { + setModifiers(view, (int)event.xkey.state); + bool repeated = false; + if (view->ignoreKeyRepeat && + XEventsQueued(view->impl->display, QueuedAfterReading)) { + XEvent next; + XPeekEvent(view->impl->display, &next); + if (next.type == KeyPress && + next.xkey.time == event.xkey.time && + next.xkey.keycode == event.xkey.keycode) { + XNextEvent(view->impl->display, &event); + repeated = true; + } + } + + if (!repeated && view->keyboardFunc) { + KeySym sym = XKeycodeToKeysym( + view->impl->display, (KeyCode)event.xkey.keycode, 0); + PuglKey special = keySymToSpecial(sym); + if (!special) { + view->keyboardFunc(view, false, (uint32_t)sym); + } else if (view->specialFunc) { + view->specialFunc(view, false, special); + } + } + } break; + case ClientMessage: + if (!strcmp(XGetAtomName(view->impl->display, + event.xclient.message_type), + "WM_PROTOCOLS")) { + if (view->closeFunc) { + view->closeFunc(view); + } + } + break; + default: + break; + } + } + + if (view->redisplay) { + puglDisplay(view); + } + + return PUGL_SUCCESS; +} + +void +puglPostRedisplay(PuglView* view) +{ + view->redisplay = true; +} + +PuglNativeWindow +puglGetNativeWindow(PuglView* view) +{ + return static_cast(view->impl->win); +} + +PuglInternals* +puglGetInternalsImpl(PuglView* view) +{ + return view->impl; +} diff --git a/source/libs/distrho/dgl/src/pugl/pugl_x11.h b/source/libs/distrho/dgl/src/pugl/pugl_x11.h new file mode 100644 index 000000000..3d592a792 --- /dev/null +++ b/source/libs/distrho/dgl/src/pugl/pugl_x11.h @@ -0,0 +1,46 @@ +/* + Copyright 2012 David Robillard + Copyright 2011-2012 Ben Loftis, Harrison Consoles + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file pugl_x11.h X11 Pugl Implementation (PuglInternalsImpl only). +*/ + +#ifndef PUGL_X11_H_INCLUDED +#define PUGL_X11_H_INCLUDED + +#include "pugl.h" + +#include +#include +#include +#include +#include + +struct PuglInternalsImpl { + Display* display; + int screen; + Window win; + GLXContext ctx; + Bool doubleBuffered; +}; + +typedef struct PuglInternalsImpl PuglInternals; + +PuglInternals* +puglGetInternalsImpl(PuglView* view); + +#endif /* PUGL_X11_H_INCLUDED */ diff --git a/source/libs/distrho/src/DistrhoUI.cpp b/source/libs/distrho/src/DistrhoUI.cpp index 88eda713a..1d7041098 100644 --- a/source/libs/distrho/src/DistrhoUI.cpp +++ b/source/libs/distrho/src/DistrhoUI.cpp @@ -38,7 +38,9 @@ UI::UI() #endif #ifdef DISTRHO_UI_QT4 - pData->widget = (Qt4UI*)this; + pData->ui = (Qt4UI*)this; +#else + pData->ui = (OpenGLUI*)this; #endif } diff --git a/source/libs/distrho/src/DistrhoUIInternal.hpp b/source/libs/distrho/src/DistrhoUIInternal.hpp index 348776b91..a0bd5f0d8 100644 --- a/source/libs/distrho/src/DistrhoUIInternal.hpp +++ b/source/libs/distrho/src/DistrhoUIInternal.hpp @@ -19,13 +19,11 @@ #include "DistrhoDefines.h" -//#ifdef DISTRHO_UI_OPENGL -//# include "DistrhoUIOpenGL.h" -// START_NAMESPACE_DISTRHO -//# include "pugl/pugl.h" -// END_NAMESPACE_DISTRHO -//#else - +#ifdef DISTRHO_UI_OPENGL +# include "../DistrhoUIOpenGL.hpp" +# include "../dgl/App.hpp" +# include "../dgl/Window.hpp" +#else # include "../DistrhoUIQt4.hpp" # include # include @@ -34,30 +32,26 @@ # ifdef Q_WS_X11 # include # endif - -//#endif +#endif START_NAMESPACE_DISTRHO // ------------------------------------------------- -//#ifdef DISTRHO_UI_OPENGL -//typedef PuglView NativeWidget; -//#else -typedef QWidget NativeWidget; -//#endif - typedef void (*editParamFunc) (void* ptr, uint32_t index, bool started); typedef void (*setParamFunc) (void* ptr, uint32_t index, float value); typedef void (*setStateFunc) (void* ptr, const char* key, const char* value); typedef void (*sendNoteFunc) (void* ptr, bool onOff, uint8_t channel, uint8_t note, uint8_t velo); typedef void (*uiResizeFunc) (void* ptr, unsigned int width, unsigned int height); -extern double d_lastUiSampleRate; +extern double d_lastUiSampleRate; +#ifdef DISTRHO_UI_OPENGL +extern Window* d_lastUiParent; +#endif // ------------------------------------------------- -//#ifdef DISTRHO_UI_QT4 +#ifdef DISTRHO_UI_QT4 # ifdef Q_WS_X11 class QEmbedWidget : public QX11EmbedWidget # else @@ -71,7 +65,7 @@ public: void embedInto(WId id); WId containerWinId() const; }; -//#endif +#endif // ------------------------------------------------- @@ -80,27 +74,23 @@ struct UIPrivateData { double sampleRate; uint32_t parameterOffset; - // UI - void* ptr; - NativeWidget* widget; - // Callbacks editParamFunc editParamCallbackFunc; setParamFunc setParamCallbackFunc; setStateFunc setStateCallbackFunc; sendNoteFunc sendNoteCallbackFunc; uiResizeFunc uiResizeCallbackFunc; + void* ptr; UIPrivateData() : sampleRate(d_lastUiSampleRate), parameterOffset(0), - ptr(nullptr), - widget(nullptr), editParamCallbackFunc(nullptr), setParamCallbackFunc(nullptr), setStateCallbackFunc(nullptr), sendNoteCallbackFunc(nullptr), - uiResizeCallbackFunc(nullptr) + uiResizeCallbackFunc(nullptr), + ptr(nullptr) { assert(d_lastUiSampleRate != 0.0); } @@ -150,15 +140,14 @@ class UIInternal { public: UIInternal(void* ptr, intptr_t winId, editParamFunc editParamCall, setParamFunc setParamCall, setStateFunc setStateCall, sendNoteFunc sendNoteCall, uiResizeFunc uiResizeCall) - : kUi(createUI()), - kData((kUi != nullptr) ? kUi->pData : nullptr), #ifdef DISTRHO_UI_QT4 - qtMouseDown(false), - qtGrip(nullptr), - qtWidget(nullptr) + : qtGrip(nullptr), + qtWidget(nullptr), #else - glInitiated(false) + : glWindow(createWindow(winId)), #endif + kUi(createUI()), + kData((kUi != nullptr) ? kUi->pData : nullptr) { assert(kUi != nullptr); assert(winId != 0); @@ -173,7 +162,11 @@ public: kData->sendNoteCallbackFunc = sendNoteCall; kData->uiResizeCallbackFunc = uiResizeCall; +#ifdef DISTRHO_UI_QT4 createWindow(winId); +#else + d_lastUiParent = nullptr; +#endif } ~UIInternal() @@ -255,20 +248,22 @@ public: kUi->d_uiIdle(); } - intptr_t getWindowId() + intptr_t getWinId() { #ifdef DISTRHO_UI_QT4 assert(qtWidget != nullptr); return (qtWidget != nullptr) ? qtWidget->winId() : 0; #else + assert(glWindow != nullptr); + return (glWindow != nullptr) ? glWindow->getWindowId() : 0; #endif } // --------------------------------------------- +#ifdef DISTRHO_UI_QT4 void createWindow(intptr_t parent) { -#ifdef DISTRHO_UI_QT4 assert(kUi != nullptr); assert(kData != nullptr); assert(kData->widget != nullptr); @@ -279,14 +274,12 @@ public: return; if (kData == nullptr) return; - if (kData->widget == nullptr) - return; if (qtGrip != nullptr) return; if (qtWidget != nullptr) return; - qtMouseDown = false; + Qt4UI* qt4Ui = (Qt4UI*)kUi; // create embedable widget qtWidget = new QEmbedWidget; @@ -298,10 +291,10 @@ public: qtWidget->setFixedSize(kUi->d_width(), kUi->d_height()); // set resize grip - if (((Qt4UI*)kUi)->d_resizable()) + if (qt4Ui->d_resizable()) { // listen for resize on the plugin widget - kData->widget->installEventFilter(this); + qt4Ui->installEventFilter(this); // create resize grip on bottom-right qtGrip = new QSizeGrip(qtWidget); @@ -318,9 +311,15 @@ public: // show it qtWidget->show(); + } #else -#endif + Window* createWindow(intptr_t parent) + { + Window* window = new Window(&glApp, parent); + d_lastParent = window; + return window; } +#endif void destroyWindow() { @@ -331,16 +330,16 @@ public: if (kData == nullptr) return; - if (kData->widget == nullptr) - return; if (qtWidget == nullptr) return; + Qt4UI* qt4Ui = (Qt4UI*)kUi; + // remove main widget, to prevent it from being auto-deleted - kData->widget->hide(); - qtWidget->layout()->removeWidget(kData->widget); - kData->widget->setParent(nullptr); - kData->widget->close(); + qt4Ui->hide(); + qtWidget->layout()->removeWidget(qt4Ui); + qt4Ui->setParent(nullptr); + qt4Ui->close(); qtWidget->close(); qtWidget->removeEventFilter(this); @@ -355,17 +354,36 @@ public: delete qtWidget; qtWidget = nullptr; #else + assert(kData != nullptr); + assert(glWindow != nullptr); + + if (kData == nullptr) + return; + if (glWindow == nullptr) + return; + + glWindow->hide(); + delete glWindow; + glWindow = nullptr; #endif } // --------------------------------------------- +private: +#ifdef DISTRHO_UI_QT4 + QSizeGrip* qtGrip; + QEmbedWidget* qtWidget; +#else + App glApp; + Window* glWindow; +#endif + protected: UI* const kUi; UIPrivateData* const kData; #ifdef DISTRHO_UI_QT4 - // FIXME - remove qtMouseDown usage bool eventFilter(QObject* obj, QEvent* event) { assert(kUi != nullptr); @@ -378,52 +396,40 @@ protected: return false; if (kData == nullptr) return false; - if (kData->widget == nullptr) - return false; if (qtGrip == nullptr) return false; if (qtWidget == nullptr) return false; + Qt4UI* qt4Ui = (Qt4UI*)kUi; + if (obj == nullptr) { // nothing } else if (obj == qtGrip) { - if (event->type() == QEvent::MouseButtonPress) + if (event->type() == QEvent::MouseMove) { QMouseEvent* mEvent = (QMouseEvent*)event; + if (mEvent->button() == Qt::LeftButton) - qtMouseDown = true; - } - else if (event->type() == QEvent::MouseMove) - { - if (qtMouseDown) { - Qt4UI* qtUi = (Qt4UI*)kUi; - QMouseEvent* mEvent = (QMouseEvent*)event; - unsigned int width = qtUi->d_width() + mEvent->x() - qtGrip->width(); - unsigned int height = qtUi->d_height() + mEvent->y() - qtGrip->height(); + unsigned int width = qt4Ui->d_width() + mEvent->x() - qtGrip->width(); + unsigned int height = qt4Ui->d_height() + mEvent->y() - qtGrip->height(); - if (width < qtUi->d_minimumWidth()) - width = qtUi->d_minimumWidth(); - if (height < qtUi->d_minimumHeight()) - height = qtUi->d_minimumHeight(); + if (width < qt4Ui->d_minimumWidth()) + width = qt4Ui->d_minimumWidth(); + if (height < qt4Ui->d_minimumHeight()) + height = qt4Ui->d_minimumHeight(); - kData->widget->setFixedSize(width, height); + qt4Ui->setFixedSize(width, height); return true; } } - else if (event->type() == QEvent::MouseButtonRelease) - { - QMouseEvent* mEvent = (QMouseEvent*)event; - if (mEvent->button() == Qt::LeftButton) - qtMouseDown = false; - } } - else if (obj == kData->widget && event->type() == QEvent::Resize) + else if (obj == qt4Ui && event->type() == QEvent::Resize) { QResizeEvent* rEvent = (QResizeEvent*)event; const QSize& size = rEvent->size(); @@ -437,15 +443,6 @@ protected: return QObject::eventFilter(obj, event); } #endif - -private: -#ifdef DISTRHO_UI_QT4 - bool qtMouseDown; - QSizeGrip* qtGrip; - QEmbedWidget* qtWidget; -#else - bool glInitiated; -#endif }; // ------------------------------------------------- diff --git a/source/libs/distrho/src/DistrhoUIOpenGL.cpp b/source/libs/distrho/src/DistrhoUIOpenGL.cpp new file mode 100644 index 000000000..a3d3104aa --- /dev/null +++ b/source/libs/distrho/src/DistrhoUIOpenGL.cpp @@ -0,0 +1,41 @@ +/* + * DISTRHO Plugin Toolkit (DPT) + * Copyright (C) 2012-2013 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * For a full copy of the license see the LGPL.txt file + */ + +#include "DistrhoUIInternal.hpp" + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- +// Static data + +Window* d_lastParent = nullptr; + +// ------------------------------------------------- +// OpenGLUI + +OpenGLUI::OpenGLUI() + : UI(), + Widget(d_lastParent) +{ +} + +OpenGLUI::~OpenGLUI() +{ +} + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO diff --git a/source/libs/distrho/src/DistrhoUIQt4.cpp b/source/libs/distrho/src/DistrhoUIQt4.cpp index 64e20fccf..72fc405bb 100644 --- a/source/libs/distrho/src/DistrhoUIQt4.cpp +++ b/source/libs/distrho/src/DistrhoUIQt4.cpp @@ -58,13 +58,6 @@ Qt4UI::~Qt4UI() { } -// ------------------------------------------------- -// UI Callbacks - -void Qt4UI::d_uiIdle() -{ -} - // ------------------------------------------------- // Implement resize internally