summaryrefslogtreecommitdiff
path: root/dgl
diff options
context:
space:
mode:
authorJP Cimalando <jpcima@users.noreply.github.com>2018-11-01 13:55:41 +0100
committerFilipe Coelho <falktx@falktx.com>2019-01-06 19:10:11 +0100
commitd80c799b8cba2765c78ac6cee867f5c4fce869ac (patch)
treeaa9201ce5504d1be5fd10aeb4833f2c934f70753 /dgl
parentaeea76d93f9ed2397c9c86e9db72afedfa779f29 (diff)
software rendering with Cairo
Diffstat (limited to 'dgl')
-rw-r--r--dgl/Base.hpp15
-rw-r--r--dgl/Color.hpp4
-rw-r--r--dgl/Geometry.hpp14
-rw-r--r--dgl/Widget.hpp4
-rw-r--r--dgl/Window.hpp4
-rw-r--r--dgl/src/Color.cpp33
-rw-r--r--dgl/src/Geometry.cpp14
-rw-r--r--dgl/src/Widget.cpp7
-rw-r--r--dgl/src/WidgetPrivateData.hpp4
-rw-r--r--dgl/src/Window.cpp34
-rw-r--r--dgl/src/pugl/pugl.h22
-rw-r--r--dgl/src/pugl/pugl_internal.h9
-rw-r--r--dgl/src/pugl/pugl_osx.m424
-rw-r--r--dgl/src/pugl/pugl_win.cpp149
-rw-r--r--dgl/src/pugl/pugl_x11.c161
15 files changed, 791 insertions, 107 deletions
diff --git a/dgl/Base.hpp b/dgl/Base.hpp
index 30d10e0d..7b7864fe 100644
--- a/dgl/Base.hpp
+++ b/dgl/Base.hpp
@@ -73,6 +73,8 @@
// -----------------------------------------------------------------------
// OpenGL includes
+#if defined(HAVE_DGL)
+
#ifdef DISTRHO_OS_MAC
# include <OpenGL/gl.h>
#else
@@ -83,9 +85,20 @@
# include <GL/glext.h>
#endif
+#endif
+
+// -----------------------------------------------------------------------
+// Cairo includes
+
+#if defined(HAVE_DCAIRO)
+# include <cairo/cairo.h>
+#endif
+
// -----------------------------------------------------------------------
// Missing OpenGL defines
+#if defined(HAVE_DGL)
+
#if defined(GL_BGR_EXT) && ! defined(GL_BGR)
# define GL_BGR GL_BGR_EXT
#endif
@@ -98,6 +111,8 @@
# define GL_CLAMP_TO_BORDER 0x812D
#endif
+#endif
+
#ifdef DISTRHO_OS_WINDOWS
// -----------------------------------------------------------------------
// Fix OpenGL includes for Windows, based on glfw code
diff --git a/dgl/Color.hpp b/dgl/Color.hpp
index 2fc8c64c..51d8afc8 100644
--- a/dgl/Color.hpp
+++ b/dgl/Color.hpp
@@ -19,7 +19,9 @@
#include "Base.hpp"
+#if !defined(HAVE_DCAIRO)
struct NVGcolor;
+#endif
START_NAMESPACE_DGL
@@ -95,12 +97,14 @@ struct Color {
*/
void fixBounds() noexcept;
+#if !defined(HAVE_DCAIRO)
/**
@internal
Needed for NanoVG compatibility.
*/
Color(const NVGcolor&) noexcept;
operator NVGcolor() const noexcept;
+#endif
};
// -----------------------------------------------------------------------
diff --git a/dgl/Geometry.hpp b/dgl/Geometry.hpp
index 3dbf7064..b82230f1 100644
--- a/dgl/Geometry.hpp
+++ b/dgl/Geometry.hpp
@@ -346,10 +346,12 @@ public:
*/
void moveBy(const Point<T>& pos) noexcept;
+#if defined(HAVE_DGL)
/**
Draw this line using the current OpenGL state.
*/
void draw();
+#endif
/**
Return true if line is null (start and end pos are equal).
@@ -460,6 +462,7 @@ public:
*/
void setNumSegments(const uint num);
+#if defined(HAVE_DGL)
/**
Draw this circle using the current OpenGL state.
*/
@@ -469,6 +472,7 @@ public:
Draw lines (outline of this circle) using the current OpenGL state.
*/
void drawOutline();
+#endif
Circle<T>& operator=(const Circle<T>& cir) noexcept;
bool operator==(const Circle<T>& cir) const noexcept;
@@ -482,7 +486,9 @@ private:
// cached values
float fTheta, fCos, fSin;
+#if defined(HAVE_DGL)
void _draw(const bool outline);
+#endif
};
// -----------------------------------------------------------------------
@@ -516,6 +522,7 @@ public:
*/
Triangle(const Triangle<T>& tri) noexcept;
+#if defined(HAVE_DGL)
/**
Draw this triangle using the current OpenGL state.
*/
@@ -525,6 +532,7 @@ public:
Draw lines (outline of this triangle) using the current OpenGL state.
*/
void drawOutline();
+#endif
/**
Return true if triangle is null (all its points are equal).
@@ -556,7 +564,9 @@ public:
private:
Point<T> fPos1, fPos2, fPos3;
+#if defined(HAVE_DGL)
void _draw(const bool outline);
+#endif
};
// -----------------------------------------------------------------------
@@ -720,6 +730,7 @@ public:
*/
bool containsY(const T& y) const noexcept;
+#if defined(HAVE_DGL)
/**
Draw this rectangle using the current OpenGL state.
*/
@@ -729,6 +740,7 @@ public:
Draw lines (outline of this rectangle) using the current OpenGL state.
*/
void drawOutline();
+#endif
Rectangle<T>& operator=(const Rectangle<T>& rect) noexcept;
Rectangle<T>& operator*=(double m) noexcept;
@@ -740,7 +752,9 @@ private:
Point<T> fPos;
Size<T> fSize;
+#if defined(HAVE_DGL)
void _draw(const bool outline);
+#endif
};
// -----------------------------------------------------------------------
diff --git a/dgl/Widget.hpp b/dgl/Widget.hpp
index 73d2d6e9..bebe5ed7 100644
--- a/dgl/Widget.hpp
+++ b/dgl/Widget.hpp
@@ -312,6 +312,10 @@ public:
*/
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.
*/
diff --git a/dgl/Window.hpp b/dgl/Window.hpp
index dbe3abfd..2a9d9517 100644
--- a/dgl/Window.hpp
+++ b/dgl/Window.hpp
@@ -119,6 +119,10 @@ public:
Application& getApp() const noexcept;
intptr_t getWindowId() const noexcept;
+#if defined(HAVE_DCAIRO)
+ cairo_t* getGraphics() const noexcept;
+#endif
+
void addIdleCallback(IdleCallback* const callback);
void removeIdleCallback(IdleCallback* const callback);
diff --git a/dgl/src/Color.cpp b/dgl/src/Color.cpp
index 2ea9819f..4965c902 100644
--- a/dgl/src/Color.cpp
+++ b/dgl/src/Color.cpp
@@ -16,7 +16,9 @@
#include "../Color.hpp"
+#if !defined(HAVE_DCAIRO)
#include "nanovg/nanovg.h"
+#endif
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)
{
+#if defined(HAVE_DGL)
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)
@@ -224,6 +255,7 @@ void Color::fixBounds() noexcept
// -----------------------------------------------------------------------
+#if !defined(HAVE_DCAIRO)
Color::Color(const NVGcolor& c) noexcept
: red(c.r), green(c.g), blue(c.b), alpha(c.a)
{
@@ -239,6 +271,7 @@ Color::operator NVGcolor() const noexcept
nc.a = alpha;
return nc;
}
+#endif
// -----------------------------------------------------------------------
diff --git a/dgl/src/Geometry.cpp b/dgl/src/Geometry.cpp
index 7ea3af34..78eebdf1 100644
--- a/dgl/src/Geometry.cpp
+++ b/dgl/src/Geometry.cpp
@@ -441,6 +441,7 @@ void Line<T>::moveBy(const Point<T>& pos) noexcept
fPosEnd.moveBy(pos);
}
+#if defined(HAVE_DGL)
template<typename T>
void Line<T>::draw()
{
@@ -455,6 +456,7 @@ void Line<T>::draw()
glEnd();
}
+#endif
template<typename T>
bool Line<T>::isNull() const noexcept
@@ -614,6 +616,7 @@ void Circle<T>::setNumSegments(const uint num)
fSin = std::sin(fTheta);
}
+#if defined(HAVE_DGL)
template<typename T>
void Circle<T>::draw()
{
@@ -625,6 +628,7 @@ void Circle<T>::drawOutline()
{
_draw(true);
}
+#endif
template<typename T>
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);
}
+#if defined(HAVE_DGL)
template<typename T>
void Circle<T>::_draw(const bool outline)
{
@@ -670,6 +675,7 @@ void Circle<T>::_draw(const bool outline)
glEnd();
}
+#endif
// -----------------------------------------------------------------------
// Triangle
@@ -698,6 +704,7 @@ Triangle<T>::Triangle(const Triangle<T>& tri) noexcept
fPos2(tri.fPos2),
fPos3(tri.fPos3) {}
+#if defined(HAVE_DGL)
template<typename T>
void Triangle<T>::draw()
{
@@ -709,6 +716,7 @@ void Triangle<T>::drawOutline()
{
_draw(true);
}
+#endif
template<typename T>
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);
}
+#if defined(HAVE_DGL)
template<typename T>
void Triangle<T>::_draw(const bool outline)
{
@@ -770,6 +779,7 @@ void Triangle<T>::_draw(const bool outline)
glEnd();
}
+#endif
// -----------------------------------------------------------------------
// Rectangle
@@ -952,6 +962,7 @@ bool Rectangle<T>::containsY(const T& y) const noexcept
return (y >= fPos.fY && y <= fPos.fY + fSize.fHeight);
}
+#if defined(HAVE_DGL)
template<typename T>
void Rectangle<T>::draw()
{
@@ -963,6 +974,7 @@ void Rectangle<T>::drawOutline()
{
_draw(true);
}
+#endif
template<typename T>
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);
}
+#if defined(HAVE_DGL)
template<typename T>
void Rectangle<T>::_draw(const bool outline)
{
@@ -1021,6 +1034,7 @@ void Rectangle<T>::_draw(const bool outline)
glEnd();
}
+#endif
// -----------------------------------------------------------------------
// Possible template data types
diff --git a/dgl/src/Widget.cpp b/dgl/src/Widget.cpp
index d200fb40..bf6fd3f8 100644
--- a/dgl/src/Widget.cpp
+++ b/dgl/src/Widget.cpp
@@ -189,6 +189,13 @@ Window& Widget::getParentWindow() const noexcept
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
{
return (x >= 0 && y >= 0 && static_cast<uint>(x) < pData->size.getWidth() && static_cast<uint>(y) < pData->size.getHeight());
diff --git a/dgl/src/WidgetPrivateData.hpp b/dgl/src/WidgetPrivateData.hpp
index 5dbe2ace..53f68f45 100644
--- a/dgl/src/WidgetPrivateData.hpp
+++ b/dgl/src/WidgetPrivateData.hpp
@@ -68,6 +68,7 @@ struct Widget::PrivateData {
if ((skipDisplay && ! renderingSubWidget) || size.isInvalid() || ! visible)
return;
+#if defined(HAVE_DGL)
bool needsDisableScissor = false;
// reset color
@@ -106,15 +107,18 @@ struct Widget::PrivateData {
glEnable(GL_SCISSOR_TEST);
needsDisableScissor = true;
}
+#endif
// display widget
self->onDisplay();
+#if defined(HAVE_DGL)
if (needsDisableScissor)
{
glDisable(GL_SCISSOR_TEST);
needsDisableScissor = false;
}
+#endif
displaySubWidgets(width, height, scaling);
}
diff --git a/dgl/src/Window.cpp b/dgl/src/Window.cpp
index ae46addb..18ea39f4 100644
--- a/dgl/src/Window.cpp
+++ b/dgl/src/Window.cpp
@@ -19,6 +19,16 @@
#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"
#if defined(__GNUC__) && (__GNUC__ >= 7)
@@ -203,6 +213,14 @@ struct Window::PrivateData {
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);
puglInitWindowSize(fView, static_cast<int>(fWidth), static_cast<int>(fHeight));
@@ -222,11 +240,12 @@ struct Window::PrivateData {
puglCreateWindow(fView, nullptr);
PuglInternals* impl = fView->impl;
+
#if defined(DISTRHO_OS_WINDOWS)
hwnd = impl->hwnd;
DISTRHO_SAFE_ASSERT(hwnd != 0);
#elif defined(DISTRHO_OS_MAC)
- mView = impl->glview;
+ mView = impl->view;
mWindow = impl->window;
DISTRHO_SAFE_ASSERT(mView != nullptr);
if (fUsingEmbed) {
@@ -1081,7 +1100,7 @@ struct Window::PrivateData {
HWND hwndParent;
#elif defined(DISTRHO_OS_MAC)
bool fNeedsIdle;
- PuglOpenGLView* mView;
+ NSView<PuglGenericView>* mView;
id mWindow;
id mParentWindow;
#else
@@ -1365,6 +1384,13 @@ intptr_t Window::getWindowId() const noexcept
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)
{
pData->addWidget(widget);
@@ -1400,8 +1426,10 @@ void Window::removeIdleCallback(IdleCallback* const callback)
void Window::onDisplayBefore()
{
+#if defined(HAVE_DGL)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
+#endif
}
void Window::onDisplayAfter()
@@ -1410,6 +1438,7 @@ void Window::onDisplayAfter()
void Window::onReshape(uint width, uint height)
{
+#if defined(HAVE_DGL)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
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));
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
+#endif
}
void Window::onClose()
diff --git a/dgl/src/pugl/pugl.h b/dgl/src/pugl/pugl.h
index 32a10a2b..a2ffa85d 100644
--- a/dgl/src/pugl/pugl.h
+++ b/dgl/src/pugl/pugl.h
@@ -274,6 +274,20 @@ PUGL_API void
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);
+
+/**
@}
*/
@@ -350,6 +364,14 @@ PUGL_API PuglHandle
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.
*/
PUGL_API uint32_t
diff --git a/dgl/src/pugl/pugl_internal.h b/dgl/src/pugl/pugl_internal.h
index fa52df40..b8d9ca93 100644
--- a/dgl/src/pugl/pugl_internal.h
+++ b/dgl/src/pugl/pugl_internal.h
@@ -41,6 +41,7 @@ struct PuglViewImpl {
PuglInternals* impl;
PuglNativeWindow parent;
+ PuglContextType ctx_type;
uintptr_t transient_parent;
int width;
@@ -141,6 +142,12 @@ puglCreate(PuglNativeWindow parent,
}
void
+puglInitContextType(PuglView* view, PuglContextType type)
+{
+ view->ctx_type = type;
+}
+
+void
puglSetHandle(PuglView* view, PuglHandle handle)
{
view->handle = handle;
@@ -239,6 +246,7 @@ puglLeaveContext(PuglView* view, bool flush);
static void
puglDefaultReshape(int width, int height)
{
+#ifdef PUGL_HAVE_GL
#ifdef ROBTK_HERE
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
@@ -257,4 +265,5 @@ puglDefaultReshape(int width, int height)
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
#endif
+#endif
}
diff --git a/dgl/src/pugl/pugl_osx.m b/dgl/src/pugl/pugl_osx.m
index 738103f3..1c00106d 100644
--- a/dgl/src/pugl/pugl_osx.m
+++ b/dgl/src/pugl/pugl_osx.m
@@ -21,6 +21,10 @@
#include <stdlib.h>
#import <Cocoa/Cocoa.h>
+#ifdef PUGL_HAVE_CAIRO
+#import <cairo.h>
+#import <cairo-quartz.h>
+#endif
#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
PuglView* puglview;
@@ -101,6 +138,9 @@ puglDisplay(PuglView* view)
bool doubleBuffered;
}
+- (PuglView *) puglView;
+- (void) setPuglview:(PuglView *)pv;
+
- (BOOL) acceptsFirstMouse:(NSEvent*)e;
- (BOOL) acceptsFirstResponder;
- (BOOL) isFlipped;
@@ -130,6 +170,13 @@ puglDisplay(PuglView* view)
@end
@implementation PuglOpenGLView
+- (PuglView *) puglView {
+ return self->puglview;
+}
+
+- (void) setPuglview:(PuglView *)pv {
+ self->puglview = pv;
+}
- (BOOL) acceptsFirstMouse:(NSEvent*)e
{
@@ -277,32 +324,296 @@ puglDisplay(PuglView* view)
[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
{
if (puglview->motionFunc) {
@@ -410,11 +721,19 @@ getFixedAppKitButton(NSInteger button)
puglview->mods = mods;
}
}
-
@end
+#endif
struct PuglInternalsImpl {
- PuglOpenGLView* glview;
+ union {
+ NSView<PuglGenericView>* view;
+#ifdef PUGL_HAVE_GL
+ PuglOpenGLView* glview;
+#endif
+#ifdef PUGL_HAVE_CAIRO
+ PuglCairoView* cairoview;
+#endif
+ };
id window;
};
@@ -427,13 +746,18 @@ puglInitInternals()
void
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
puglLeaveContext(PuglView* view, bool flush)
{
- if (flush) {
+#ifdef PUGL_HAVE_GL
+ if (view->ctx_type == PUGL_GL && flush) {
if (view->impl->glview->doubleBuffered) {
[[view->impl->glview openGLContext] flushBuffer];
} else {
@@ -441,6 +765,7 @@ puglLeaveContext(PuglView* view, bool flush)
}
//[NSOpenGLContext clearCurrentContext];
}
+#endif
}
int
@@ -451,22 +776,31 @@ puglCreateWindow(PuglView* view, const char* title)
[NSAutoreleasePool new];
[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;
}
-
- impl->glview->puglview = view;
+
+ [impl->view setPuglview:view];
if (view->user_resizable) {
- [impl->glview setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
+ [impl->view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
}
if (view->parent) {
- [impl->glview retain];
+ [impl->view retain];
NSView* pview = (NSView*)view->parent;
- [pview addSubview:impl->glview];
+ [pview addSubview:impl->view];
return 0;
}
@@ -482,8 +816,8 @@ puglCreateWindow(PuglView* view, const char* title)
}
[window setPuglview:view];
- [window setContentView:impl->glview];
- [window makeFirstResponder:impl->glview];
+ [window setContentView:impl->view];
+ [window makeFirstResponder:impl->view];
[window makeKeyAndOrderFront:window];
// wait for first puglShowWindow
@@ -505,7 +839,7 @@ puglShowWindow(PuglView* view)
if (impl->window) {
[impl->window setIsVisible:YES];
} else {
- [view->impl->glview setHidden:NO];
+ [view->impl->view setHidden:NO];
}
}
@@ -517,21 +851,21 @@ puglHideWindow(PuglView* view)
if (impl->window) {
[impl->window setIsVisible:NO];
} else {
- [impl->glview setHidden:YES];
+ [impl->view setHidden:YES];
}
}
void
puglDestroy(PuglView* view)
{
- view->impl->glview->puglview = NULL;
+ [view->impl->view setPuglview:NULL];
if (view->impl->window) {
[view->impl->window close];
- [view->impl->glview release];
+ [view->impl->view release];
[view->impl->window release];
} else {
- [view->impl->glview release];
+ [view->impl->view release];
}
free(view->impl);
@@ -551,13 +885,27 @@ void
puglPostRedisplay(PuglView* view)
{
view->redisplay = true;
- [view->impl->glview setNeedsDisplay:YES];
+ [view->impl->view setNeedsDisplay:YES];
}
PuglNativeWindow
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
diff --git a/dgl/src/pugl/pugl_win.cpp b/dgl/src/pugl/pugl_win.cpp
index 9990b8ef..e8b2612f 100644
--- a/dgl/src/pugl/pugl_win.cpp
+++ b/dgl/src/pugl/pugl_win.cpp
@@ -21,7 +21,13 @@
#include <winsock2.h>
#include <windows.h>
#include <windowsx.h>
+#ifdef PUGL_HAVE_GL
#include <GL/gl.h>
+#endif
+#ifdef PUGL_HAVE_CAIRO
+#include <cairo/cairo.h>
+#include <cairo/cairo-win32.h>
+#endif
#include <ctime>
#include <cstdio>
@@ -48,8 +54,13 @@ HINSTANCE hInstance = NULL;
struct PuglInternalsImpl {
HWND hwnd;
+#ifdef PUGL_HAVE_GL
HDC hdc;
HGLRC hglrc;
+#endif
+#ifdef PUGL_HAVE_CAIRO
+ cairo_t* cr;
+#endif
WNDCLASS wc;
};
@@ -76,17 +87,25 @@ puglInitInternals()
void
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
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
@@ -124,7 +143,6 @@ puglCreateWindow(PuglView* view, const char* title)
if (!RegisterClass(&impl->wc)) {
free((void*)impl->wc.lpszClassName);
free(impl);
- free(view);
return 1;
}
@@ -155,37 +173,39 @@ puglCreateWindow(PuglView* view, const char* title)
UnregisterClass(impl->wc.lpszClassName, NULL);
free((void*)impl->wc.lpszClassName);
free(impl);
- free(view);
return 1;
}
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;
}
@@ -205,13 +225,23 @@ puglHideWindow(PuglView* view)
void
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);
}
@@ -329,9 +359,32 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
mmi->ptMinTrackSize.y = view->min_height;
break;
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;
case WM_MOUSEMOVE:
if (view->motionFunc) {
@@ -469,6 +522,20 @@ puglGetNativeWindow(PuglView* view)
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
puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect)
{
diff --git a/dgl/src/pugl/pugl_x11.c b/dgl/src/pugl/pugl_x11.c
index ea70db1d..20f86b73 100644
--- a/dgl/src/pugl/pugl_x11.c
+++ b/dgl/src/pugl/pugl_x11.c
@@ -24,8 +24,14 @@
#include <stdlib.h>
#include <string.h>
+#ifdef PUGL_HAVE_GL
#include <GL/gl.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/Xlib.h>
#include <X11/Xutil.h>
@@ -53,10 +59,17 @@ struct PuglInternalsImpl {
Display* display;
int screen;
Window win;
+#ifdef PUGL_HAVE_CAIRO
+ cairo_t* cr;
+ cairo_surface_t* surface;
+#endif
+#ifdef PUGL_HAVE_GL
GLXContext ctx;
Bool doubleBuffered;
+#endif
};
+#ifdef PUGL_HAVE_GL
/**
Attributes for single-buffered RGBA with at least
4 bits per color and a 16 bit depth buffer.
@@ -102,6 +115,7 @@ static int attrListDblMS[] = {
GLX_SAMPLES, 4,
None
};
+#endif
PuglInternals*
puglInitInternals(void)
@@ -112,25 +126,33 @@ puglInitInternals(void)
void
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
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
puglCreateWindow(PuglView* view, const char* title)
{
- PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals));
+ PuglInternals* impl = view->impl;
if (!impl) {
return 1;
}
@@ -142,21 +164,35 @@ puglCreateWindow(PuglView* view, const char* title)
return 1;
}
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
- printf("puGL: multisampling (antialiasing) is not available\n");
+ printf("puGL: multisampling (antialiasing) is not available\n");
#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) {
XCloseDisplay(impl->display);
@@ -165,18 +201,25 @@ puglCreateWindow(PuglView* view, const char* title)
}
#ifdef PUGL_VERBOSE
+#ifdef PUGL_HAVE_GL
int glxMajor, glxMinor;
glXQueryVersion(impl->display, &glxMajor, &glxMinor);
printf("puGL: GLX-Version : %d.%d\n", glxMajor, glxMinor);
#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)view->parent
@@ -201,11 +244,40 @@ puglCreateWindow(PuglView* view, const char* title)
CWBorderPixel | CWColormap | CWEventMask, &attr);
if (!impl->win) {
+#ifdef PUGL_HAVE_GL
+ if (view->ctx_type == PUGL_GL) {
+ glXDestroyContext(impl->display, impl->ctx);
+ }
+#endif
+ XFree(vi);
XCloseDisplay(impl->display);
free(impl);
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) {
puglUpdateGeometryConstraints(view, view->min_width, view->min_height, view->min_width != view->width);
XResizeWindow(view->impl->display, view->impl->win, view->width, view->height);
@@ -227,12 +299,14 @@ puglCreateWindow(PuglView* view, const char* title)
}
#ifdef PUGL_VERBOSE
+#ifdef PUGL_HAVE_GL
if (glXIsDirect(impl->display, impl->ctx)) {
printf("puGL: DRI enabled (to disable, set LIBGL_ALWAYS_INDIRECT=1\n");
} else {
printf("puGL: No DRI available\n");
}
#endif
+#endif
XFree(vi);
return 0;
@@ -244,14 +318,27 @@ puglDestroy(PuglView* view)
if (!view) {
return;
}
+
+ PuglInternals* const impl = view->impl;
+
#ifndef DGL_FILE_BROWSER_DISABLED
- x_fib_close(view->impl->display);
+ x_fib_close(impl->display);
#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);
}
@@ -554,6 +641,14 @@ puglProcessEvents(PuglView* view)
}
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);
}
@@ -586,6 +681,20 @@ puglGetNativeWindow(PuglView* view)
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
puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect)
{