aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pugl/event.h2
-rw-r--r--pugl/glu.h2
-rw-r--r--pugl/pugl.h29
-rw-r--r--pugl/pugl.hpp123
-rw-r--r--pugl/pugl_internal.h23
-rw-r--r--pugl/pugl_osx.m20
-rw-r--r--pugl/pugl_win.cpp14
-rw-r--r--pugl/pugl_x11.c65
-rw-r--r--pugl_cairo_test.c1
-rw-r--r--pugl_test.c1
-rw-r--r--wscript3
11 files changed, 253 insertions, 30 deletions
diff --git a/pugl/event.h b/pugl/event.h
index 68fdcda..731e045 100644
--- a/pugl/event.h
+++ b/pugl/event.h
@@ -1,5 +1,5 @@
/*
- Copyright 2014 David Robillard <http://drobilla.net>
+ Copyright 2014-2015 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
diff --git a/pugl/glu.h b/pugl/glu.h
index 0ed0055..0d3e8e1 100644
--- a/pugl/glu.h
+++ b/pugl/glu.h
@@ -1,5 +1,5 @@
/*
- Copyright 2012-2014 David Robillard <http://drobilla.net>
+ Copyright 2012-2015 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
diff --git a/pugl/pugl.h b/pugl/pugl.h
index 53115ff..074297c 100644
--- a/pugl/pugl.h
+++ b/pugl/pugl.h
@@ -1,5 +1,5 @@
/*
- Copyright 2012-2014 David Robillard <http://drobilla.net>
+ Copyright 2012-2015 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -171,6 +171,19 @@ PUGL_API void
puglInitWindowMinSize(PuglView* view, int width, int height);
/**
+ Set the window aspect ratio range before creating a window.
+
+ The x and y values here represent a ratio of width to height. To set a
+ fixed aspect ratio, set the minimum and maximum values to the same ratio.
+*/
+PUGL_API void
+puglInitWindowAspectRatio(PuglView* view,
+ int min_x,
+ int min_y,
+ int max_x,
+ int max_y);
+
+/**
Enable or disable resizing before creating a window.
*/
PUGL_API void
@@ -349,10 +362,22 @@ PUGL_API void
puglGrabFocus(PuglView* view);
/**
+ Block and wait for an event to be ready.
+
+ This can be used in a loop to only process events via puglProcessEvents when
+ necessary. This function will block indefinitely if no events are
+ available, so is not appropriate for use in programs that need to perform
+ regular updates (e.g. animation).
+*/
+PUGL_API PuglStatus
+puglWaitForEvent(PuglView* view);
+
+/**
Process all pending window events.
This handles input events as well as rendering, so it should be called
- regularly and rapidly enough to keep the UI responsive.
+ regularly and rapidly enough to keep the UI responsive. This function does
+ not block if no events are pending.
*/
PUGL_API PuglStatus
puglProcessEvents(PuglView* view);
diff --git a/pugl/pugl.hpp b/pugl/pugl.hpp
new file mode 100644
index 0000000..b6386ac
--- /dev/null
+++ b/pugl/pugl.hpp
@@ -0,0 +1,123 @@
+/*
+ Copyright 2012-2015 David Robillard <http://drobilla.net>
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/**
+ @file pugl.hpp C++ API for Pugl, a minimal portable API for OpenGL.
+*/
+
+#ifndef PUGL_HPP_INCLUDED
+#define PUGL_HPP_INCLUDED
+
+#include "pugl/pugl.h"
+
+/**
+ @defgroup puglmm Puglmm
+ C++ API wrapper for Pugl.
+ @{
+*/
+
+namespace pugl {
+
+class View {
+public:
+ View(int* pargc, char** argv)
+ : _view(puglInit(pargc, argv))
+ {
+ puglSetHandle(_view, this);
+ puglSetEventFunc(_view, _onEvent);
+ puglSetCloseFunc(_view, _onClose);
+ puglSetReshapeFunc(_view, _onReshape);
+ puglSetDisplayFunc(_view, _onDisplay);
+ }
+
+ ~View() { puglDestroy(_view); }
+
+ virtual void initWindowParent(PuglNativeWindow parent) {
+ puglInitWindowParent(_view, parent);
+ }
+
+ virtual void initWindowSize(int width, int height) {
+ puglInitWindowSize(_view, width, height);
+ }
+
+ virtual void initWindowMinSize(int width, int height) {
+ puglInitWindowMinSize(_view, width, height);
+ }
+
+ virtual void initWindowAspectRatio(int min_x, int min_y, int max_x, int max_y) {
+ puglInitWindowAspectRatio(_view, min_x, min_y, max_x, max_y);
+ }
+
+ virtual void initResizable(bool resizable) {
+ puglInitResizable(_view, resizable);
+ }
+
+ virtual void initTransientFor(uintptr_t parent) {
+ puglInitTransientFor(_view, parent);
+ }
+
+ virtual void initContextType(PuglContextType type) {
+ puglInitContextType(_view, type);
+ }
+
+ virtual void createWindow(const char* title) {
+ puglCreateWindow(_view, title);
+ }
+
+ virtual void showWindow() { puglShowWindow(_view); }
+ virtual void hideWindow() { puglHideWindow(_view); }
+ virtual PuglNativeWindow getNativeWindow() { return puglGetNativeWindow(_view); }
+
+ virtual void onEvent(const PuglEvent* event) {}
+ virtual void onClose() {}
+ virtual void onReshape(int width, int height) {}
+ virtual void onDisplay() {}
+
+ virtual void* getContext() { return puglGetContext(_view); }
+ virtual uint32_t getEventTimestamp() { return puglGetEventTimestamp(_view); }
+ virtual int getModifiers() { return puglGetModifiers(_view); }
+ virtual void ignoreKeyRepeat(bool ignore) { puglIgnoreKeyRepeat(_view, ignore); }
+ virtual void grabFocus() { puglGrabFocus(_view); }
+ virtual PuglStatus waitForEvent() { return puglWaitForEvent(_view); }
+ virtual PuglStatus processEvents() { return puglProcessEvents(_view); }
+ virtual void postRedisplay() { puglPostRedisplay(_view); }
+
+ PuglView* cobj() { return _view; }
+
+private:
+ static void _onEvent(PuglView* view, const PuglEvent* event) {
+ ((View*)puglGetHandle(view))->onEvent(event);
+ }
+ static void _onClose(PuglView* view) {
+ ((View*)puglGetHandle(view))->onClose();
+ }
+ static void _onReshape(PuglView* view, int width, int height) {
+ ((View*)puglGetHandle(view))->onReshape(width, height);
+ }
+ static void _onDisplay(PuglView* view) {
+ ((View*)puglGetHandle(view))->onDisplay();
+ }
+
+ PuglView* _view;
+};
+
+} // namespace pugl
+
+/**
+ @}
+*/
+
+#endif /* PUGL_HPP_INCLUDED */
diff --git a/pugl/pugl_internal.h b/pugl/pugl_internal.h
index 993f319..1006c90 100644
--- a/pugl/pugl_internal.h
+++ b/pugl/pugl_internal.h
@@ -1,5 +1,5 @@
/*
- Copyright 2012-2014 David Robillard <http://drobilla.net>
+ Copyright 2012-2015 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -55,6 +55,10 @@ struct PuglViewImpl {
int height;
int min_width;
int min_height;
+ int min_aspect_x;
+ int min_aspect_y;
+ int max_aspect_x;
+ int max_aspect_y;
int mods;
bool mouse_in_view;
bool ignoreKeyRepeat;
@@ -100,6 +104,19 @@ puglInitWindowMinSize(PuglView* view, int width, int height)
}
void
+puglInitWindowAspectRatio(PuglView* view,
+ int min_x,
+ int min_y,
+ int max_x,
+ int max_y)
+{
+ view->min_aspect_x = min_x;
+ view->min_aspect_y = min_y;
+ view->max_aspect_x = max_x;
+ view->max_aspect_y = max_y;
+}
+
+void
puglInitWindowParent(PuglView* view, PuglNativeWindow parent)
{
view->parent = parent;
@@ -250,7 +267,9 @@ puglDecodeUTF8(const uint8_t* buf)
static void
puglDispatchEvent(PuglView* view, const PuglEvent* event)
{
- if (view->eventFunc) {
+ if (event->type == PUGL_NOTHING) {
+ return;
+ } else if (view->eventFunc) {
view->eventFunc(view, event);
}
diff --git a/pugl/pugl_osx.m b/pugl/pugl_osx.m
index 85e71a8..f41c863 100644
--- a/pugl/pugl_osx.m
+++ b/pugl/pugl_osx.m
@@ -1,5 +1,5 @@
/*
- Copyright 2012-2014 David Robillard <http://drobilla.net>
+ Copyright 2012-2015 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -525,10 +525,24 @@ puglGrabFocus(PuglView* view)
}
PuglStatus
+puglWaitForEvent(PuglView* view)
+{
+ [view->impl->window nextEventMatchingMask: NSAnyEventMask
+ untilDate: [NSDate distantFuture]
+ dequeue: NO];
+
+ return PUGL_SUCCESS;
+}
+
+PuglStatus
puglProcessEvents(PuglView* view)
{
- NSEvent* ev = [view->impl->window nextEventMatchingMask: NSAnyEventMask];
- [view->impl->app sendEvent: ev];
+ NSEvent* ev = [view->impl->window nextEventMatchingMask: NSAnyEventMask
+ untilDate: [NSDate distantPast]];
+
+ if (ev) {
+ [view->impl->app sendEvent: ev];
+ }
return PUGL_SUCCESS;
}
diff --git a/pugl/pugl_win.cpp b/pugl/pugl_win.cpp
index 28112ad..3686b37 100644
--- a/pugl/pugl_win.cpp
+++ b/pugl/pugl_win.cpp
@@ -1,5 +1,5 @@
/*
- Copyright 2012-2014 David Robillard <http://drobilla.net>
+ Copyright 2012-2015 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -153,7 +153,7 @@ puglCreateWindow(PuglView* view, const char* title)
impl->hwnd = CreateWindowEx(
WS_EX_TOPMOST,
- classNameBuf, title,
+ classNameBuf, title,
(view->parent ? WS_CHILD : winFlags),
CW_USEDEFAULT, CW_USEDEFAULT, wr.right-wr.left, wr.bottom-wr.top,
(HWND)view->parent, NULL, NULL, NULL);
@@ -168,7 +168,7 @@ puglCreateWindow(PuglView* view, const char* title)
#ifdef _WIN64
SetWindowLongPtr(impl->hwnd, GWLP_USERDATA, (LONG_PTR)view);
#else
- SetWindowLongPtr(impl->hwnd, GWL_USERDATA, (LONG)view);
+ SetWindowLongPtr(impl->hwnd, GWL_USERDATA, (LONG)view);
#endif
impl->hdc = GetDC(impl->hwnd);
@@ -425,6 +425,13 @@ puglGrabFocus(PuglView* view)
}
PuglStatus
+puglWaitForEvent(PuglView* view)
+{
+ WaitMessage();
+ return PUGL_SUCCESS;
+}
+
+PuglStatus
puglProcessEvents(PuglView* view)
{
MSG msg;
@@ -432,7 +439,6 @@ puglProcessEvents(PuglView* view)
handleMessage(view, msg.message, msg.wParam, msg.lParam);
}
-
if (view->redisplay) {
InvalidateRect(view->impl->hwnd, NULL, FALSE);
}
diff --git a/pugl/pugl_x11.c b/pugl/pugl_x11.c
index da33063..35cca8c 100644
--- a/pugl/pugl_x11.c
+++ b/pugl/pugl_x11.c
@@ -1,5 +1,5 @@
/*
- Copyright 2012-2014 David Robillard <http://drobilla.net>
+ Copyright 2012-2015 David Robillard <http://drobilla.net>
Copyright 2013 Robin Gareus <robin@gareus.org>
Copyright 2011-2012 Ben Loftis, Harrison Consoles
@@ -43,17 +43,18 @@
#include "pugl/pugl_internal.h"
struct PuglInternalsImpl {
- Display* display;
- int screen;
- Window win;
- XIM xim;
- XIC xic;
+ Display* display;
+ int screen;
+ Window win;
+ XIM xim;
+ XIC xic;
#ifdef PUGL_HAVE_CAIRO
- cairo_t* cr;
+ cairo_surface_t* surface;
+ cairo_t* cr;
#endif
#ifdef PUGL_HAVE_GL
- GLXContext ctx;
- Bool doubleBuffered;
+ GLXContext ctx;
+ Bool doubleBuffered;
#endif
};
@@ -118,9 +119,9 @@ createContext(PuglView* view, XVisualInfo* vi)
#endif
#ifdef PUGL_HAVE_CAIRO
if (view->ctx_type == PUGL_CAIRO) {
- cairo_surface_t* surface = cairo_xlib_surface_create(
+ view->impl->surface = cairo_xlib_surface_create(
impl->display, impl->win, vi->visual, view->width, view->height);
- if (!(impl->cr = cairo_create(surface))) {
+ if (!(impl->cr = cairo_create(view->impl->surface))) {
fprintf(stderr, "failed to create cairo context\n");
}
}
@@ -137,7 +138,8 @@ destroyContext(PuglView* view)
#endif
#ifdef PUGL_HAVE_CAIRO
if (view->ctx_type == PUGL_CAIRO) {
- glXDestroyContext(view->impl->display, view->impl->ctx);
+ cairo_destroy(view->impl->cr);
+ cairo_surface_destroy(view->impl->surface);
}
#endif
}
@@ -212,10 +214,20 @@ puglCreateWindow(PuglView* view, const char* title)
sizeHints.max_width = view->width;
sizeHints.max_height = view->height;
XSetNormalHints(impl->display, impl->win, &sizeHints);
- } else if (view->min_width || view->min_height) {
- sizeHints.flags = PMinSize;
- sizeHints.min_width = view->min_width;
- sizeHints.min_height = view->min_height;
+ } else {
+ if (view->min_width || view->min_height) {
+ sizeHints.flags = PMinSize;
+ sizeHints.min_width = view->min_width;
+ sizeHints.min_height = view->min_height;
+ }
+ if (view->min_aspect_x) {
+ sizeHints.flags |= PAspect;
+ sizeHints.min_aspect.x = view->min_aspect_x;
+ sizeHints.min_aspect.y = view->min_aspect_y;
+ sizeHints.max_aspect.x = view->max_aspect_x;
+ sizeHints.max_aspect.y = view->max_aspect_y;
+ }
+
XSetNormalHints(impl->display, impl->win, &sizeHints);
}
@@ -482,9 +494,18 @@ puglGrabFocus(PuglView* view)
}
PuglStatus
+puglWaitForEvent(PuglView* view)
+{
+ XEvent xevent;
+ XPeekEvent(view->impl->display, &xevent);
+ return PUGL_SUCCESS;
+}
+
+PuglStatus
puglProcessEvents(PuglView* view)
{
XEvent xevent;
+ bool resized = false;
while (XPending(view->impl->display) > 0) {
XNextEvent(view->impl->display, &xevent);
bool ignore = false;
@@ -515,6 +536,8 @@ puglProcessEvents(PuglView* view)
XSetICFocus(view->impl->xic);
} else if (xevent.type == FocusOut) {
XUnsetICFocus(view->impl->xic);
+ } else if (xevent.type == ConfigureNotify) {
+ resized = true;
}
if (!ignore) {
@@ -524,6 +547,16 @@ puglProcessEvents(PuglView* view)
}
}
+ if (resized) {
+#ifdef PUGL_HAVE_CAIRO
+ if (view->ctx_type == PUGL_CAIRO) {
+ cairo_xlib_surface_set_size(
+ view->impl->surface, view->width, view->height);
+ view->redisplay = true;
+ }
+#endif
+ }
+
if (view->redisplay) {
const PuglEventExpose expose = {
PUGL_EXPOSE, view, true, 0, 0, view->width, view->height, 0
diff --git a/pugl_cairo_test.c b/pugl_cairo_test.c
index bd97668..9c1bef8 100644
--- a/pugl_cairo_test.c
+++ b/pugl_cairo_test.c
@@ -166,6 +166,7 @@ main(int argc, char** argv)
puglShowWindow(view);
while (!quit) {
+ puglWaitForEvent(view);
puglProcessEvents(view);
}
diff --git a/pugl_test.c b/pugl_test.c
index 248a49a..af51e53 100644
--- a/pugl_test.c
+++ b/pugl_test.c
@@ -191,6 +191,7 @@ main(int argc, char** argv)
puglShowWindow(view);
while (!quit) {
+ puglWaitForEvent(view);
puglProcessEvents(view);
}
diff --git a/wscript b/wscript
index 522c0e8..b1e284a 100644
--- a/wscript
+++ b/wscript
@@ -95,6 +95,7 @@ def build(bld):
# C Headers
includedir = '${INCLUDEDIR}/pugl-%s/pugl' % PUGL_MAJOR_VERSION
bld.install_files(includedir, bld.path.ant_glob('pugl/*.h'))
+ bld.install_files(includedir, bld.path.ant_glob('pugl/*.hpp'))
# Pkgconfig file
autowaf.build_pc(bld, 'PUGL', PUGL_VERSION, PUGL_MAJOR_VERSION, [],
@@ -166,7 +167,7 @@ def build(bld):
progs += ['pugl_test']
if bld.is_defined('HAVE_CAIRO'):
progs += ['pugl_cairo_test']
-
+
for prog in progs:
obj = bld(features = 'c cprogram',
source = '%s.c' % prog,