From 23ecce9dacf6938391a127f95a8b6eea27ee8fb5 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 12 Jul 2015 23:23:15 -0400 Subject: Fix whitespace. --- pugl/pugl_win.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pugl/pugl_win.cpp b/pugl/pugl_win.cpp index 32ca6fb..04bc4b6 100644 --- a/pugl/pugl_win.cpp +++ b/pugl/pugl_win.cpp @@ -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); @@ -432,7 +432,6 @@ puglProcessEvents(PuglView* view) handleMessage(view, msg.message, msg.wParam, msg.lParam); } - if (view->redisplay) { InvalidateRect(view->impl->hwnd, NULL, FALSE); } -- cgit v1.2.1 From 2c72fa23e3aad2dc54a65bf3c9635eafa9c8786e Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 18 Jul 2015 14:27:20 -0400 Subject: Don't dispatch nothing events. --- pugl/pugl_internal.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pugl/pugl_internal.h b/pugl/pugl_internal.h index 993f319..f83f2c7 100644 --- a/pugl/pugl_internal.h +++ b/pugl/pugl_internal.h @@ -1,5 +1,5 @@ /* - Copyright 2012-2014 David Robillard + Copyright 2012-2015 David Robillard Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -250,7 +250,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); } -- cgit v1.2.1 From dc90b4f5d902218b4e1ccfa5a2b3c1a0b24a7995 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 12 Sep 2015 13:00:18 -0400 Subject: Fix destruction of cairo context. --- pugl/pugl_x11.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pugl/pugl_x11.c b/pugl/pugl_x11.c index da33063..a48edde 100644 --- a/pugl/pugl_x11.c +++ b/pugl/pugl_x11.c @@ -137,7 +137,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 } -- cgit v1.2.1 From ae2153511097fc0cc34c0456ebbb13fd4f5c79ec Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 12 Sep 2015 13:00:37 -0400 Subject: Fix resizing with cairo context. --- pugl/pugl_x11.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/pugl/pugl_x11.c b/pugl/pugl_x11.c index a48edde..bd85b37 100644 --- a/pugl/pugl_x11.c +++ b/pugl/pugl_x11.c @@ -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"); } } @@ -486,6 +487,7 @@ PuglStatus puglProcessEvents(PuglView* view) { XEvent xevent; + bool resized = false; while (XPending(view->impl->display) > 0) { XNextEvent(view->impl->display, &xevent); bool ignore = false; @@ -516,6 +518,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) { @@ -525,6 +529,15 @@ 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); + } +#endif + } + if (view->redisplay) { const PuglEventExpose expose = { PUGL_EXPOSE, view, true, 0, 0, view->width, view->height, 0 -- cgit v1.2.1 From 6b4a5a128ef5d87374dfef017cd20e069c068a4b Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 12 Sep 2015 15:22:49 -0400 Subject: Add support for aspect ratio constraints. Currently only implemented on X11. --- pugl/pugl.h | 13 +++++++++++++ pugl/pugl_internal.h | 17 +++++++++++++++++ pugl/pugl_x11.c | 18 ++++++++++++++---- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/pugl/pugl.h b/pugl/pugl.h index 53115ff..3ff66f9 100644 --- a/pugl/pugl.h +++ b/pugl/pugl.h @@ -170,6 +170,19 @@ puglInitWindowSize(PuglView* view, int width, int height); 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. */ diff --git a/pugl/pugl_internal.h b/pugl/pugl_internal.h index f83f2c7..1006c90 100644 --- a/pugl/pugl_internal.h +++ b/pugl/pugl_internal.h @@ -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; @@ -99,6 +103,19 @@ puglInitWindowMinSize(PuglView* view, int width, int height) view->min_height = 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) { diff --git a/pugl/pugl_x11.c b/pugl/pugl_x11.c index bd85b37..6375609 100644 --- a/pugl/pugl_x11.c +++ b/pugl/pugl_x11.c @@ -214,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); } -- cgit v1.2.1 From 809ead2220f5a9ed66f88b1ae84a93e334e2717f Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 12 Sep 2015 19:45:02 -0400 Subject: Add puglWaitForEvent for blocking main loops. --- pugl/pugl.h | 14 +++++++++++++- pugl/pugl_osx.m | 18 ++++++++++++++++-- pugl/pugl_win.cpp | 7 +++++++ pugl/pugl_x11.c | 9 +++++++++ pugl_cairo_test.c | 1 + pugl_test.c | 1 + 6 files changed, 47 insertions(+), 3 deletions(-) diff --git a/pugl/pugl.h b/pugl/pugl.h index 3ff66f9..8dca956 100644 --- a/pugl/pugl.h +++ b/pugl/pugl.h @@ -361,11 +361,23 @@ puglSetReshapeFunc(PuglView* view, PuglReshapeFunc reshapeFunc); 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_osx.m b/pugl/pugl_osx.m index 85e71a8..47c8138 100644 --- a/pugl/pugl_osx.m +++ b/pugl/pugl_osx.m @@ -524,11 +524,25 @@ puglGrabFocus(PuglView* view) // TODO } +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 04bc4b6..850947d 100644 --- a/pugl/pugl_win.cpp +++ b/pugl/pugl_win.cpp @@ -424,6 +424,13 @@ puglGrabFocus(PuglView* view) // TODO } +PuglStatus +puglWaitForEvent(PuglView* view) +{ + WaitMessage(); + return PUGL_SUCCESS; +} + PuglStatus puglProcessEvents(PuglView* view) { diff --git a/pugl/pugl_x11.c b/pugl/pugl_x11.c index 6375609..32501da 100644 --- a/pugl/pugl_x11.c +++ b/pugl/pugl_x11.c @@ -493,6 +493,14 @@ puglGrabFocus(PuglView* view) view->impl->display, view->impl->win, RevertToPointerRoot, CurrentTime); } +PuglStatus +puglWaitForEvent(PuglView* view) +{ + XEvent xevent; + XPeekEvent(view->impl->display, &xevent); + return PUGL_SUCCESS; +} + PuglStatus puglProcessEvents(PuglView* view) { @@ -544,6 +552,7 @@ puglProcessEvents(PuglView* view) if (view->ctx_type == PUGL_CAIRO) { cairo_xlib_surface_set_size( view->impl->surface, view->width, view->height); + view->redisplay = true; } #endif } 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); } -- cgit v1.2.1 From 6abce4944cb49c65dd1d592be45b766110dbfeba Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 12 Sep 2015 19:51:03 -0400 Subject: Update copyright dates. --- pugl/event.h | 2 +- pugl/glu.h | 2 +- pugl/pugl.h | 2 +- pugl/pugl_osx.m | 2 +- pugl/pugl_win.cpp | 2 +- pugl/pugl_x11.c | 2 +- 6 files changed, 6 insertions(+), 6 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 + Copyright 2014-2015 David Robillard Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above 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 + Copyright 2012-2015 David Robillard Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/pugl/pugl.h b/pugl/pugl.h index 8dca956..074297c 100644 --- a/pugl/pugl.h +++ b/pugl/pugl.h @@ -1,5 +1,5 @@ /* - Copyright 2012-2014 David Robillard + Copyright 2012-2015 David Robillard Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/pugl/pugl_osx.m b/pugl/pugl_osx.m index 47c8138..f41c863 100644 --- a/pugl/pugl_osx.m +++ b/pugl/pugl_osx.m @@ -1,5 +1,5 @@ /* - Copyright 2012-2014 David Robillard + Copyright 2012-2015 David Robillard Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/pugl/pugl_win.cpp b/pugl/pugl_win.cpp index 850947d..e3ceef7 100644 --- a/pugl/pugl_win.cpp +++ b/pugl/pugl_win.cpp @@ -1,5 +1,5 @@ /* - Copyright 2012-2014 David Robillard + Copyright 2012-2015 David Robillard Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/pugl/pugl_x11.c b/pugl/pugl_x11.c index 32501da..35cca8c 100644 --- a/pugl/pugl_x11.c +++ b/pugl/pugl_x11.c @@ -1,5 +1,5 @@ /* - Copyright 2012-2014 David Robillard + Copyright 2012-2015 David Robillard Copyright 2013 Robin Gareus Copyright 2011-2012 Ben Loftis, Harrison Consoles -- cgit v1.2.1 From d457ac139797b05fdc214f8af458833b58033224 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 13 Sep 2015 11:37:52 -0400 Subject: Add C++ bindings. --- pugl/pugl.hpp | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ wscript | 3 +- 2 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 pugl/pugl.hpp 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 + + 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/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, -- cgit v1.2.1