aboutsummaryrefslogtreecommitdiffstats
path: root/pugl
diff options
context:
space:
mode:
Diffstat (limited to 'pugl')
-rw-r--r--pugl/pugl.h16
-rw-r--r--pugl/pugl_osx.m291
-rw-r--r--pugl/pugl_x11.c6
3 files changed, 311 insertions, 2 deletions
diff --git a/pugl/pugl.h b/pugl/pugl.h
index e5021f3..13f5efa 100644
--- a/pugl/pugl.h
+++ b/pugl/pugl.h
@@ -23,6 +23,22 @@
#include <stdint.h>
+/*
+ This API is pure portable C and contains no platform specific elements, or
+ even a GL dependency. However, unfortunately GL includes vary across
+ platforms so they are included here to allow for pure portable programs.
+*/
+#ifdef __APPLE__
+# include "OpenGL/gl.h"
+# include "OpenGL/glu.h"
+#else
+# ifdef _WIN32
+# include <windows.h> /* Broken Windows GL headers require this */
+# endif
+# include "GL/gl.h"
+# include "GL/glu.h"
+#endif
+
#ifdef __cplusplus
extern "C" {
#else
diff --git a/pugl/pugl_osx.m b/pugl/pugl_osx.m
new file mode 100644
index 0000000..619e453
--- /dev/null
+++ b/pugl/pugl_osx.m
@@ -0,0 +1,291 @@
+/*
+ Copyright 2012 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.
+*/
+
+#include <stdlib.h>
+
+#import <Cocoa/Cocoa.h>
+
+#include "pugl_internal.h"
+
+@interface PuglOpenGLView : NSOpenGLView
+{
+ int colorBits;
+ int depthBits;
+@public
+ PuglWindow* win;
+}
+
+- (id) initWithFrame:(NSRect)frame
+ colorBits:(int)numColorBits
+ depthBits:(int)numDepthBits;
+- (void) reshape;
+- (void) drawRect:(NSRect)rect;
+- (void) mouseMoved:(NSEvent*)event;
+- (void) mouseDown:(NSEvent*)event;
+- (void) mouseUp:(NSEvent*)event;
+- (void) rightMouseDown:(NSEvent*)event;
+- (void) rightMouseUp:(NSEvent*)event;
+- (void) keyDown:(NSEvent*)event;
+- (void) keyUp:(NSEvent*)event;
+
+@end
+
+@implementation PuglOpenGLView
+
+- (id) initWithFrame:(NSRect)frame
+ colorBits:(int)numColorBits
+ depthBits:(int)numDepthBits
+{
+ colorBits = numColorBits;
+ depthBits = numDepthBits;
+
+ NSOpenGLPixelFormatAttribute pixelAttribs[16] = {
+ NSOpenGLPFADoubleBuffer,
+ NSOpenGLPFAAccelerated,
+ NSOpenGLPFAColorSize,
+ colorBits,
+ NSOpenGLPFADepthSize,
+ depthBits,
+ 0
+ };
+
+ NSOpenGLPixelFormat* pixelFormat = [[NSOpenGLPixelFormat alloc]
+ initWithAttributes:pixelAttribs];
+
+ if (pixelFormat) {
+ self = [super initWithFrame:frame pixelFormat:pixelFormat];
+ [pixelFormat release];
+ if (self) {
+ [[self openGLContext] makeCurrentContext];
+ [self reshape];
+ }
+ } else {
+ self = nil;
+ }
+
+ return self;
+}
+
+- (void) reshape
+{
+ [[self openGLContext] update];
+
+ NSRect bounds = [self bounds];
+ int width = bounds.size.width;
+ int height = bounds.size.height;
+
+ if (win->reshapeFunc) {
+ // User provided a reshape function, defer to that
+ win->reshapeFunc(win, width, height);
+ } else {
+ // No custom reshape function, do something reasonable
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(45.0f, width/(float)height, 1.0f, 10.0f);
+ glViewport(0, 0, width, height);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ }
+
+ win->width = width;
+ win->height = height;
+ win->redisplay = true;
+}
+
+- (void) drawRect:(NSRect)rect
+{
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glLoadIdentity();
+
+ if (self->win->displayFunc) {
+ self->win->displayFunc(self->win);
+ }
+
+ glFlush();
+ glSwapAPPLE();
+}
+
+- (void) mouseMoved:(NSEvent*)event
+{
+ NSPoint loc = [event locationInWindow];
+ if (win->motionFunc) {
+ win->motionFunc(win, loc.x, loc.y);
+ }
+}
+
+- (void) mouseDown:(NSEvent*)event
+{
+ NSPoint loc = [event locationInWindow];
+ if (win->mouseFunc) {
+ win->mouseFunc(win, 1, true, loc.x, loc.y);
+ }
+}
+
+- (void) mouseUp:(NSEvent*)event
+{
+ NSPoint loc = [event locationInWindow];
+ if (win->mouseFunc) {
+ win->mouseFunc(win, 1, false, loc.x, loc.y);
+ }
+}
+
+- (void) rightMouseDown:(NSEvent*)event
+{
+ NSPoint loc = [event locationInWindow];
+ if (win->mouseFunc) {
+ win->mouseFunc(win, 3, true, loc.x, loc.y);
+ }
+}
+
+- (void) rightMouseUp:(NSEvent*)event
+{
+ NSPoint loc = [event locationInWindow];
+ if (win->mouseFunc) {
+ win->mouseFunc(win, 3, false, loc.x, loc.y);
+ }
+}
+
+- (void) scrollWheel:(NSEvent*)event
+{
+ if (win->scrollFunc) {
+ win->scrollFunc(win, [event deltaX], [event deltaY]);
+ }
+}
+
+- (void) keyDown:(NSEvent*)event
+{
+ NSString* chars = [event characters];;
+ if (win->keyboardFunc) {
+ win->keyboardFunc(win, true, [chars characterAtIndex:0]);
+ }
+}
+
+- (void) keyUp:(NSEvent*)event
+{
+ NSString* chars = [event characters];;
+ if (win->keyboardFunc) {
+ win->keyboardFunc(win, false, [chars characterAtIndex:0]);
+ }
+}
+
+@end
+
+struct PuglPlatformDataImpl {
+ PuglOpenGLView* view;
+ NSModalSession session;
+ id window;
+};
+
+PuglWindow*
+puglCreate(PuglNativeWindow parent,
+ const char* title,
+ int width,
+ int height,
+ bool resizable)
+{
+ PuglWindow* win = (PuglWindow*)calloc(1, sizeof(PuglWindow));
+ win->width = width;
+ win->height = height;
+
+ win->impl = (PuglPlatformData*)calloc(1, sizeof(PuglPlatformData));
+
+ PuglPlatformData* impl = win->impl;
+
+ [NSAutoreleasePool new];
+ [NSApplication sharedApplication];
+ [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+
+ NSString* titleString = [[NSString alloc]
+ initWithBytes:title
+ length:strlen(title)
+ encoding:NSUTF8StringEncoding];
+
+ id window = [[[NSWindow alloc]
+ initWithContentRect:NSMakeRect(0, 0, 512, 512)
+ styleMask:NSTitledWindowMask
+ backing:NSBackingStoreBuffered
+ defer:NO]
+ autorelease];
+
+ [window cascadeTopLeftFromPoint:NSMakePoint(20, 20)];
+ [window setTitle:titleString];
+ [window setAcceptsMouseMovedEvents:YES];
+
+ impl->view = [PuglOpenGLView new];
+ impl->window = window;
+ impl->view->win = win;
+
+ [window setContentView:impl->view];
+ [NSApp activateIgnoringOtherApps:YES];
+ [window makeFirstResponder:impl->view];
+
+ impl->session = [NSApp beginModalSessionForWindow:win->impl->window];
+
+ return win;
+}
+
+void
+puglDestroy(PuglWindow* win)
+{
+ [NSApp endModalSession:win->impl->session];
+ [win->impl->view release];
+ free(win->impl);
+ free(win);
+}
+
+void
+puglDisplay(PuglWindow* win)
+{
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glLoadIdentity();
+
+ if (win->displayFunc) {
+ win->displayFunc(win);
+ }
+
+ glFlush();
+ win->redisplay = false;
+}
+
+PuglStatus
+puglProcessEvents(PuglWindow* win)
+{
+ NSInteger response = [NSApp runModalSession:win->impl->session];
+ if (response != NSRunContinuesResponse) {
+ if (win->closeFunc) {
+ win->closeFunc(win);
+ }
+ }
+
+ if (win->redisplay) {
+ puglDisplay(win);
+ }
+
+ return PUGL_SUCCESS;
+}
+
+void
+puglPostRedisplay(PuglWindow* win)
+{
+ win->redisplay = true;
+}
+
+PuglNativeWindow
+puglGetNativeWindow(PuglWindow* win)
+{
+ return (PuglNativeWindow)win->impl->view;
+}
diff --git a/pugl/pugl_x11.c b/pugl/pugl_x11.c
index c6cc2b5..f4aa933 100644
--- a/pugl/pugl_x11.c
+++ b/pugl/pugl_x11.c
@@ -176,8 +176,8 @@ puglReshape(PuglWindow* win, int width, int height)
// No custom reshape function, do something reasonable
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
- gluPerspective(45.0f, win->width/(float)win->height, 1.0f, 10.0f);
- glViewport(0, 0, win->width, win->height);
+ gluPerspective(45.0f, width/(float)height, 1.0f, 10.0f);
+ glViewport(0, 0, width, height);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
@@ -203,6 +203,8 @@ puglDisplay(PuglWindow* win)
if (win->impl->doubleBuffered) {
glXSwapBuffers(win->impl->display, win->impl->win);
}
+
+ win->redisplay = false;
}
PuglStatus