aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2012-04-29 02:12:26 +0000
committerDavid Robillard <d@drobilla.net>2012-04-29 02:12:26 +0000
commite346dc20fb1fcbc8f895d7c46e3ec54628d3db0c (patch)
tree0b6d83ef9b8daf7a4fa57cd384a1abc33602906e
parent43083a0ca80a876286b6a6ef39ec6f10c9b6f9bf (diff)
Windows implementation.
-rw-r--r--pugl/pugl_win.cpp193
-rw-r--r--pugl_test.c17
-rw-r--r--wscript52
3 files changed, 242 insertions, 20 deletions
diff --git a/pugl/pugl_win.cpp b/pugl/pugl_win.cpp
new file mode 100644
index 0000000..a27a2c5
--- /dev/null
+++ b/pugl/pugl_win.cpp
@@ -0,0 +1,193 @@
+/*
+ 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 <stdio.h>
+
+#include <windows.h>
+#include <windowsx.h>
+#include <gl/gl.h>
+
+#include "pugl_internal.h"
+
+struct PuglPlatformDataImpl {
+ HWND hwnd;
+ HDC hdc;
+ HGLRC hglrc;
+};
+
+PuglWindow*
+puglCreate(PuglNativeWindow parent, const char* title, int width, int height)
+{
+ PuglWindow* win = (PuglWindow*)calloc(1, sizeof(PuglWindow));
+
+ win->impl = (PuglPlatformData*)calloc(1, sizeof(PuglPlatformData));
+
+ PuglPlatformData* impl = win->impl;
+
+ WNDCLASS wc;
+ wc.style = CS_OWNDC;
+ wc.lpfnWndProc = DefWindowProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = 0;
+ wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = "Pugl";
+ RegisterClass(&wc);
+
+ impl->hwnd = CreateWindow("Pugl", title,
+ WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE,
+ 0, 0, width, height,
+ (HWND)parent, NULL, NULL, NULL);
+
+
+ impl->hdc = GetDC(impl->hwnd);
+
+ PIXELFORMATDESCRIPTOR pfd;
+ ZeroMemory(&pfd, sizeof(pfd));
+ pfd.nSize = sizeof(pfd);
+ pfd.nVersion = 1;
+ pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ pfd.cColorBits = 24;
+ pfd.cDepthBits = 16;
+ pfd.iLayerType = PFD_MAIN_PLANE;
+
+ int format = ChoosePixelFormat(impl->hdc, &pfd);
+ SetPixelFormat(impl->hdc, format, &pfd);
+
+ impl->hglrc = wglCreateContext(impl->hdc);
+ wglMakeCurrent(impl->hdc, impl->hglrc);
+
+ win->width = width;
+ win->height = height;
+
+ return win;
+}
+
+void
+puglDestroy(PuglWindow* win)
+{
+ wglMakeCurrent(NULL, NULL);
+ wglDeleteContext(win->impl->hglrc);
+ ReleaseDC(win->impl->hwnd, win->impl->hdc);
+ DestroyWindow(win->impl->hwnd);
+ free(win);
+}
+
+void
+puglDisplay(PuglWindow* win)
+{
+ glViewport(0, 0, win->width, win->height);
+
+ if (win->displayFunc) {
+ win->displayFunc(win);
+ }
+
+ SwapBuffers(win->impl->hdc);
+ win->redisplay = false;
+}
+
+static void
+processMouseEvent(PuglWindow* win, int button, bool down, LPARAM lParam)
+{
+ if (win->mouseFunc) {
+ win->mouseFunc(win, button, down,
+ GET_X_LPARAM(lParam),
+ GET_Y_LPARAM(lParam));
+ }
+}
+
+PuglStatus
+puglProcessEvents(PuglWindow* win)
+{
+ MSG msg;
+ PAINTSTRUCT ps;
+ int button;
+ bool down = true;
+ while (PeekMessage(&msg, win->impl->hwnd, 0, 0, PM_REMOVE)) {
+ switch (msg.message) {
+ case WM_PAINT:
+ BeginPaint(win->impl->hwnd, &ps);
+ puglDisplay(win);
+ EndPaint(win->impl->hwnd, &ps);
+ break;
+ case WM_SIZE:
+ if (win->reshapeFunc) {
+ win->reshapeFunc(win, LOWORD(msg.lParam), HIWORD(msg.lParam));
+ }
+ break;
+ case WM_MOUSEMOVE:
+ if (win->motionFunc) {
+ win->motionFunc(
+ win, GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
+ }
+ break;
+ case WM_LBUTTONDOWN:
+ processMouseEvent(win, 1, true, msg.lParam);
+ break;
+ case WM_MBUTTONDOWN:
+ processMouseEvent(win, 2, true, msg.lParam);
+ break;
+ case WM_RBUTTONDOWN:
+ processMouseEvent(win, 3, true, msg.lParam);
+ break;
+ case WM_LBUTTONUP:
+ processMouseEvent(win, 1, false, msg.lParam);
+ break;
+ case WM_MBUTTONUP:
+ processMouseEvent(win, 2, false, msg.lParam);
+ break;
+ case WM_RBUTTONUP:
+ processMouseEvent(win, 3, false, msg.lParam);
+ break;
+ case WM_KEYDOWN:
+ case WM_KEYUP:
+ if (win->keyboardFunc) {
+ win->keyboardFunc(win, msg.message == WM_KEYDOWN, msg.wParam);
+ }
+ break;
+ case WM_QUIT:
+ if (win->closeFunc) {
+ win->closeFunc(win);
+ }
+ break;
+ default:
+ DefWindowProc(
+ win->impl->hwnd, msg.message, msg.wParam, msg.lParam);
+ }
+ }
+
+ if (win->redisplay) {
+ puglDisplay(win);
+ }
+
+ return PUGL_SUCCESS;
+}
+
+void
+puglPostRedisplay(PuglWindow* win)
+{
+ win->redisplay = true;
+}
+
+PuglNativeWindow
+puglGetNativeWindow(PuglWindow* win)
+{
+ return (PuglNativeWindow)win->impl->hwnd;
+}
diff --git a/pugl_test.c b/pugl_test.c
index 3122a89..f6d9ac2 100644
--- a/pugl_test.c
+++ b/pugl_test.c
@@ -18,6 +18,14 @@
@file pugl_test.c A simple Pugl test that creates a top-level window.
*/
+/*
+ This program uses only the the Pugl and OpenGL APIs, but the Windows
+ gl.h is broken and requires windows.h to be included first...
+*/
+#ifdef _WIN32
+# include <windows.h>
+#endif
+
#include <stdio.h>
#include "GL/gl.h"
@@ -51,7 +59,7 @@ onDisplay(PuglWindow* win)
static void
onKeyboard(PuglWindow* win, bool press, uint32_t key)
{
- if (key == 'q' || key == KEY_ESCAPE) {
+ if (key == 'q' || key == 'Q' || key == KEY_ESCAPE) {
quit = 1;
}
}
@@ -65,6 +73,12 @@ onMotion(PuglWindow* win, int x, int y)
}
static void
+onMouse(PuglWindow* handle, int button, int state, int x, int y)
+{
+ fprintf(stderr, "Mouse %d at %d,%d\n", button, x, y);
+}
+
+static void
onClose(PuglWindow* win)
{
quit = 1;
@@ -76,6 +90,7 @@ main(int argc, char** argv)
PuglWindow* win = puglCreate(0, "Pugl Test", 512, 512);
puglSetKeyboardFunc(win, onKeyboard);
puglSetMotionFunc(win, onMotion);
+ puglSetMouseFunc(win, onMouse);
puglSetDisplayFunc(win, onDisplay);
puglSetCloseFunc(win, onClose);
diff --git a/wscript b/wscript
index 1bf5b07..6643408 100644
--- a/wscript
+++ b/wscript
@@ -27,14 +27,20 @@ out = 'build'
def options(opt):
opt.load('compiler_c')
+ if Options.platform == 'win32':
+ opt.load('compiler_cxx')
autowaf.set_options(opt)
opt.add_option('--test', action='store_true', default=False, dest='build_tests',
help="Build unit tests")
opt.add_option('--static', action='store_true', default=False, dest='static',
help="Build static library")
+ opt.add_option('--shared', action='store_true', default=False, dest='shared',
+ help="Build shared library")
def configure(conf):
conf.load('compiler_c')
+ if Options.platform == 'win32':
+ conf.load('compiler_cxx')
autowaf.configure(conf)
autowaf.display_header('Pugl Configuration')
@@ -43,7 +49,10 @@ def configure(conf):
else:
conf.env.append_unique('CFLAGS', '-std=c99')
+ # Shared library building is broken on win32 for some reason
conf.env['BUILD_TESTS'] = Options.options.build_tests
+ conf.env['BUILD_SHARED'] = (Options.platform != 'win32' or
+ Options.options.shared)
conf.env['BUILD_STATIC'] = (Options.options.build_tests or
Options.options.static)
@@ -69,32 +78,37 @@ def build(bld):
{'PUGL_MAJOR_VERSION' : PUGL_MAJOR_VERSION})
libflags = [ '-fvisibility=hidden' ]
- libs = [ 'X11', 'GL' ]
- defines = []
+ if Options.platform == 'win32':
+ lang = 'cxx'
+ lib_source = ['pugl/pugl_win.cpp']
+ libs = ['opengl32', 'gdi32', 'user32']
+ defines = []
+ else:
+ lang = 'c'
+ lib_source = ['pugl/pugl_x11.c']
+ libs = ['X11', 'GL']
+ defines = []
if bld.env['MSVC_COMPILER']:
libflags = []
- libs = []
- defines = ['snprintf=_snprintf']
-
- lib_source = ['./pugl/pugl_x11.c']
# Shared Library
- obj = bld(features = 'c cshlib',
- export_includes = ['.'],
- source = lib_source,
- includes = ['.', './src'],
- lib = libs,
- name = 'libpugl',
- target = 'pugl-%s' % PUGL_MAJOR_VERSION,
- vnum = PUGL_LIB_VERSION,
- install_path = '${LIBDIR}',
- defines = defines,
- cflags = libflags + [ '-DPUGL_SHARED',
- '-DPUGL_INTERNAL' ])
+ if bld.env['BUILD_SHARED']:
+ obj = bld(features = '%s %sshlib' % (lang, lang),
+ export_includes = ['.'],
+ source = lib_source,
+ includes = ['.', './src'],
+ lib = libs,
+ name = 'libpugl',
+ target = 'pugl-%s' % PUGL_MAJOR_VERSION,
+ vnum = PUGL_LIB_VERSION,
+ install_path = '${LIBDIR}',
+ defines = defines,
+ cflags = libflags + [ '-DPUGL_SHARED',
+ '-DPUGL_INTERNAL' ])
# Static library
if bld.env['BUILD_STATIC']:
- obj = bld(features = 'c cstlib',
+ obj = bld(features = '%s %sstlib' % (lang, lang),
export_includes = ['.'],
source = lib_source,
includes = ['.', './src'],