@@ -189,6 +189,8 @@ endif | |||||
ifeq ($(HAVE_DGL),true) | ifeq ($(HAVE_DGL),true) | ||||
DGL_FLAGS += -DHAVE_DGL | |||||
ifeq ($(MACOS),true) | ifeq ($(MACOS),true) | ||||
DGL_LIBS = -framework OpenGL -framework Cocoa | DGL_LIBS = -framework OpenGL -framework Cocoa | ||||
endif | endif | ||||
@@ -198,8 +200,8 @@ DGL_LIBS = -lopengl32 -lgdi32 | |||||
endif | endif | ||||
ifneq ($(MACOS_OR_WIN32),true) | ifneq ($(MACOS_OR_WIN32),true) | ||||
DGL_FLAGS = $(shell pkg-config --cflags gl x11) | |||||
DGL_LIBS = $(shell pkg-config --libs gl x11) | |||||
DGL_FLAGS += $(shell pkg-config --cflags gl x11) | |||||
DGL_LIBS += $(shell pkg-config --libs gl x11) | |||||
endif | endif | ||||
endif # HAVE_DGL | endif # HAVE_DGL | ||||
@@ -73,6 +73,8 @@ | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// OpenGL includes | // OpenGL includes | ||||
#if defined(HAVE_DGL) | |||||
#ifdef DISTRHO_OS_MAC | #ifdef DISTRHO_OS_MAC | ||||
# include <OpenGL/gl.h> | # include <OpenGL/gl.h> | ||||
#else | #else | ||||
@@ -83,9 +85,20 @@ | |||||
# include <GL/glext.h> | # include <GL/glext.h> | ||||
#endif | #endif | ||||
#endif | |||||
// ----------------------------------------------------------------------- | |||||
// Cairo includes | |||||
#if defined(HAVE_DCAIRO) | |||||
# include <cairo/cairo.h> | |||||
#endif | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// Missing OpenGL defines | // Missing OpenGL defines | ||||
#if defined(HAVE_DGL) | |||||
#if defined(GL_BGR_EXT) && ! defined(GL_BGR) | #if defined(GL_BGR_EXT) && ! defined(GL_BGR) | ||||
# define GL_BGR GL_BGR_EXT | # define GL_BGR GL_BGR_EXT | ||||
#endif | #endif | ||||
@@ -98,6 +111,8 @@ | |||||
# define GL_CLAMP_TO_BORDER 0x812D | # define GL_CLAMP_TO_BORDER 0x812D | ||||
#endif | #endif | ||||
#endif | |||||
#ifdef DISTRHO_OS_WINDOWS | #ifdef DISTRHO_OS_WINDOWS | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// Fix OpenGL includes for Windows, based on glfw code | // Fix OpenGL includes for Windows, based on glfw code | ||||
@@ -19,7 +19,9 @@ | |||||
#include "Base.hpp" | #include "Base.hpp" | ||||
#if !defined(HAVE_DCAIRO) | |||||
struct NVGcolor; | struct NVGcolor; | ||||
#endif | |||||
START_NAMESPACE_DGL | START_NAMESPACE_DGL | ||||
@@ -95,12 +97,14 @@ struct Color { | |||||
*/ | */ | ||||
void fixBounds() noexcept; | void fixBounds() noexcept; | ||||
#if !defined(HAVE_DCAIRO) | |||||
/** | /** | ||||
@internal | @internal | ||||
Needed for NanoVG compatibility. | Needed for NanoVG compatibility. | ||||
*/ | */ | ||||
Color(const NVGcolor&) noexcept; | Color(const NVGcolor&) noexcept; | ||||
operator NVGcolor() const noexcept; | operator NVGcolor() const noexcept; | ||||
#endif | |||||
}; | }; | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
@@ -346,10 +346,12 @@ public: | |||||
*/ | */ | ||||
void moveBy(const Point<T>& pos) noexcept; | void moveBy(const Point<T>& pos) noexcept; | ||||
#if defined(HAVE_DGL) | |||||
/** | /** | ||||
Draw this line using the current OpenGL state. | Draw this line using the current OpenGL state. | ||||
*/ | */ | ||||
void draw(); | void draw(); | ||||
#endif | |||||
/** | /** | ||||
Return true if line is null (start and end pos are equal). | Return true if line is null (start and end pos are equal). | ||||
@@ -460,6 +462,7 @@ public: | |||||
*/ | */ | ||||
void setNumSegments(const uint num); | void setNumSegments(const uint num); | ||||
#if defined(HAVE_DGL) | |||||
/** | /** | ||||
Draw this circle using the current OpenGL state. | Draw this circle using the current OpenGL state. | ||||
*/ | */ | ||||
@@ -469,6 +472,7 @@ public: | |||||
Draw lines (outline of this circle) using the current OpenGL state. | Draw lines (outline of this circle) using the current OpenGL state. | ||||
*/ | */ | ||||
void drawOutline(); | void drawOutline(); | ||||
#endif | |||||
Circle<T>& operator=(const Circle<T>& cir) noexcept; | Circle<T>& operator=(const Circle<T>& cir) noexcept; | ||||
bool operator==(const Circle<T>& cir) const noexcept; | bool operator==(const Circle<T>& cir) const noexcept; | ||||
@@ -482,7 +486,9 @@ private: | |||||
// cached values | // cached values | ||||
float fTheta, fCos, fSin; | float fTheta, fCos, fSin; | ||||
#if defined(HAVE_DGL) | |||||
void _draw(const bool outline); | void _draw(const bool outline); | ||||
#endif | |||||
}; | }; | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
@@ -516,6 +522,7 @@ public: | |||||
*/ | */ | ||||
Triangle(const Triangle<T>& tri) noexcept; | Triangle(const Triangle<T>& tri) noexcept; | ||||
#if defined(HAVE_DGL) | |||||
/** | /** | ||||
Draw this triangle using the current OpenGL state. | Draw this triangle using the current OpenGL state. | ||||
*/ | */ | ||||
@@ -525,6 +532,7 @@ public: | |||||
Draw lines (outline of this triangle) using the current OpenGL state. | Draw lines (outline of this triangle) using the current OpenGL state. | ||||
*/ | */ | ||||
void drawOutline(); | void drawOutline(); | ||||
#endif | |||||
/** | /** | ||||
Return true if triangle is null (all its points are equal). | Return true if triangle is null (all its points are equal). | ||||
@@ -556,7 +564,9 @@ public: | |||||
private: | private: | ||||
Point<T> fPos1, fPos2, fPos3; | Point<T> fPos1, fPos2, fPos3; | ||||
#if defined(HAVE_DGL) | |||||
void _draw(const bool outline); | void _draw(const bool outline); | ||||
#endif | |||||
}; | }; | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
@@ -720,6 +730,7 @@ public: | |||||
*/ | */ | ||||
bool containsY(const T& y) const noexcept; | bool containsY(const T& y) const noexcept; | ||||
#if defined(HAVE_DGL) | |||||
/** | /** | ||||
Draw this rectangle using the current OpenGL state. | Draw this rectangle using the current OpenGL state. | ||||
*/ | */ | ||||
@@ -729,6 +740,7 @@ public: | |||||
Draw lines (outline of this rectangle) using the current OpenGL state. | Draw lines (outline of this rectangle) using the current OpenGL state. | ||||
*/ | */ | ||||
void drawOutline(); | void drawOutline(); | ||||
#endif | |||||
Rectangle<T>& operator=(const Rectangle<T>& rect) noexcept; | Rectangle<T>& operator=(const Rectangle<T>& rect) noexcept; | ||||
Rectangle<T>& operator*=(double m) noexcept; | Rectangle<T>& operator*=(double m) noexcept; | ||||
@@ -740,7 +752,9 @@ private: | |||||
Point<T> fPos; | Point<T> fPos; | ||||
Size<T> fSize; | Size<T> fSize; | ||||
#if defined(HAVE_DGL) | |||||
void _draw(const bool outline); | void _draw(const bool outline); | ||||
#endif | |||||
}; | }; | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
@@ -312,6 +312,10 @@ public: | |||||
*/ | */ | ||||
Window& getParentWindow() const noexcept; | Window& getParentWindow() const noexcept; | ||||
#if defined(HAVE_DCAIRO) | |||||
cairo_t* getGraphics() const noexcept; | |||||
#endif | |||||
/** | /** | ||||
Check if this widget contains the point defined by @a x and @a y. | Check if this widget contains the point defined by @a x and @a y. | ||||
*/ | */ | ||||
@@ -119,6 +119,10 @@ public: | |||||
Application& getApp() const noexcept; | Application& getApp() const noexcept; | ||||
intptr_t getWindowId() const noexcept; | intptr_t getWindowId() const noexcept; | ||||
#if defined(HAVE_DCAIRO) | |||||
cairo_t* getGraphics() const noexcept; | |||||
#endif | |||||
void addIdleCallback(IdleCallback* const callback); | void addIdleCallback(IdleCallback* const callback); | ||||
void removeIdleCallback(IdleCallback* const callback); | void removeIdleCallback(IdleCallback* const callback); | ||||
@@ -16,7 +16,9 @@ | |||||
#include "../Color.hpp" | #include "../Color.hpp" | ||||
#if !defined(HAVE_DCAIRO) | |||||
#include "nanovg/nanovg.h" | #include "nanovg/nanovg.h" | ||||
#endif | |||||
START_NAMESPACE_DGL | START_NAMESPACE_DGL | ||||
@@ -105,7 +107,36 @@ Color::Color(const Color& color1, const Color& color2, float u) noexcept | |||||
Color Color::fromHSL(float hue, float saturation, float lightness, float alpha) | Color Color::fromHSL(float hue, float saturation, float lightness, float alpha) | ||||
{ | { | ||||
#if defined(HAVE_DGL) | |||||
return nvgHSLA(hue, saturation, lightness, static_cast<uchar>(getFixedRange(alpha)*255.0f)); | return nvgHSLA(hue, saturation, lightness, static_cast<uchar>(getFixedRange(alpha)*255.0f)); | ||||
#else | |||||
float m1, m2; | |||||
Color col; | |||||
hue = fmodf(hue, 1.0f); | |||||
if (hue < 0.0f) hue += 1.0f; | |||||
fixRange(saturation); | |||||
fixRange(lightness); | |||||
m2 = lightness <= 0.5f ? (lightness * (1 + saturation)) : (lightness + saturation - lightness * saturation); | |||||
m1 = 2 * lightness - m2; | |||||
auto hue_ = [](float h, float m1, float m2) -> float | |||||
{ | |||||
if (h < 0) h += 1; | |||||
if (h > 1) h -= 1; | |||||
if (h < 1.0f/6.0f) | |||||
return m1 + (m2 - m1) * h * 6.0f; | |||||
else if (h < 3.0f/6.0f) | |||||
return m2; | |||||
else if (h < 4.0f/6.0f) | |||||
return m1 + (m2 - m1) * (2.0f/3.0f - h) * 6.0f; | |||||
return m1; | |||||
}; | |||||
col.red = hue_(hue + 1.0f/3.0f, m1, m2); | |||||
col.green = hue_(hue, m1, m2); | |||||
col.blue = hue_(hue - 1.0f/3.0f, m1, m2); | |||||
col.alpha = alpha; | |||||
col.fixBounds(); | |||||
return col; | |||||
#endif | |||||
} | } | ||||
Color Color::fromHTML(const char* rgb, float alpha) | Color Color::fromHTML(const char* rgb, float alpha) | ||||
@@ -224,6 +255,7 @@ void Color::fixBounds() noexcept | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
#if !defined(HAVE_DCAIRO) | |||||
Color::Color(const NVGcolor& c) noexcept | Color::Color(const NVGcolor& c) noexcept | ||||
: red(c.r), green(c.g), blue(c.b), alpha(c.a) | : red(c.r), green(c.g), blue(c.b), alpha(c.a) | ||||
{ | { | ||||
@@ -239,6 +271,7 @@ Color::operator NVGcolor() const noexcept | |||||
nc.a = alpha; | nc.a = alpha; | ||||
return nc; | return nc; | ||||
} | } | ||||
#endif | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
@@ -441,6 +441,7 @@ void Line<T>::moveBy(const Point<T>& pos) noexcept | |||||
fPosEnd.moveBy(pos); | fPosEnd.moveBy(pos); | ||||
} | } | ||||
#if defined(HAVE_DGL) | |||||
template<typename T> | template<typename T> | ||||
void Line<T>::draw() | void Line<T>::draw() | ||||
{ | { | ||||
@@ -455,6 +456,7 @@ void Line<T>::draw() | |||||
glEnd(); | glEnd(); | ||||
} | } | ||||
#endif | |||||
template<typename T> | template<typename T> | ||||
bool Line<T>::isNull() const noexcept | bool Line<T>::isNull() const noexcept | ||||
@@ -614,6 +616,7 @@ void Circle<T>::setNumSegments(const uint num) | |||||
fSin = std::sin(fTheta); | fSin = std::sin(fTheta); | ||||
} | } | ||||
#if defined(HAVE_DGL) | |||||
template<typename T> | template<typename T> | ||||
void Circle<T>::draw() | void Circle<T>::draw() | ||||
{ | { | ||||
@@ -625,6 +628,7 @@ void Circle<T>::drawOutline() | |||||
{ | { | ||||
_draw(true); | _draw(true); | ||||
} | } | ||||
#endif | |||||
template<typename T> | template<typename T> | ||||
Circle<T>& Circle<T>::operator=(const Circle<T>& cir) noexcept | Circle<T>& Circle<T>::operator=(const Circle<T>& cir) noexcept | ||||
@@ -650,6 +654,7 @@ bool Circle<T>::operator!=(const Circle<T>& cir) const noexcept | |||||
return (fPos != cir.fPos || d_isNotEqual(fSize, cir.fSize) || fNumSegments != cir.fNumSegments); | return (fPos != cir.fPos || d_isNotEqual(fSize, cir.fSize) || fNumSegments != cir.fNumSegments); | ||||
} | } | ||||
#if defined(HAVE_DGL) | |||||
template<typename T> | template<typename T> | ||||
void Circle<T>::_draw(const bool outline) | void Circle<T>::_draw(const bool outline) | ||||
{ | { | ||||
@@ -670,6 +675,7 @@ void Circle<T>::_draw(const bool outline) | |||||
glEnd(); | glEnd(); | ||||
} | } | ||||
#endif | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// Triangle | // Triangle | ||||
@@ -698,6 +704,7 @@ Triangle<T>::Triangle(const Triangle<T>& tri) noexcept | |||||
fPos2(tri.fPos2), | fPos2(tri.fPos2), | ||||
fPos3(tri.fPos3) {} | fPos3(tri.fPos3) {} | ||||
#if defined(HAVE_DGL) | |||||
template<typename T> | template<typename T> | ||||
void Triangle<T>::draw() | void Triangle<T>::draw() | ||||
{ | { | ||||
@@ -709,6 +716,7 @@ void Triangle<T>::drawOutline() | |||||
{ | { | ||||
_draw(true); | _draw(true); | ||||
} | } | ||||
#endif | |||||
template<typename T> | template<typename T> | ||||
bool Triangle<T>::isNull() const noexcept | bool Triangle<T>::isNull() const noexcept | ||||
@@ -755,6 +763,7 @@ bool Triangle<T>::operator!=(const Triangle<T>& tri) const noexcept | |||||
return (fPos1 != tri.fPos1 || fPos2 != tri.fPos2 || fPos3 != tri.fPos3); | return (fPos1 != tri.fPos1 || fPos2 != tri.fPos2 || fPos3 != tri.fPos3); | ||||
} | } | ||||
#if defined(HAVE_DGL) | |||||
template<typename T> | template<typename T> | ||||
void Triangle<T>::_draw(const bool outline) | void Triangle<T>::_draw(const bool outline) | ||||
{ | { | ||||
@@ -770,6 +779,7 @@ void Triangle<T>::_draw(const bool outline) | |||||
glEnd(); | glEnd(); | ||||
} | } | ||||
#endif | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// Rectangle | // Rectangle | ||||
@@ -952,6 +962,7 @@ bool Rectangle<T>::containsY(const T& y) const noexcept | |||||
return (y >= fPos.fY && y <= fPos.fY + fSize.fHeight); | return (y >= fPos.fY && y <= fPos.fY + fSize.fHeight); | ||||
} | } | ||||
#if defined(HAVE_DGL) | |||||
template<typename T> | template<typename T> | ||||
void Rectangle<T>::draw() | void Rectangle<T>::draw() | ||||
{ | { | ||||
@@ -963,6 +974,7 @@ void Rectangle<T>::drawOutline() | |||||
{ | { | ||||
_draw(true); | _draw(true); | ||||
} | } | ||||
#endif | |||||
template<typename T> | template<typename T> | ||||
Rectangle<T>& Rectangle<T>::operator=(const Rectangle<T>& rect) noexcept | Rectangle<T>& Rectangle<T>::operator=(const Rectangle<T>& rect) noexcept | ||||
@@ -998,6 +1010,7 @@ bool Rectangle<T>::operator!=(const Rectangle<T>& rect) const noexcept | |||||
return (fPos != rect.fPos || fSize != rect.fSize); | return (fPos != rect.fPos || fSize != rect.fSize); | ||||
} | } | ||||
#if defined(HAVE_DGL) | |||||
template<typename T> | template<typename T> | ||||
void Rectangle<T>::_draw(const bool outline) | void Rectangle<T>::_draw(const bool outline) | ||||
{ | { | ||||
@@ -1021,6 +1034,7 @@ void Rectangle<T>::_draw(const bool outline) | |||||
glEnd(); | glEnd(); | ||||
} | } | ||||
#endif | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// Possible template data types | // Possible template data types | ||||
@@ -189,6 +189,13 @@ Window& Widget::getParentWindow() const noexcept | |||||
return pData->parent; | return pData->parent; | ||||
} | } | ||||
#if defined(HAVE_DCAIRO) | |||||
cairo_t* Widget::getGraphics() const noexcept | |||||
{ | |||||
return pData->parent.getGraphics(); | |||||
} | |||||
#endif | |||||
bool Widget::contains(int x, int y) const noexcept | bool Widget::contains(int x, int y) const noexcept | ||||
{ | { | ||||
return (x >= 0 && y >= 0 && static_cast<uint>(x) < pData->size.getWidth() && static_cast<uint>(y) < pData->size.getHeight()); | return (x >= 0 && y >= 0 && static_cast<uint>(x) < pData->size.getWidth() && static_cast<uint>(y) < pData->size.getHeight()); | ||||
@@ -68,6 +68,7 @@ struct Widget::PrivateData { | |||||
if ((skipDisplay && ! renderingSubWidget) || size.isInvalid() || ! visible) | if ((skipDisplay && ! renderingSubWidget) || size.isInvalid() || ! visible) | ||||
return; | return; | ||||
#if defined(HAVE_DGL) | |||||
bool needsDisableScissor = false; | bool needsDisableScissor = false; | ||||
// reset color | // reset color | ||||
@@ -106,15 +107,18 @@ struct Widget::PrivateData { | |||||
glEnable(GL_SCISSOR_TEST); | glEnable(GL_SCISSOR_TEST); | ||||
needsDisableScissor = true; | needsDisableScissor = true; | ||||
} | } | ||||
#endif | |||||
// display widget | // display widget | ||||
self->onDisplay(); | self->onDisplay(); | ||||
#if defined(HAVE_DGL) | |||||
if (needsDisableScissor) | if (needsDisableScissor) | ||||
{ | { | ||||
glDisable(GL_SCISSOR_TEST); | glDisable(GL_SCISSOR_TEST); | ||||
needsDisableScissor = false; | needsDisableScissor = false; | ||||
} | } | ||||
#endif | |||||
displaySubWidgets(width, height, scaling); | displaySubWidgets(width, height, scaling); | ||||
} | } | ||||
@@ -19,6 +19,16 @@ | |||||
#include "../Base.hpp" | #include "../Base.hpp" | ||||
#undef PUGL_HAVE_CAIRO | |||||
#undef PUGL_HAVE_GL | |||||
#if defined(HAVE_DGL) | |||||
#define PUGL_HAVE_GL 1 | |||||
#endif | |||||
#if defined(HAVE_DCAIRO) | |||||
#define PUGL_HAVE_CAIRO 1 | |||||
#endif | |||||
#include "pugl/pugl.h" | #include "pugl/pugl.h" | ||||
#if defined(__GNUC__) && (__GNUC__ >= 7) | #if defined(__GNUC__) && (__GNUC__ >= 7) | ||||
@@ -203,6 +213,14 @@ struct Window::PrivateData { | |||||
return; | return; | ||||
} | } | ||||
#if defined(HAVE_DGL) | |||||
PuglContextType contextType = PUGL_GL; | |||||
#endif | |||||
#if defined(HAVE_DCAIRO) | |||||
PuglContextType contextType = PUGL_CAIRO; | |||||
#endif | |||||
puglInitContextType(fView, contextType); | |||||
puglInitUserResizable(fView, fResizable); | puglInitUserResizable(fView, fResizable); | ||||
puglInitWindowSize(fView, static_cast<int>(fWidth), static_cast<int>(fHeight)); | puglInitWindowSize(fView, static_cast<int>(fWidth), static_cast<int>(fHeight)); | ||||
@@ -222,11 +240,12 @@ struct Window::PrivateData { | |||||
puglCreateWindow(fView, nullptr); | puglCreateWindow(fView, nullptr); | ||||
PuglInternals* impl = fView->impl; | PuglInternals* impl = fView->impl; | ||||
#if defined(DISTRHO_OS_WINDOWS) | #if defined(DISTRHO_OS_WINDOWS) | ||||
hwnd = impl->hwnd; | hwnd = impl->hwnd; | ||||
DISTRHO_SAFE_ASSERT(hwnd != 0); | DISTRHO_SAFE_ASSERT(hwnd != 0); | ||||
#elif defined(DISTRHO_OS_MAC) | #elif defined(DISTRHO_OS_MAC) | ||||
mView = impl->glview; | |||||
mView = impl->view; | |||||
mWindow = impl->window; | mWindow = impl->window; | ||||
DISTRHO_SAFE_ASSERT(mView != nullptr); | DISTRHO_SAFE_ASSERT(mView != nullptr); | ||||
if (fUsingEmbed) { | if (fUsingEmbed) { | ||||
@@ -1081,7 +1100,7 @@ struct Window::PrivateData { | |||||
HWND hwndParent; | HWND hwndParent; | ||||
#elif defined(DISTRHO_OS_MAC) | #elif defined(DISTRHO_OS_MAC) | ||||
bool fNeedsIdle; | bool fNeedsIdle; | ||||
PuglOpenGLView* mView; | |||||
NSView<PuglGenericView>* mView; | |||||
id mWindow; | id mWindow; | ||||
id mParentWindow; | id mParentWindow; | ||||
#else | #else | ||||
@@ -1365,6 +1384,13 @@ intptr_t Window::getWindowId() const noexcept | |||||
return puglGetNativeWindow(pData->fView); | return puglGetNativeWindow(pData->fView); | ||||
} | } | ||||
#if defined(HAVE_DCAIRO) | |||||
cairo_t* Window::getGraphics() const noexcept | |||||
{ | |||||
return (cairo_t*)puglGetContext(pData->fView); | |||||
} | |||||
#endif | |||||
void Window::_addWidget(Widget* const widget) | void Window::_addWidget(Widget* const widget) | ||||
{ | { | ||||
pData->addWidget(widget); | pData->addWidget(widget); | ||||
@@ -1400,8 +1426,10 @@ void Window::removeIdleCallback(IdleCallback* const callback) | |||||
void Window::onDisplayBefore() | void Window::onDisplayBefore() | ||||
{ | { | ||||
#if defined(HAVE_DGL) | |||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | ||||
glLoadIdentity(); | glLoadIdentity(); | ||||
#endif | |||||
} | } | ||||
void Window::onDisplayAfter() | void Window::onDisplayAfter() | ||||
@@ -1410,6 +1438,7 @@ void Window::onDisplayAfter() | |||||
void Window::onReshape(uint width, uint height) | void Window::onReshape(uint width, uint height) | ||||
{ | { | ||||
#if defined(HAVE_DGL) | |||||
glEnable(GL_BLEND); | glEnable(GL_BLEND); | ||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||||
glMatrixMode(GL_PROJECTION); | glMatrixMode(GL_PROJECTION); | ||||
@@ -1418,6 +1447,7 @@ void Window::onReshape(uint width, uint height) | |||||
glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height)); | glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height)); | ||||
glMatrixMode(GL_MODELVIEW); | glMatrixMode(GL_MODELVIEW); | ||||
glLoadIdentity(); | glLoadIdentity(); | ||||
#endif | |||||
} | } | ||||
void Window::onClose() | void Window::onClose() | ||||
@@ -273,6 +273,20 @@ puglInitUserResizable(PuglView* view, bool resizable); | |||||
PUGL_API void | PUGL_API void | ||||
puglInitTransientFor(PuglView* view, uintptr_t parent); | puglInitTransientFor(PuglView* view, uintptr_t parent); | ||||
/** | |||||
Drawing context type. | |||||
*/ | |||||
typedef enum { | |||||
PUGL_GL, | |||||
PUGL_CAIRO | |||||
} PuglContextType; | |||||
/** | |||||
Set the context type before creating a window. | |||||
*/ | |||||
PUGL_API void | |||||
puglInitContextType(PuglView* view, PuglContextType type); | |||||
/** | /** | ||||
@} | @} | ||||
*/ | */ | ||||
@@ -349,6 +363,14 @@ puglSetHandle(PuglView* view, PuglHandle handle); | |||||
PUGL_API PuglHandle | PUGL_API PuglHandle | ||||
puglGetHandle(PuglView* view); | puglGetHandle(PuglView* view); | ||||
/** | |||||
Get the drawing context. | |||||
For PUGL_GL contexts, this is unused and returns NULL. | |||||
For PUGL_CAIRO contexts, this returns a pointer to a cairo_t. | |||||
*/ | |||||
PUGL_API void* | |||||
puglGetContext(PuglView* view); | |||||
/** | /** | ||||
Return the timestamp (if any) of the currently-processing event. | Return the timestamp (if any) of the currently-processing event. | ||||
*/ | */ | ||||
@@ -41,6 +41,7 @@ struct PuglViewImpl { | |||||
PuglInternals* impl; | PuglInternals* impl; | ||||
PuglNativeWindow parent; | PuglNativeWindow parent; | ||||
PuglContextType ctx_type; | |||||
uintptr_t transient_parent; | uintptr_t transient_parent; | ||||
int width; | int width; | ||||
@@ -140,6 +141,12 @@ puglCreate(PuglNativeWindow parent, | |||||
return view; | return view; | ||||
} | } | ||||
void | |||||
puglInitContextType(PuglView* view, PuglContextType type) | |||||
{ | |||||
view->ctx_type = type; | |||||
} | |||||
void | void | ||||
puglSetHandle(PuglView* view, PuglHandle handle) | puglSetHandle(PuglView* view, PuglHandle handle) | ||||
{ | { | ||||
@@ -239,6 +246,7 @@ puglLeaveContext(PuglView* view, bool flush); | |||||
static void | static void | ||||
puglDefaultReshape(int width, int height) | puglDefaultReshape(int width, int height) | ||||
{ | { | ||||
#ifdef PUGL_HAVE_GL | |||||
#ifdef ROBTK_HERE | #ifdef ROBTK_HERE | ||||
glViewport(0, 0, width, height); | glViewport(0, 0, width, height); | ||||
glMatrixMode(GL_PROJECTION); | glMatrixMode(GL_PROJECTION); | ||||
@@ -257,4 +265,5 @@ puglDefaultReshape(int width, int height) | |||||
glMatrixMode(GL_MODELVIEW); | glMatrixMode(GL_MODELVIEW); | ||||
glLoadIdentity(); | glLoadIdentity(); | ||||
#endif | #endif | ||||
#endif | |||||
} | } |
@@ -21,6 +21,10 @@ | |||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#import <Cocoa/Cocoa.h> | #import <Cocoa/Cocoa.h> | ||||
#ifdef PUGL_HAVE_CAIRO | |||||
#import <cairo.h> | |||||
#import <cairo-quartz.h> | |||||
#endif | |||||
#include "pugl_internal.h" | #include "pugl_internal.h" | ||||
@@ -93,7 +97,40 @@ puglDisplay(PuglView* view) | |||||
} | } | ||||
} | } | ||||
@interface PuglOpenGLView : NSOpenGLView | |||||
@protocol PuglGenericView | |||||
@required | |||||
- (PuglView *) puglView; | |||||
- (void) setPuglview:(PuglView *)pv; | |||||
@end | |||||
static unsigned | |||||
getModifiers(PuglView* view, NSEvent* ev) | |||||
{ | |||||
const unsigned modifierFlags = [ev modifierFlags]; | |||||
view->event_timestamp_ms = fmod([ev timestamp] * 1000.0, UINT32_MAX); | |||||
unsigned 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; | |||||
} | |||||
static int | |||||
getFixedAppKitButton(NSInteger button) | |||||
{ | |||||
switch (button) { | |||||
case 0: return 1; | |||||
case 1: return 3; | |||||
case 2: return 2; | |||||
default: return button; | |||||
} | |||||
} | |||||
#ifdef PUGL_HAVE_GL | |||||
@interface PuglOpenGLView : NSOpenGLView<PuglGenericView> | |||||
{ | { | ||||
@public | @public | ||||
PuglView* puglview; | PuglView* puglview; | ||||
@@ -101,6 +138,9 @@ puglDisplay(PuglView* view) | |||||
bool doubleBuffered; | bool doubleBuffered; | ||||
} | } | ||||
- (PuglView *) puglView; | |||||
- (void) setPuglview:(PuglView *)pv; | |||||
- (BOOL) acceptsFirstMouse:(NSEvent*)e; | - (BOOL) acceptsFirstMouse:(NSEvent*)e; | ||||
- (BOOL) acceptsFirstResponder; | - (BOOL) acceptsFirstResponder; | ||||
- (BOOL) isFlipped; | - (BOOL) isFlipped; | ||||
@@ -130,6 +170,13 @@ puglDisplay(PuglView* view) | |||||
@end | @end | ||||
@implementation PuglOpenGLView | @implementation PuglOpenGLView | ||||
- (PuglView *) puglView { | |||||
return self->puglview; | |||||
} | |||||
- (void) setPuglview:(PuglView *)pv { | |||||
self->puglview = pv; | |||||
} | |||||
- (BOOL) acceptsFirstMouse:(NSEvent*)e | - (BOOL) acceptsFirstMouse:(NSEvent*)e | ||||
{ | { | ||||
@@ -277,32 +324,296 @@ puglDisplay(PuglView* view) | |||||
[super viewWillMoveToWindow:newWindow]; | [super viewWillMoveToWindow:newWindow]; | ||||
} | } | ||||
static unsigned | |||||
getModifiers(PuglView* view, NSEvent* ev) | |||||
- (void) mouseMoved:(NSEvent*)event | |||||
{ | { | ||||
const unsigned modifierFlags = [ev modifierFlags]; | |||||
if (puglview->motionFunc) { | |||||
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil]; | |||||
puglview->mods = getModifiers(puglview, event); | |||||
puglview->motionFunc(puglview, loc.x, loc.y); | |||||
} | |||||
} | |||||
view->event_timestamp_ms = fmod([ev timestamp] * 1000.0, UINT32_MAX); | |||||
- (void) mouseDragged:(NSEvent*)event | |||||
{ | |||||
[self mouseMoved:event]; | |||||
} | |||||
unsigned 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) rightMouseDragged:(NSEvent*)event | |||||
{ | |||||
[self mouseDragged:event]; | |||||
} | } | ||||
static int | |||||
getFixedAppKitButton(NSInteger button) | |||||
- (void) otherMouseDragged:(NSEvent*)event | |||||
{ | { | ||||
switch (button) { | |||||
case 0: return 1; | |||||
case 1: return 3; | |||||
case 2: return 2; | |||||
default: return button; | |||||
[self mouseDragged:event]; | |||||
} | |||||
- (void) mouseDown:(NSEvent*)event | |||||
{ | |||||
if (puglview->mouseFunc) { | |||||
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil]; | |||||
puglview->mods = getModifiers(puglview, event); | |||||
puglview->mouseFunc(puglview, getFixedAppKitButton([event buttonNumber]), true, loc.x, loc.y); | |||||
} | |||||
} | |||||
- (void) rightMouseDown:(NSEvent*)event | |||||
{ | |||||
[self mouseDown:event]; | |||||
} | |||||
- (void) otherMouseDown:(NSEvent*)event | |||||
{ | |||||
[self mouseDown:event]; | |||||
} | |||||
- (void) mouseUp:(NSEvent*)event | |||||
{ | |||||
if (puglview->mouseFunc) { | |||||
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil]; | |||||
puglview->mods = getModifiers(puglview, event); | |||||
puglview->mouseFunc(puglview, getFixedAppKitButton([event buttonNumber]), false, loc.x, loc.y); | |||||
} | } | ||||
} | } | ||||
- (void) rightMouseUp:(NSEvent*)event | |||||
{ | |||||
[self mouseUp:event]; | |||||
} | |||||
- (void) otherMouseUp:(NSEvent*)event | |||||
{ | |||||
[self mouseUp:event]; | |||||
} | |||||
- (void) scrollWheel:(NSEvent*)event | |||||
{ | |||||
if (puglview->scrollFunc) { | |||||
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil]; | |||||
puglview->mods = getModifiers(puglview, event); | |||||
puglview->scrollFunc(puglview, | |||||
loc.x, loc.y, | |||||
[event deltaX], [event deltaY]); | |||||
} | |||||
} | |||||
- (void) keyDown:(NSEvent*)event | |||||
{ | |||||
if (puglview->keyboardFunc && !(puglview->ignoreKeyRepeat && [event isARepeat])) { | |||||
NSString* chars = [event characters]; | |||||
puglview->mods = getModifiers(puglview, event); | |||||
puglview->keyboardFunc(puglview, true, [chars characterAtIndex:0]); | |||||
} | |||||
} | |||||
- (void) keyUp:(NSEvent*)event | |||||
{ | |||||
if (puglview->keyboardFunc) { | |||||
NSString* chars = [event characters]; | |||||
puglview->mods = getModifiers(puglview, event); | |||||
puglview->keyboardFunc(puglview, false, [chars characterAtIndex:0]); | |||||
} | |||||
} | |||||
- (void) flagsChanged:(NSEvent*)event | |||||
{ | |||||
if (puglview->specialFunc) { | |||||
const unsigned mods = getModifiers(puglview, event); | |||||
if ((mods & PUGL_MOD_SHIFT) != (puglview->mods & PUGL_MOD_SHIFT)) { | |||||
puglview->specialFunc(puglview, mods & PUGL_MOD_SHIFT, PUGL_KEY_SHIFT); | |||||
} else if ((mods & PUGL_MOD_CTRL) != (puglview->mods & PUGL_MOD_CTRL)) { | |||||
puglview->specialFunc(puglview, mods & PUGL_MOD_CTRL, PUGL_KEY_CTRL); | |||||
} else if ((mods & PUGL_MOD_ALT) != (puglview->mods & PUGL_MOD_ALT)) { | |||||
puglview->specialFunc(puglview, mods & PUGL_MOD_ALT, PUGL_KEY_ALT); | |||||
} else if ((mods & PUGL_MOD_SUPER) != (puglview->mods & PUGL_MOD_SUPER)) { | |||||
puglview->specialFunc(puglview, mods & PUGL_MOD_SUPER, PUGL_KEY_SUPER); | |||||
} | |||||
puglview->mods = mods; | |||||
} | |||||
} | |||||
@end | |||||
#endif | |||||
#ifdef PUGL_HAVE_CAIRO | |||||
@interface PuglCairoView : NSView<PuglGenericView> | |||||
{ | |||||
PuglView* puglview; | |||||
cairo_t* cr; | |||||
NSTrackingArea* trackingArea; | |||||
} | |||||
- (PuglView *) puglView; | |||||
- (void) setPuglview:(PuglView *)pv; | |||||
- (cairo_t *) cairoContext; | |||||
- (BOOL) acceptsFirstMouse:(NSEvent*)e; | |||||
- (BOOL) acceptsFirstResponder; | |||||
- (BOOL) isFlipped; | |||||
- (BOOL) isOpaque; | |||||
- (BOOL) preservesContentInLiveResize; | |||||
- (id) initWithFrame:(NSRect)frame; | |||||
- (void) reshape; | |||||
- (void) drawRect:(NSRect)r; | |||||
/* TODO: duplication of code from PuglOpenGLView */ | |||||
- (void) cursorUpdate:(NSEvent*)e; | |||||
- (void) updateTrackingAreas; | |||||
- (void) viewWillMoveToWindow:(NSWindow*)newWindow; | |||||
- (void) mouseMoved:(NSEvent*)event; | |||||
- (void) mouseDragged:(NSEvent*)event; | |||||
- (void) rightMouseDragged:(NSEvent*)event; | |||||
- (void) otherMouseDragged:(NSEvent*)event; | |||||
- (void) mouseDown:(NSEvent*)event; | |||||
- (void) rightMouseDown:(NSEvent*)event; | |||||
- (void) otherMouseDown:(NSEvent*)event; | |||||
- (void) mouseUp:(NSEvent*)event; | |||||
- (void) rightMouseUp:(NSEvent*)event; | |||||
- (void) otherMouseUp:(NSEvent*)event; | |||||
- (void) scrollWheel:(NSEvent*)event; | |||||
- (void) keyDown:(NSEvent*)event; | |||||
- (void) keyUp:(NSEvent*)event; | |||||
- (void) flagsChanged:(NSEvent*)event; | |||||
@end | |||||
@implementation PuglCairoView | |||||
- (PuglView *) puglView { | |||||
return self->puglview; | |||||
} | |||||
- (void) setPuglview:(PuglView *)pv { | |||||
self->puglview = pv; | |||||
} | |||||
- (cairo_t *) cairoContext { | |||||
return cr; | |||||
} | |||||
- (BOOL) acceptsFirstMouse:(NSEvent*)e | |||||
{ | |||||
return YES; | |||||
// unused | |||||
(void)e; | |||||
} | |||||
- (BOOL) acceptsFirstResponder | |||||
{ | |||||
return YES; | |||||
} | |||||
- (BOOL) isFlipped | |||||
{ | |||||
return YES; | |||||
} | |||||
- (BOOL) isOpaque | |||||
{ | |||||
return YES; | |||||
} | |||||
- (BOOL) preservesContentInLiveResize | |||||
{ | |||||
return NO; | |||||
} | |||||
- (id) initWithFrame:(NSRect)frame { | |||||
puglview = nil; | |||||
cr = NULL; | |||||
trackingArea = nil; | |||||
[super initWithFrame:frame]; | |||||
return self; | |||||
} | |||||
- (void) reshape | |||||
{ | |||||
if (!puglview) { | |||||
/* NOTE: Apparently reshape gets called when the GC gets around to | |||||
deleting the view (?), so we must have reset puglview to NULL when | |||||
this comes around. | |||||
*/ | |||||
return; | |||||
} | |||||
NSRect bounds = [self bounds]; | |||||
int width = bounds.size.width; | |||||
int height = bounds.size.height; | |||||
puglEnterContext(puglview); | |||||
if (puglview->reshapeFunc) { | |||||
puglview->reshapeFunc(puglview, width, height); | |||||
} else { | |||||
puglDefaultReshape(width, height); | |||||
} | |||||
puglLeaveContext(puglview, false); | |||||
puglview->width = width; | |||||
puglview->height = height; | |||||
} | |||||
- (void) drawRect:(NSRect)r { | |||||
CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; | |||||
NSRect bounds = [self bounds]; | |||||
cairo_surface_t* surface; | |||||
cairo_t* cairo; | |||||
surface = cairo_quartz_surface_create_for_cg_context(ctx, bounds.size.width, bounds.size.height); | |||||
if (surface) { | |||||
cairo = cairo_create(surface); | |||||
if (cairo) { | |||||
self->cr = cairo; | |||||
puglEnterContext(puglview); | |||||
puglDisplay(puglview); | |||||
puglLeaveContext(puglview, true); | |||||
self->cr = NULL; | |||||
cairo_destroy(cairo); | |||||
} | |||||
cairo_surface_destroy(surface); | |||||
} | |||||
} | |||||
- (void) cursorUpdate:(NSEvent*)e | |||||
{ | |||||
[[NSCursor arrowCursor] set]; | |||||
// unused | |||||
return; (void)e; | |||||
} | |||||
- (void) updateTrackingAreas | |||||
{ | |||||
static const int opts = NSTrackingMouseEnteredAndExited | |||||
| NSTrackingMouseMoved | |||||
| NSTrackingEnabledDuringMouseDrag | |||||
| NSTrackingInVisibleRect | |||||
| NSTrackingActiveAlways | |||||
| NSTrackingCursorUpdate; | |||||
if (trackingArea != nil) { | |||||
[self removeTrackingArea:trackingArea]; | |||||
[trackingArea release]; | |||||
} | |||||
trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] | |||||
options:opts | |||||
owner:self | |||||
userInfo:nil]; | |||||
[self addTrackingArea:trackingArea]; | |||||
[super updateTrackingAreas]; | |||||
} | |||||
- (void) viewWillMoveToWindow:(NSWindow*)newWindow | |||||
{ | |||||
if (newWindow != nil) { | |||||
[newWindow setAcceptsMouseMovedEvents:YES]; | |||||
[newWindow makeFirstResponder:self]; | |||||
} | |||||
[super viewWillMoveToWindow:newWindow]; | |||||
} | |||||
- (void) mouseMoved:(NSEvent*)event | - (void) mouseMoved:(NSEvent*)event | ||||
{ | { | ||||
if (puglview->motionFunc) { | if (puglview->motionFunc) { | ||||
@@ -410,11 +721,19 @@ getFixedAppKitButton(NSInteger button) | |||||
puglview->mods = mods; | puglview->mods = mods; | ||||
} | } | ||||
} | } | ||||
@end | @end | ||||
#endif | |||||
struct PuglInternalsImpl { | struct PuglInternalsImpl { | ||||
PuglOpenGLView* glview; | |||||
union { | |||||
NSView<PuglGenericView>* view; | |||||
#ifdef PUGL_HAVE_GL | |||||
PuglOpenGLView* glview; | |||||
#endif | |||||
#ifdef PUGL_HAVE_CAIRO | |||||
PuglCairoView* cairoview; | |||||
#endif | |||||
}; | |||||
id window; | id window; | ||||
}; | }; | ||||
@@ -427,13 +746,18 @@ puglInitInternals() | |||||
void | void | ||||
puglEnterContext(PuglView* view) | puglEnterContext(PuglView* view) | ||||
{ | { | ||||
[[view->impl->glview openGLContext] makeCurrentContext]; | |||||
#ifdef PUGL_HAVE_GL | |||||
if (view->ctx_type == PUGL_GL) { | |||||
[[view->impl->glview openGLContext] makeCurrentContext]; | |||||
} | |||||
#endif | |||||
} | } | ||||
void | void | ||||
puglLeaveContext(PuglView* view, bool flush) | puglLeaveContext(PuglView* view, bool flush) | ||||
{ | { | ||||
if (flush) { | |||||
#ifdef PUGL_HAVE_GL | |||||
if (view->ctx_type == PUGL_GL && flush) { | |||||
if (view->impl->glview->doubleBuffered) { | if (view->impl->glview->doubleBuffered) { | ||||
[[view->impl->glview openGLContext] flushBuffer]; | [[view->impl->glview openGLContext] flushBuffer]; | ||||
} else { | } else { | ||||
@@ -441,6 +765,7 @@ puglLeaveContext(PuglView* view, bool flush) | |||||
} | } | ||||
//[NSOpenGLContext clearCurrentContext]; | //[NSOpenGLContext clearCurrentContext]; | ||||
} | } | ||||
#endif | |||||
} | } | ||||
int | int | ||||
@@ -451,22 +776,31 @@ puglCreateWindow(PuglView* view, const char* title) | |||||
[NSAutoreleasePool new]; | [NSAutoreleasePool new]; | ||||
[NSApplication sharedApplication]; | [NSApplication sharedApplication]; | ||||
impl->glview = [PuglOpenGLView new]; | |||||
#ifdef PUGL_HAVE_GL | |||||
if (view->ctx_type == PUGL_GL) { | |||||
impl->glview = [PuglOpenGLView new]; | |||||
} | |||||
#endif | |||||
#ifdef PUGL_HAVE_CAIRO | |||||
if (view->ctx_type == PUGL_CAIRO) { | |||||
impl->cairoview = [PuglCairoView new]; | |||||
} | |||||
#endif | |||||
if (!impl->glview) { | |||||
if (!impl->view) { | |||||
return 1; | return 1; | ||||
} | } | ||||
impl->glview->puglview = view; | |||||
[impl->view setPuglview:view]; | |||||
if (view->user_resizable) { | if (view->user_resizable) { | ||||
[impl->glview setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; | |||||
[impl->view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; | |||||
} | } | ||||
if (view->parent) { | if (view->parent) { | ||||
[impl->glview retain]; | |||||
[impl->view retain]; | |||||
NSView* pview = (NSView*)view->parent; | NSView* pview = (NSView*)view->parent; | ||||
[pview addSubview:impl->glview]; | |||||
[pview addSubview:impl->view]; | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -482,8 +816,8 @@ puglCreateWindow(PuglView* view, const char* title) | |||||
} | } | ||||
[window setPuglview:view]; | [window setPuglview:view]; | ||||
[window setContentView:impl->glview]; | |||||
[window makeFirstResponder:impl->glview]; | |||||
[window setContentView:impl->view]; | |||||
[window makeFirstResponder:impl->view]; | |||||
[window makeKeyAndOrderFront:window]; | [window makeKeyAndOrderFront:window]; | ||||
// wait for first puglShowWindow | // wait for first puglShowWindow | ||||
@@ -505,7 +839,7 @@ puglShowWindow(PuglView* view) | |||||
if (impl->window) { | if (impl->window) { | ||||
[impl->window setIsVisible:YES]; | [impl->window setIsVisible:YES]; | ||||
} else { | } else { | ||||
[view->impl->glview setHidden:NO]; | |||||
[view->impl->view setHidden:NO]; | |||||
} | } | ||||
} | } | ||||
@@ -517,21 +851,21 @@ puglHideWindow(PuglView* view) | |||||
if (impl->window) { | if (impl->window) { | ||||
[impl->window setIsVisible:NO]; | [impl->window setIsVisible:NO]; | ||||
} else { | } else { | ||||
[impl->glview setHidden:YES]; | |||||
[impl->view setHidden:YES]; | |||||
} | } | ||||
} | } | ||||
void | void | ||||
puglDestroy(PuglView* view) | puglDestroy(PuglView* view) | ||||
{ | { | ||||
view->impl->glview->puglview = NULL; | |||||
[view->impl->view setPuglview:NULL]; | |||||
if (view->impl->window) { | if (view->impl->window) { | ||||
[view->impl->window close]; | [view->impl->window close]; | ||||
[view->impl->glview release]; | |||||
[view->impl->view release]; | |||||
[view->impl->window release]; | [view->impl->window release]; | ||||
} else { | } else { | ||||
[view->impl->glview release]; | |||||
[view->impl->view release]; | |||||
} | } | ||||
free(view->impl); | free(view->impl); | ||||
@@ -551,13 +885,27 @@ void | |||||
puglPostRedisplay(PuglView* view) | puglPostRedisplay(PuglView* view) | ||||
{ | { | ||||
view->redisplay = true; | view->redisplay = true; | ||||
[view->impl->glview setNeedsDisplay:YES]; | |||||
[view->impl->view setNeedsDisplay:YES]; | |||||
} | } | ||||
PuglNativeWindow | PuglNativeWindow | ||||
puglGetNativeWindow(PuglView* view) | puglGetNativeWindow(PuglView* view) | ||||
{ | { | ||||
return (PuglNativeWindow)view->impl->glview; | |||||
return (PuglNativeWindow)view->impl->view; | |||||
} | |||||
void* | |||||
puglGetContext(PuglView* view) | |||||
{ | |||||
#ifdef PUGL_HAVE_CAIRO | |||||
if (view->ctx_type == PUGL_CAIRO) { | |||||
return [view->impl->cairoview cairoContext]; | |||||
} | |||||
#endif | |||||
return NULL; | |||||
// may be unused | |||||
(void)view; | |||||
} | } | ||||
int | int | ||||
@@ -21,7 +21,13 @@ | |||||
#include <winsock2.h> | #include <winsock2.h> | ||||
#include <windows.h> | #include <windows.h> | ||||
#include <windowsx.h> | #include <windowsx.h> | ||||
#ifdef PUGL_HAVE_GL | |||||
#include <GL/gl.h> | #include <GL/gl.h> | ||||
#endif | |||||
#ifdef PUGL_HAVE_CAIRO | |||||
#include <cairo/cairo.h> | |||||
#include <cairo/cairo-win32.h> | |||||
#endif | |||||
#include <ctime> | #include <ctime> | ||||
#include <cstdio> | #include <cstdio> | ||||
@@ -48,8 +54,13 @@ HINSTANCE hInstance = NULL; | |||||
struct PuglInternalsImpl { | struct PuglInternalsImpl { | ||||
HWND hwnd; | HWND hwnd; | ||||
#ifdef PUGL_HAVE_GL | |||||
HDC hdc; | HDC hdc; | ||||
HGLRC hglrc; | HGLRC hglrc; | ||||
#endif | |||||
#ifdef PUGL_HAVE_CAIRO | |||||
cairo_t* cr; | |||||
#endif | |||||
WNDCLASS wc; | WNDCLASS wc; | ||||
}; | }; | ||||
@@ -76,17 +87,25 @@ puglInitInternals() | |||||
void | void | ||||
puglEnterContext(PuglView* view) | puglEnterContext(PuglView* view) | ||||
{ | { | ||||
wglMakeCurrent(view->impl->hdc, view->impl->hglrc); | |||||
#ifdef PUGL_HAVE_GL | |||||
if (view->ctx_type == PUGL_GL) { | |||||
wglMakeCurrent(view->impl->hdc, view->impl->hglrc); | |||||
} | |||||
#endif | |||||
} | } | ||||
void | void | ||||
puglLeaveContext(PuglView* view, bool flush) | puglLeaveContext(PuglView* view, bool flush) | ||||
{ | { | ||||
if (flush) { | |||||
glFlush(); | |||||
SwapBuffers(view->impl->hdc); | |||||
#ifdef PUGL_HAVE_GL | |||||
if (view->ctx_type == PUGL_GL) { | |||||
if (flush) { | |||||
glFlush(); | |||||
SwapBuffers(view->impl->hdc); | |||||
} | |||||
wglMakeCurrent(NULL, NULL); | |||||
} | } | ||||
wglMakeCurrent(NULL, NULL); | |||||
#endif | |||||
} | } | ||||
int | int | ||||
@@ -124,7 +143,6 @@ puglCreateWindow(PuglView* view, const char* title) | |||||
if (!RegisterClass(&impl->wc)) { | if (!RegisterClass(&impl->wc)) { | ||||
free((void*)impl->wc.lpszClassName); | free((void*)impl->wc.lpszClassName); | ||||
free(impl); | free(impl); | ||||
free(view); | |||||
return 1; | return 1; | ||||
} | } | ||||
@@ -155,37 +173,39 @@ puglCreateWindow(PuglView* view, const char* title) | |||||
UnregisterClass(impl->wc.lpszClassName, NULL); | UnregisterClass(impl->wc.lpszClassName, NULL); | ||||
free((void*)impl->wc.lpszClassName); | free((void*)impl->wc.lpszClassName); | ||||
free(impl); | free(impl); | ||||
free(view); | |||||
return 1; | return 1; | ||||
} | } | ||||
SetWindowLongPtr(impl->hwnd, GWLP_USERDATA, (LONG_PTR)view); | SetWindowLongPtr(impl->hwnd, GWLP_USERDATA, (LONG_PTR)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); | |||||
if (!impl->hglrc) { | |||||
ReleaseDC (impl->hwnd, impl->hdc); | |||||
DestroyWindow (impl->hwnd); | |||||
UnregisterClass (impl->wc.lpszClassName, NULL); | |||||
free((void*)impl->wc.lpszClassName); | |||||
free(impl); | |||||
free(view); | |||||
return 1; | |||||
#ifdef PUGL_HAVE_GL | |||||
if (view->ctx_type == PUGL_GL) { | |||||
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); | |||||
if (!impl->hglrc) { | |||||
ReleaseDC (impl->hwnd, impl->hdc); | |||||
DestroyWindow (impl->hwnd); | |||||
UnregisterClass (impl->wc.lpszClassName, NULL); | |||||
free((void*)impl->wc.lpszClassName); | |||||
free(impl); | |||||
return 1; | |||||
} | |||||
} | } | ||||
#endif | |||||
return PUGL_SUCCESS; | return PUGL_SUCCESS; | ||||
} | } | ||||
@@ -205,13 +225,23 @@ puglHideWindow(PuglView* view) | |||||
void | void | ||||
puglDestroy(PuglView* view) | puglDestroy(PuglView* view) | ||||
{ | { | ||||
wglMakeCurrent(NULL, NULL); | |||||
wglDeleteContext(view->impl->hglrc); | |||||
ReleaseDC(view->impl->hwnd, view->impl->hdc); | |||||
DestroyWindow(view->impl->hwnd); | |||||
UnregisterClass(view->impl->wc.lpszClassName, NULL); | |||||
free((void*)view->impl->wc.lpszClassName); | |||||
free(view->impl); | |||||
if (!view) { | |||||
return; | |||||
} | |||||
PuglInternals* const impl = view->impl; | |||||
#ifdef PUGL_HAVE_GL | |||||
if (view->ctx_type == PUGL_GL) { | |||||
wglMakeCurrent(NULL, NULL); | |||||
wglDeleteContext(impl->hglrc); | |||||
} | |||||
ReleaseDC(impl->hwnd, impl->hdc); | |||||
#endif | |||||
DestroyWindow(impl->hwnd); | |||||
UnregisterClass(impl->wc.lpszClassName, NULL); | |||||
free((void*)impl->wc.lpszClassName); | |||||
free(impl); | |||||
free(view); | free(view); | ||||
} | } | ||||
@@ -329,9 +359,32 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) | |||||
mmi->ptMinTrackSize.y = view->min_height; | mmi->ptMinTrackSize.y = view->min_height; | ||||
break; | break; | ||||
case WM_PAINT: | case WM_PAINT: | ||||
BeginPaint(view->impl->hwnd, &ps); | |||||
puglDisplay(view); | |||||
EndPaint(view->impl->hwnd, &ps); | |||||
#ifdef PUGL_HAVE_GL | |||||
if (view->ctx_type == PUGL_GL) { | |||||
BeginPaint(view->impl->hwnd, &ps); | |||||
puglDisplay(view); | |||||
EndPaint(view->impl->hwnd, &ps); | |||||
} | |||||
#endif | |||||
#ifdef PUGL_HAVE_CAIRO | |||||
if (view->ctx_type == PUGL_CAIRO) { | |||||
HDC hdc = BeginPaint(view->impl->hwnd, &ps); | |||||
if (hdc == NULL) | |||||
break; | |||||
cairo_surface_t *surface = cairo_win32_surface_create(hdc); | |||||
if (surface) { | |||||
cairo_t *cr = cairo_create(surface); | |||||
if (cr) { | |||||
view->impl->cr = cr; | |||||
puglDisplay(view); | |||||
view->impl->cr = NULL; | |||||
cairo_destroy(cr); | |||||
} | |||||
cairo_surface_destroy(surface); | |||||
} | |||||
EndPaint(view->impl->hwnd, &ps); | |||||
} | |||||
#endif | |||||
break; | break; | ||||
case WM_MOUSEMOVE: | case WM_MOUSEMOVE: | ||||
if (view->motionFunc) { | if (view->motionFunc) { | ||||
@@ -469,6 +522,20 @@ puglGetNativeWindow(PuglView* view) | |||||
return (PuglNativeWindow)view->impl->hwnd; | return (PuglNativeWindow)view->impl->hwnd; | ||||
} | } | ||||
void* | |||||
puglGetContext(PuglView* view) | |||||
{ | |||||
#ifdef PUGL_HAVE_CAIRO | |||||
if (view->ctx_type == PUGL_CAIRO) { | |||||
return view->impl->cr; | |||||
} | |||||
#endif | |||||
return NULL; | |||||
// may be unused | |||||
(void)view; | |||||
} | |||||
int | int | ||||
puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect) | puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect) | ||||
{ | { | ||||
@@ -24,8 +24,14 @@ | |||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#ifdef PUGL_HAVE_GL | |||||
#include <GL/gl.h> | #include <GL/gl.h> | ||||
#include <GL/glx.h> | #include <GL/glx.h> | ||||
#endif | |||||
#ifdef PUGL_HAVE_CAIRO | |||||
#include <cairo/cairo.h> | |||||
#include <cairo/cairo-xlib.h> | |||||
#endif | |||||
#include <X11/Xatom.h> | #include <X11/Xatom.h> | ||||
#include <X11/Xlib.h> | #include <X11/Xlib.h> | ||||
#include <X11/Xutil.h> | #include <X11/Xutil.h> | ||||
@@ -53,10 +59,17 @@ struct PuglInternalsImpl { | |||||
Display* display; | Display* display; | ||||
int screen; | int screen; | ||||
Window win; | Window win; | ||||
#ifdef PUGL_HAVE_CAIRO | |||||
cairo_t* cr; | |||||
cairo_surface_t* surface; | |||||
#endif | |||||
#ifdef PUGL_HAVE_GL | |||||
GLXContext ctx; | GLXContext ctx; | ||||
Bool doubleBuffered; | Bool doubleBuffered; | ||||
#endif | |||||
}; | }; | ||||
#ifdef PUGL_HAVE_GL | |||||
/** | /** | ||||
Attributes for single-buffered RGBA with at least | Attributes for single-buffered RGBA with at least | ||||
4 bits per color and a 16 bit depth buffer. | 4 bits per color and a 16 bit depth buffer. | ||||
@@ -102,6 +115,7 @@ static int attrListDblMS[] = { | |||||
GLX_SAMPLES, 4, | GLX_SAMPLES, 4, | ||||
None | None | ||||
}; | }; | ||||
#endif | |||||
PuglInternals* | PuglInternals* | ||||
puglInitInternals(void) | puglInitInternals(void) | ||||
@@ -112,25 +126,33 @@ puglInitInternals(void) | |||||
void | void | ||||
puglEnterContext(PuglView* view) | puglEnterContext(PuglView* view) | ||||
{ | { | ||||
glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx); | |||||
#ifdef PUGL_HAVE_GL | |||||
if (view->ctx_type == PUGL_GL) { | |||||
glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx); | |||||
} | |||||
#endif | |||||
} | } | ||||
void | void | ||||
puglLeaveContext(PuglView* view, bool flush) | puglLeaveContext(PuglView* view, bool flush) | ||||
{ | { | ||||
if (flush) { | |||||
glFlush(); | |||||
if (view->impl->doubleBuffered) { | |||||
glXSwapBuffers(view->impl->display, view->impl->win); | |||||
#ifdef PUGL_HAVE_GL | |||||
if (view->ctx_type == PUGL_GL) { | |||||
if (flush) { | |||||
glFlush(); | |||||
if (view->impl->doubleBuffered) { | |||||
glXSwapBuffers(view->impl->display, view->impl->win); | |||||
} | |||||
} | } | ||||
glXMakeCurrent(view->impl->display, None, NULL); | |||||
} | } | ||||
glXMakeCurrent(view->impl->display, None, NULL); | |||||
#endif | |||||
} | } | ||||
int | int | ||||
puglCreateWindow(PuglView* view, const char* title) | puglCreateWindow(PuglView* view, const char* title) | ||||
{ | { | ||||
PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); | |||||
PuglInternals* impl = view->impl; | |||||
if (!impl) { | if (!impl) { | ||||
return 1; | return 1; | ||||
} | } | ||||
@@ -142,21 +164,35 @@ puglCreateWindow(PuglView* view, const char* title) | |||||
return 1; | return 1; | ||||
} | } | ||||
impl->screen = DefaultScreen(impl->display); | impl->screen = DefaultScreen(impl->display); | ||||
impl->doubleBuffered = True; | |||||
XVisualInfo* vi = glXChooseVisual(impl->display, impl->screen, attrListDblMS); | |||||
XVisualInfo* vi = NULL; | |||||
if (!vi) { | |||||
vi = glXChooseVisual(impl->display, impl->screen, attrListDbl); | |||||
#ifdef PUGL_HAVE_GL | |||||
if (view->ctx_type == PUGL_GL) { | |||||
impl->doubleBuffered = True; | |||||
vi = glXChooseVisual(impl->display, impl->screen, attrListDblMS); | |||||
if (!vi) { | |||||
vi = glXChooseVisual(impl->display, impl->screen, attrListDbl); | |||||
#ifdef PUGL_VERBOSE | #ifdef PUGL_VERBOSE | ||||
printf("puGL: multisampling (antialiasing) is not available\n"); | |||||
printf("puGL: multisampling (antialiasing) is not available\n"); | |||||
#endif | #endif | ||||
} | |||||
} | |||||
if (!vi) { | |||||
vi = glXChooseVisual(impl->display, impl->screen, attrListSgl); | |||||
impl->doubleBuffered = False; | |||||
if (!vi) { | |||||
vi = glXChooseVisual(impl->display, impl->screen, attrListSgl); | |||||
impl->doubleBuffered = False; | |||||
} | |||||
} | } | ||||
#endif | |||||
#ifdef PUGL_HAVE_CAIRO | |||||
if (view->ctx_type == PUGL_CAIRO) { | |||||
XVisualInfo pat; | |||||
int n; | |||||
pat.screen = impl->screen; | |||||
vi = XGetVisualInfo(impl->display, VisualScreenMask, &pat, &n); | |||||
} | |||||
#endif | |||||
if (!vi) { | if (!vi) { | ||||
XCloseDisplay(impl->display); | XCloseDisplay(impl->display); | ||||
@@ -165,18 +201,25 @@ puglCreateWindow(PuglView* view, const char* title) | |||||
} | } | ||||
#ifdef PUGL_VERBOSE | #ifdef PUGL_VERBOSE | ||||
#ifdef PUGL_HAVE_GL | |||||
int glxMajor, glxMinor; | int glxMajor, glxMinor; | ||||
glXQueryVersion(impl->display, &glxMajor, &glxMinor); | glXQueryVersion(impl->display, &glxMajor, &glxMinor); | ||||
printf("puGL: GLX-Version : %d.%d\n", glxMajor, glxMinor); | printf("puGL: GLX-Version : %d.%d\n", glxMajor, glxMinor); | ||||
#endif | #endif | ||||
#endif | |||||
impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE); | |||||
#ifdef PUGL_HAVE_GL | |||||
if (view->ctx_type == PUGL_GL) { | |||||
impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE); | |||||
if (!impl->ctx) { | |||||
XCloseDisplay(impl->display); | |||||
free(impl); | |||||
return 1; | |||||
if (!impl->ctx) { | |||||
XFree(vi); | |||||
XCloseDisplay(impl->display); | |||||
free(impl); | |||||
return 1; | |||||
} | |||||
} | } | ||||
#endif | |||||
Window xParent = view->parent | Window xParent = view->parent | ||||
? (Window)view->parent | ? (Window)view->parent | ||||
@@ -201,11 +244,40 @@ puglCreateWindow(PuglView* view, const char* title) | |||||
CWBorderPixel | CWColormap | CWEventMask, &attr); | CWBorderPixel | CWColormap | CWEventMask, &attr); | ||||
if (!impl->win) { | if (!impl->win) { | ||||
#ifdef PUGL_HAVE_GL | |||||
if (view->ctx_type == PUGL_GL) { | |||||
glXDestroyContext(impl->display, impl->ctx); | |||||
} | |||||
#endif | |||||
XFree(vi); | |||||
XCloseDisplay(impl->display); | XCloseDisplay(impl->display); | ||||
free(impl); | free(impl); | ||||
return 1; | return 1; | ||||
} | } | ||||
#ifdef PUGL_HAVE_CAIRO | |||||
if (view->ctx_type == PUGL_CAIRO) { | |||||
impl->surface = cairo_xlib_surface_create( | |||||
impl->display, impl->win, vi->visual, view->width, view->height); | |||||
if (impl->surface == NULL || cairo_surface_status(impl->surface) != CAIRO_STATUS_SUCCESS) { | |||||
printf("puGL: failed to create cairo surface\n"); | |||||
} | |||||
else { | |||||
impl->cr = cairo_create(impl->surface); | |||||
} | |||||
if (impl->cr == NULL || cairo_status(impl->cr) != CAIRO_STATUS_SUCCESS) { | |||||
cairo_destroy(impl->cr); | |||||
cairo_surface_destroy(impl->surface); | |||||
XDestroyWindow(impl->display, impl->win); | |||||
XFree(vi); | |||||
XCloseDisplay(impl->display); | |||||
free(impl); | |||||
printf("puGL: failed to create cairo context\n"); | |||||
return 1; | |||||
} | |||||
} | |||||
#endif | |||||
if (view->width > 1 || view->height > 1) { | if (view->width > 1 || view->height > 1) { | ||||
puglUpdateGeometryConstraints(view, view->min_width, view->min_height, view->min_width != view->width); | puglUpdateGeometryConstraints(view, view->min_width, view->min_height, view->min_width != view->width); | ||||
XResizeWindow(view->impl->display, view->impl->win, view->width, view->height); | XResizeWindow(view->impl->display, view->impl->win, view->width, view->height); | ||||
@@ -227,11 +299,13 @@ puglCreateWindow(PuglView* view, const char* title) | |||||
} | } | ||||
#ifdef PUGL_VERBOSE | #ifdef PUGL_VERBOSE | ||||
#ifdef PUGL_HAVE_GL | |||||
if (glXIsDirect(impl->display, impl->ctx)) { | if (glXIsDirect(impl->display, impl->ctx)) { | ||||
printf("puGL: DRI enabled (to disable, set LIBGL_ALWAYS_INDIRECT=1\n"); | printf("puGL: DRI enabled (to disable, set LIBGL_ALWAYS_INDIRECT=1\n"); | ||||
} else { | } else { | ||||
printf("puGL: No DRI available\n"); | printf("puGL: No DRI available\n"); | ||||
} | } | ||||
#endif | |||||
#endif | #endif | ||||
XFree(vi); | XFree(vi); | ||||
@@ -244,14 +318,27 @@ puglDestroy(PuglView* view) | |||||
if (!view) { | if (!view) { | ||||
return; | return; | ||||
} | } | ||||
PuglInternals* const impl = view->impl; | |||||
#ifndef DGL_FILE_BROWSER_DISABLED | #ifndef DGL_FILE_BROWSER_DISABLED | ||||
x_fib_close(view->impl->display); | |||||
x_fib_close(impl->display); | |||||
#endif | #endif | ||||
glXDestroyContext(view->impl->display, view->impl->ctx); | |||||
XDestroyWindow(view->impl->display, view->impl->win); | |||||
XCloseDisplay(view->impl->display); | |||||
free(view->impl); | |||||
#ifdef PUGL_HAVE_GL | |||||
if (view->ctx_type == PUGL_GL) { | |||||
glXDestroyContext(impl->display, impl->ctx); | |||||
} | |||||
#endif | |||||
#ifdef PUGL_HAVE_CAIRO | |||||
if (view->ctx_type == PUGL_CAIRO) { | |||||
cairo_destroy(impl->cr); | |||||
cairo_surface_destroy(impl->surface); | |||||
} | |||||
#endif | |||||
XDestroyWindow(impl->display, impl->win); | |||||
XCloseDisplay(impl->display); | |||||
free(impl); | |||||
free(view); | free(view); | ||||
} | } | ||||
@@ -554,6 +641,14 @@ puglProcessEvents(PuglView* view) | |||||
} | } | ||||
if (conf_width != -1) { | if (conf_width != -1) { | ||||
#ifdef PUGL_HAVE_CAIRO | |||||
if (view->ctx_type == PUGL_CAIRO) { | |||||
// Resize surfaces/contexts before dispatching | |||||
view->redisplay = true; | |||||
cairo_xlib_surface_set_size(view->impl->surface, | |||||
conf_width, conf_height); | |||||
} | |||||
#endif | |||||
puglReshape(view, conf_width, conf_height); | puglReshape(view, conf_width, conf_height); | ||||
} | } | ||||
@@ -586,6 +681,20 @@ puglGetNativeWindow(PuglView* view) | |||||
return view->impl->win; | return view->impl->win; | ||||
} | } | ||||
void* | |||||
puglGetContext(PuglView* view) | |||||
{ | |||||
#ifdef PUGL_HAVE_CAIRO | |||||
if (view->ctx_type == PUGL_CAIRO) { | |||||
return view->impl->cr; | |||||
} | |||||
#endif | |||||
return NULL; | |||||
// may be unused | |||||
(void)view; | |||||
} | |||||
int | int | ||||
puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect) | puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect) | ||||
{ | { | ||||
@@ -93,7 +93,7 @@ | |||||
// Define DISTRHO_PLUGIN_HAS_EMBED_UI if needed | // Define DISTRHO_PLUGIN_HAS_EMBED_UI if needed | ||||
#ifndef DISTRHO_PLUGIN_HAS_EMBED_UI | #ifndef DISTRHO_PLUGIN_HAS_EMBED_UI | ||||
# ifdef HAVE_DGL | |||||
# if defined(HAVE_DGL) || defined(HAVE_DCAIRO) | |||||
# define DISTRHO_PLUGIN_HAS_EMBED_UI 1 | # define DISTRHO_PLUGIN_HAS_EMBED_UI 1 | ||||
# else | # else | ||||
# define DISTRHO_PLUGIN_HAS_EMBED_UI 0 | # define DISTRHO_PLUGIN_HAS_EMBED_UI 0 | ||||
@@ -135,7 +135,7 @@ | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// Disable UI if DGL or External UI is not available | // Disable UI if DGL or External UI is not available | ||||
#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI && ! defined(HAVE_DGL) | |||||
#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI && ! defined(HAVE_DGL) && ! defined(HAVE_DCAIRO) | |||||
# undef DISTRHO_PLUGIN_HAS_UI | # undef DISTRHO_PLUGIN_HAS_UI | ||||
# define DISTRHO_PLUGIN_HAS_UI 0 | # define DISTRHO_PLUGIN_HAS_UI 0 | ||||
#endif | #endif | ||||
@@ -152,6 +152,7 @@ void UI::uiFileBrowserSelected(const char*) | |||||
void UI::uiReshape(uint width, uint height) | void UI::uiReshape(uint width, uint height) | ||||
{ | { | ||||
#if defined(HAVE_DGL) | |||||
glEnable(GL_BLEND); | glEnable(GL_BLEND); | ||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||||
glMatrixMode(GL_PROJECTION); | glMatrixMode(GL_PROJECTION); | ||||
@@ -160,6 +161,7 @@ void UI::uiReshape(uint width, uint height) | |||||
glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height)); | glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height)); | ||||
glMatrixMode(GL_MODELVIEW); | glMatrixMode(GL_MODELVIEW); | ||||
glLoadIdentity(); | glLoadIdentity(); | ||||
#endif | |||||
} | } | ||||
/* ------------------------------------------------------------------------------------------------------------ | /* ------------------------------------------------------------------------------------------------------------ | ||||