Browse Source

Continue work for DISTRHO UI, now OpenGL

tags/1.9.4
falkTX 11 years ago
parent
commit
c01e3a1c07
24 changed files with 3327 additions and 93 deletions
  1. +0
    -5
      source/libs/distrho/DistrhoUI.hpp
  2. +70
    -0
      source/libs/distrho/DistrhoUIOpenGL.hpp
  3. +1
    -1
      source/libs/distrho/DistrhoUIQt4.hpp
  4. +45
    -0
      source/libs/distrho/dgl/App.hpp
  5. +79
    -0
      source/libs/distrho/dgl/Base.hpp
  6. +131
    -0
      source/libs/distrho/dgl/Geometry.hpp
  7. +56
    -0
      source/libs/distrho/dgl/Image.hpp
  8. +54
    -0
      source/libs/distrho/dgl/Widget.hpp
  9. +65
    -0
      source/libs/distrho/dgl/Window.hpp
  10. +56
    -0
      source/libs/distrho/dgl/src/App.cpp
  11. +82
    -0
      source/libs/distrho/dgl/src/AppPrivate.hpp
  12. +380
    -0
      source/libs/distrho/dgl/src/Geometry.cpp
  13. +115
    -0
      source/libs/distrho/dgl/src/Widget.cpp
  14. +497
    -0
      source/libs/distrho/dgl/src/Window.cpp
  15. +341
    -0
      source/libs/distrho/dgl/src/pugl/pugl.h
  16. +135
    -0
      source/libs/distrho/dgl/src/pugl/pugl_internal.h
  17. +331
    -0
      source/libs/distrho/dgl/src/pugl/pugl_osx.m
  18. +344
    -0
      source/libs/distrho/dgl/src/pugl/pugl_win.cpp
  19. +379
    -0
      source/libs/distrho/dgl/src/pugl/pugl_x11.c
  20. +46
    -0
      source/libs/distrho/dgl/src/pugl/pugl_x11.h
  21. +3
    -1
      source/libs/distrho/src/DistrhoUI.cpp
  22. +76
    -79
      source/libs/distrho/src/DistrhoUIInternal.hpp
  23. +41
    -0
      source/libs/distrho/src/DistrhoUIOpenGL.cpp
  24. +0
    -7
      source/libs/distrho/src/DistrhoUIQt4.cpp

+ 0
- 5
source/libs/distrho/DistrhoUI.hpp View File

@@ -82,11 +82,6 @@ protected:
private:
UIPrivateData* const pData;
friend class UIInternal;
#ifdef DISTRHO_UI_QT4
friend class Qt4UI;
#else
friend class OpenGLUI;
#endif
};

// -------------------------------------------------


+ 70
- 0
source/libs/distrho/DistrhoUIOpenGL.hpp View File

@@ -0,0 +1,70 @@
/*
* DISTRHO Plugin Toolkit (DPT)
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
*
* 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__

+ 1
- 1
source/libs/distrho/DistrhoUIQt4.hpp View File

@@ -58,7 +58,7 @@ protected:
// ---------------------------------------------
// UI Callbacks

virtual void d_uiIdle();
virtual void d_uiIdle() {}

private:
friend class UIInternal;


+ 45
- 0
source/libs/distrho/dgl/App.hpp View File

@@ -0,0 +1,45 @@
/*
* DISTRHO Plugin Toolkit (DPT)
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
*
* 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__

+ 79
- 0
source/libs/distrho/dgl/Base.hpp View File

@@ -0,0 +1,79 @@
/*
* DISTRHO Plugin Toolkit (DPT)
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
*
* 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 <OpenGL/glu.h>
#else
# include <GL/glu.h>
#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__

+ 131
- 0
source/libs/distrho/dgl/Geometry.hpp View File

@@ -0,0 +1,131 @@
/*
* DISTRHO Plugin Toolkit (DPT)
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
*
* 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<typename T>
class Point
{
public:
Point();
Point(T x, T y);
Point(const Point<T>& 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<T>& pos);

Point<T>& operator=(const Point<T>& pos);
Point<T>& operator+=(const Point<T>& pos);
Point<T>& operator-=(const Point<T>& pos);
bool operator==(const Point<T>& pos) const;
bool operator!=(const Point<T>& pos) const;

private:
T fX, fY;
template<typename> friend class Rectangle;
};

// -------------------------------------------------

template<typename T>
class Size
{
public:
Size();
Size(T width, T height);
Size(const Size<T>& size);

T getWidth() const;
T getHeight() const;

void setWidth(T width);
void setHeight(T height);

Size<T>& operator=(const Size<T>& size);
Size<T>& operator+=(const Size<T>& size);
Size<T>& operator-=(const Size<T>& size);
Size<T>& operator*=(T m);
Size<T>& operator/=(T d);
bool operator==(const Size<T>& size) const;
bool operator!=(const Size<T>& size) const;

private:
T fWidth, fHeight;
template<typename> friend class Rectangle;
};

// -------------------------------------------------

template<typename T>
class Rectangle
{
public:
Rectangle();
Rectangle(T x, T y, T width, T height);
Rectangle(T x, T y, const Size<T>& size);
Rectangle(const Point<T>& pos, T width, T height);
Rectangle(const Point<T>& pos, const Size<T>& size);
Rectangle(const Rectangle<T>& rect);

T getX() const;
T getY() const;
T getWidth() const;
T getHeight() const;

const Point<T>& getPos() const;
const Size<T>& getSize() const;

bool contains(T x, T y) const;
bool contains(const Point<T>& pos) const;

void setX(T x);
void setY(T y);
void setPos(T x, T y);
void setPos(const Point<T>& pos);

void move(T x, T y);
void move(const Point<T>& pos);

void setWidth(T width);
void setHeight(T height);
void setSize(T width, T height);
void setSize(const Size<T>& size);

Rectangle<T>& operator=(const Rectangle<T>& rect);

private:
Point<T> fPos;
Size<T> fSize;
};

// -------------------------------------------------

END_NAMESPACE_DISTRHO

#endif // __DGL_GEOMETRY_HPP__

+ 56
- 0
source/libs/distrho/dgl/Image.hpp View File

@@ -0,0 +1,56 @@
/*
* DISTRHO Plugin Toolkit (DPT)
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
*
* 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<int>& size, GLenum format = GL_BGRA, GLenum type = GL_UNSIGNED_BYTE);
Image(const Image& image);

void loadFromMemory(const char* data, const Size<int>& size, GLenum format = GL_BGRA, GLenum type = GL_UNSIGNED_BYTE);

bool isValid() const;

int getWidth() const;
int getHeight() const;
const Size<int>& getSize() const;

const char* getData() const;
GLenum getFormat() const;
GLenum getType() const;

private:
const char* fData;
Size<int> fSize;
GLenum fFormat;
GLenum fType;
};

// -------------------------------------------------

END_NAMESPACE_DISTRHO

#endif // __DGL_IMAGE_HPP__

+ 54
- 0
source/libs/distrho/dgl/Widget.hpp View File

@@ -0,0 +1,54 @@
/*
* DISTRHO Plugin Toolkit (DPT)
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
*
* 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__

+ 65
- 0
source/libs/distrho/dgl/Window.hpp View File

@@ -0,0 +1,65 @@
/*
* DISTRHO Plugin Toolkit (DPT)
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
*
* 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__

+ 56
- 0
source/libs/distrho/dgl/src/App.cpp View File

@@ -0,0 +1,56 @@
/*
* DISTRHO Plugin Toolkit (DPT)
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
*
* 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

+ 82
- 0
source/libs/distrho/dgl/src/AppPrivate.hpp View File

@@ -0,0 +1,82 @@
/*
* DISTRHO Plugin Toolkit (DPT)
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
*
* 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 <list>

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<Window*> fWindows;

friend class App;
};

// -------------------------------------------------

END_NAMESPACE_DISTRHO

#endif // __APP_PRIVATE_HPP__

+ 380
- 0
source/libs/distrho/dgl/src/Geometry.cpp View File

@@ -0,0 +1,380 @@
/*
* DISTRHO Plugin Toolkit (DPT)
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
*
* 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<typename T>
Point<T>::Point()
: fX(0),
fY(0)
{
}

template<typename T>
Point<T>::Point(T x, T y)
: fX(x),
fY(y)
{
}

template<typename T>
Point<T>::Point(const Point& pos)
: fX(pos.fX),
fY(pos.fY)
{
}

template<typename T>
T Point<T>::getX() const
{
return fX;
}

template<typename T>
T Point<T>::getY() const
{
return fY;
}

template<typename T>
void Point<T>::setX(T x)
{
fX = x;
}

template<typename T>
void Point<T>::setY(T y)
{
fY = y;
}

template<typename T>
void Point<T>::move(T x, T y)
{
fX += x;
fY += y;
}

template<typename T>
void Point<T>::move(const Point& pos)
{
fX += pos.fX;
fY += pos.fY;
}

template<typename T>
Point<T>& Point<T>::operator=(const Point<T>& pos)
{
fX = pos.fX;
fY = pos.fY;
return *this;
}

template<typename T>
Point<T>& Point<T>::operator+=(const Point<T>& pos)
{
fX += pos.fX;
fY += pos.fY;
return *this;
}

template<typename T>
Point<T>& Point<T>::operator-=(const Point<T>& pos)
{
fX -= pos.fX;
fY -= pos.fY;
return *this;
}

template<typename T>
bool Point<T>::operator==(const Point<T>& pos) const
{
return (fX == pos.fX && fY== pos.fY);
}

template<typename T>
bool Point<T>::operator!=(const Point<T>& pos) const
{
return !operator==(pos);
}

// -------------------------------------------------
// Size

template<typename T>
Size<T>::Size()
: fWidth(0),
fHeight(0)
{
}

template<typename T>
Size<T>::Size(T width, T height)
: fWidth(width),
fHeight(height)
{
}

template<typename T>
Size<T>::Size(const Size<T>& size)
: fWidth(size.fWidth),
fHeight(size.fHeight)
{
}

template<typename T>
T Size<T>::getWidth() const
{
return fWidth;
}

template<typename T>
T Size<T>::getHeight() const
{
return fHeight;
}

template<typename T>
void Size<T>::setWidth(T width)
{
fWidth = width;
}

template<typename T>
void Size<T>::setHeight(T height)
{
fHeight = height;
}

template<typename T>
Size<T>& Size<T>::operator=(const Size<T>& size)
{
fWidth = size.fWidth;
fHeight = size.fHeight;
return *this;
}

template<typename T>
Size<T>& Size<T>::operator+=(const Size<T>& size)
{
fWidth += size.fWidth;
fHeight += size.fHeight;
return *this;
}

template<typename T>
Size<T>& Size<T>::operator-=(const Size<T>& size)
{
fWidth -= size.fWidth;
fHeight -= size.fHeight;
return *this;
}

template<typename T>
Size<T>& Size<T>::operator*=(T m)
{
fWidth *= m;
fHeight *= m;
return *this;
}

template<typename T>
Size<T>& Size<T>::operator/=(T d)
{
fWidth /= d;
fHeight /= d;
return *this;
}

template<typename T>
bool Size<T>::operator==(const Size<T>& size) const
{
return (fWidth == size.fWidth && fHeight == size.fHeight);
}

template<typename T>
bool Size<T>::operator!=(const Size<T>& size) const
{
return !operator==(size);
}

// -------------------------------------------------
// Rectangle

template<typename T>
Rectangle<T>::Rectangle()
: fPos(0, 0),
fSize(0, 0)
{
}

template<typename T>
Rectangle<T>::Rectangle(T x, T y, T width, T height)
: fPos(x, y),
fSize(width, height)
{
}

template<typename T>
Rectangle<T>::Rectangle(T x, T y, const Size<T>& size)
: fPos(x, y),
fSize(size)
{
}

template<typename T>
Rectangle<T>::Rectangle(const Point<T>& pos, T width, T height)
: fPos(pos),
fSize(width, height)
{
}

template<typename T>
Rectangle<T>::Rectangle(const Point<T>& pos, const Size<T>& size)
: fPos(pos),
fSize(size)
{
}

template<typename T>
Rectangle<T>::Rectangle(const Rectangle<T>& rect)
: fPos(rect._pos),
fSize(rect._size)
{
}

template<typename T>
T Rectangle<T>::getX() const
{
return fPos.fX;
}

template<typename T>
T Rectangle<T>::getY() const
{
return fPos.fY;
}

template<typename T>
T Rectangle<T>::getWidth() const
{
return fSize.fWidth;
}

template<typename T>
T Rectangle<T>::getHeight() const
{
return fSize.fHeight;
}

template<typename T>
const Point<T>& Rectangle<T>::getPos() const
{
return fPos;
}

template<typename T>
const Size<T>& Rectangle<T>::getSize() const
{
return fSize;
}

template<typename T>
bool Rectangle<T>::contains(T x, T y) const
{
return (x >= fPos.fX && y >= fPos.fY && x <= fPos.fX+fSize.fWidth && y <= fPos.fY+fSize.fHeight);
}

template<typename T>
bool Rectangle<T>::contains(const Point<T>& pos) const
{
return contains(pos.fX, pos.fY);
}

#if 0
template<typename T>
void Rectangle::setX(int x)
{
_pos._x = x;
}

template<typename T>
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


+ 115
- 0
source/libs/distrho/dgl/src/Widget.cpp View File

@@ -0,0 +1,115 @@
/*
* DISTRHO Plugin Toolkit (DPT)
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
*
* 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

+ 497
- 0
source/libs/distrho/dgl/src/Window.cpp View File

@@ -0,0 +1,497 @@
/*
* DISTRHO Plugin Toolkit (DPT)
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
*
* 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<Widget*> 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>(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

+ 341
- 0
source/libs/distrho/dgl/src/pugl/pugl.h View File

@@ -0,0 +1,341 @@
/*
Copyright 2012 David Robillard <http://drobilla.net>

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 <stdint.h>

/*
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 <windows.h> /* 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 <stdbool.h>
#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 */

+ 135
- 0
source/libs/distrho/dgl/src/pugl/pugl_internal.h View File

@@ -0,0 +1,135 @@
/*
Copyright 2012 David Robillard <http://drobilla.net>

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;
}

+ 331
- 0
source/libs/distrho/dgl/src/pugl/pugl_osx.m View File

@@ -0,0 +1,331 @@
/*
Copyright 2012 David Robillard <http://drobilla.net>

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 <stdlib.h>

#import <Cocoa/Cocoa.h>

#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;
}

+ 344
- 0
source/libs/distrho/dgl/src/pugl/pugl_win.cpp View File

@@ -0,0 +1,344 @@
/*
Copyright 2012 David Robillard <http://drobilla.net>

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 <windows.h>
#include <windowsx.h>
#include <GL/gl.h>

#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;
}

+ 379
- 0
source/libs/distrho/dgl/src/pugl/pugl_x11.c View File

@@ -0,0 +1,379 @@
/*
Copyright 2012 David Robillard <http://drobilla.net>
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 <stdio.h>
#include <stdlib.h>
#include <string.h>

#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<PuglNativeWindow>(view->impl->win);
}

PuglInternals*
puglGetInternalsImpl(PuglView* view)
{
return view->impl;
}

+ 46
- 0
source/libs/distrho/dgl/src/pugl/pugl_x11.h View File

@@ -0,0 +1,46 @@
/*
Copyright 2012 David Robillard <http://drobilla.net>
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 <GL/gl.h>
#include <GL/glx.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>

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 */

+ 3
- 1
source/libs/distrho/src/DistrhoUI.cpp View File

@@ -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
}



+ 76
- 79
source/libs/distrho/src/DistrhoUIInternal.hpp View File

@@ -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 <QtGui/QMouseEvent>
# include <QtGui/QResizeEvent>
@@ -34,30 +32,26 @@
# ifdef Q_WS_X11
# include <QtGui/QX11EmbedWidget>
# 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
};

// -------------------------------------------------


+ 41
- 0
source/libs/distrho/src/DistrhoUIOpenGL.cpp View File

@@ -0,0 +1,41 @@
/*
* DISTRHO Plugin Toolkit (DPT)
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
*
* 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

+ 0
- 7
source/libs/distrho/src/DistrhoUIQt4.cpp View File

@@ -58,13 +58,6 @@ Qt4UI::~Qt4UI()
{
}

// -------------------------------------------------
// UI Callbacks

void Qt4UI::d_uiIdle()
{
}

// -------------------------------------------------
// Implement resize internally



Loading…
Cancel
Save