diff options
| -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 | ||||
| -rw-r--r-- | pugl_cairo_test.c | 1 | ||||
| -rw-r--r-- | pugl_test.c | 1 | ||||
| -rw-r--r-- | wscript | 3 | 
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 @@ -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);  	} @@ -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, | 
