diff options
author | David Robillard <d@drobilla.net> | 2015-09-13 16:24:45 -0400 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2015-09-13 16:24:45 -0400 |
commit | add00976a0c39f78f57df79c2a194c4f4e7adbf7 (patch) | |
tree | 0ac8e24a7d09faa2b6d177d147d471555cc09af6 /pugl | |
parent | 7c1f22fdf4782aa04a14a914b5a51b3617362366 (diff) | |
parent | d457ac139797b05fdc214f8af458833b58033224 (diff) | |
download | pugl-add00976a0c39f78f57df79c2a194c4f4e7adbf7.tar.gz pugl-add00976a0c39f78f57df79c2a194c4f4e7adbf7.tar.bz2 pugl-add00976a0c39f78f57df79c2a194c4f4e7adbf7.zip |
Merge branch 'master' of git.drobilla.net:/home/drobilla/git.drobilla.net/pugl
Diffstat (limited to 'pugl')
-rw-r--r-- | pugl/event.h | 2 | ||||
-rw-r--r-- | pugl/glu.h | 2 | ||||
-rw-r--r-- | pugl/pugl.h | 29 | ||||
-rw-r--r-- | pugl/pugl.hpp | 123 | ||||
-rw-r--r-- | pugl/pugl_internal.h | 23 | ||||
-rw-r--r-- | pugl/pugl_osx.m | 20 | ||||
-rw-r--r-- | pugl/pugl_win.cpp | 14 | ||||
-rw-r--r-- | pugl/pugl_x11.c | 65 |
8 files changed, 249 insertions, 29 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 @@ -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 |