| @@ -20,10 +20,27 @@ | |||
| Note this file contains function definitions, so it must be compiled into | |||
| the final binary exactly once. Each platform specific implementation file | |||
| including it once should achieve this. | |||
| If you are copying the pugl code into your source tree, the following | |||
| symbols can be defined to tweak pugl behaviour: | |||
| PUGL_GRAB_FOCUS: Work around reparent keyboard issues by grabbing focus. | |||
| PUGL_VERBOSE: Print GL information to console. | |||
| */ | |||
| #include "pugl.h" | |||
| #ifdef PUGL_VERBOSE | |||
| # include <stdio.h> | |||
| # define PUGL_LOG(str) fprintf(stderr, "pugl: " str) | |||
| # define PUGL_LOGF(fmt, ...) fprintf(stderr, "pugl: " fmt, __VA_ARGS__) | |||
| #else | |||
| # define PUGL_LOG(str) | |||
| # define PUGL_LOGF(fmt, ...) | |||
| #endif | |||
| void puglDefaultReshape(PuglView* view, int width, int height); | |||
| typedef struct PuglInternalsImpl PuglInternals; | |||
| struct PuglViewImpl { | |||
| @@ -24,14 +24,6 @@ | |||
| #include "pugl_internal.h" | |||
| void | |||
| puglDisplay(PuglView* view) | |||
| { | |||
| if (view->displayFunc) { | |||
| view->displayFunc(view); | |||
| } | |||
| } | |||
| @interface PuglWindow : NSWindow | |||
| { | |||
| @public | |||
| @@ -44,7 +36,6 @@ puglDisplay(PuglView* view) | |||
| defer:(BOOL)flag; | |||
| - (void) setPuglview:(PuglView*)view; | |||
| - (BOOL) windowShouldClose:(id)sender; | |||
| - (void) becomeKeyWindow:(id)sender; | |||
| - (BOOL) canBecomeKeyWindow:(id)sender; | |||
| @end | |||
| @@ -59,8 +50,7 @@ puglDisplay(PuglView* view) | |||
| styleMask:(NSClosableWindowMask | | |||
| NSTitledWindowMask | | |||
| NSResizableWindowMask) | |||
| backing:NSBackingStoreBuffered | |||
| defer:NO]; | |||
| backing:NSBackingStoreBuffered defer:NO]; | |||
| [result setAcceptsMouseMovedEvents:YES]; | |||
| [result setLevel: CGShieldingWindowLevel() + 1]; | |||
| @@ -81,19 +71,21 @@ puglDisplay(PuglView* view) | |||
| return YES; | |||
| } | |||
| - (void)becomeKeyWindow:(id)sender | |||
| { | |||
| printf("becomeKeyWindow\n"); | |||
| } | |||
| // this allows spacebar (for example) to start/stop the transport | |||
| - (BOOL) canBecomeKeyWindow:(id)sender | |||
| { | |||
| return YES; | |||
| return NO; | |||
| } | |||
| @end | |||
| void | |||
| puglDisplay(PuglView* view) | |||
| { | |||
| if (view->displayFunc) { | |||
| view->displayFunc(view); | |||
| } | |||
| } | |||
| @interface PuglOpenGLView : NSOpenGLView | |||
| { | |||
| int colorBits; | |||
| @@ -71,7 +71,7 @@ puglCreate(PuglNativeWindow parent, | |||
| // Should class be a parameter? Does this make sense on other platforms? | |||
| static int wc_count = 0; | |||
| char classNameBuf[256]; | |||
| sprintf(classNameBuf, "%s_%d\n", title, wc_count++); | |||
| _snprintf(classNameBuf, sizeof(classNameBuf), "%s_%d\n", title, wc_count++); | |||
| impl->wc.style = CS_OWNDC; | |||
| impl->wc.lpfnWndProc = wndProc; | |||
| @@ -91,7 +91,6 @@ puglCreate(PuglNativeWindow parent, | |||
| } | |||
| // Adjust the overall window size to accomodate our requested client size | |||
| // If there's any doubt that Windows is laughably outdated, here's the proof | |||
| RECT wr = { 0, 0, width, height }; | |||
| AdjustWindowRectEx(&wr, winFlags, FALSE, WS_EX_TOPMOST); | |||
| @@ -271,43 +270,45 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) | |||
| } | |||
| break; | |||
| case WM_LBUTTONDOWN: | |||
| view->event_timestamp_ms = (GetMessageTime()); | |||
| processMouseEvent(view, 1, true, lParam); | |||
| break; | |||
| case WM_MBUTTONDOWN: | |||
| view->event_timestamp_ms = (GetMessageTime()); | |||
| processMouseEvent(view, 2, true, lParam); | |||
| break; | |||
| case WM_RBUTTONDOWN: | |||
| view->event_timestamp_ms = (GetMessageTime()); | |||
| processMouseEvent(view, 3, true, lParam); | |||
| break; | |||
| case WM_LBUTTONUP: | |||
| view->event_timestamp_ms = (GetMessageTime()); | |||
| processMouseEvent(view, 1, false, lParam); | |||
| break; | |||
| case WM_MBUTTONUP: | |||
| view->event_timestamp_ms = (GetMessageTime()); | |||
| processMouseEvent(view, 2, false, lParam); | |||
| break; | |||
| case WM_RBUTTONUP: | |||
| view->event_timestamp_ms = (GetMessageTime()); | |||
| processMouseEvent(view, 3, false, lParam); | |||
| break; | |||
| case WM_MOUSEWHEEL: | |||
| if (view->scrollFunc) { | |||
| view->event_timestamp_ms = GetMessageTime(); | |||
| view->scrollFunc( | |||
| view, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), | |||
| 0.0f, (int16_t)HIWORD(wParam) / (float)WHEEL_DELTA); | |||
| } | |||
| break; | |||
| case WM_MOUSEHWHEEL: | |||
| if (view->scrollFunc) { | |||
| view->event_timestamp_ms = GetMessageTime(); | |||
| view->scrollFunc( | |||
| view, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), | |||
| (int16_t)HIWORD(wParam) / (float)WHEEL_DELTA, 0); | |||
| (int16_t)HIWORD(wParam) / float(WHEEL_DELTA), 0.0f); | |||
| } | |||
| break; | |||
| case WM_KEYDOWN: | |||
| view->event_timestamp_ms = (GetMessageTime()); | |||
| if (view->ignoreKeyRepeat && (lParam & (1 << 30))) { | |||
| break; | |||
| } // else nobreak | |||
| case WM_KEYUP: | |||
| view->event_timestamp_ms = GetMessageTime(); | |||
| if ((key = keySymToSpecial(wParam))) { | |||
| if (view->specialFunc) { | |||
| view->specialFunc(view, message == WM_KEYDOWN, key); | |||
| @@ -338,6 +339,7 @@ puglProcessEvents(PuglView* view) | |||
| handleMessage(view, msg.message, msg.wParam, msg.lParam); | |||
| } | |||
| if (view->redisplay) { | |||
| InvalidateRect(view->impl->hwnd, NULL, FALSE); | |||
| } | |||
| @@ -1,7 +1,6 @@ | |||
| /* | |||
| Copyright 2012-2014 David Robillard <http://drobilla.net> | |||
| Copyright 2011-2012 Ben Loftis, Harrison Consoles | |||
| Copyright 2013 Robin Gareus <robin@gareus.org> | |||
| Permission to use, copy, modify, and/or distribute this software for any | |||
| purpose with or without fee is hereby granted, provided that the above | |||
| @@ -32,16 +31,6 @@ | |||
| #include "pugl_internal.h" | |||
| /* work around buggy re-parent & focus issues on some systems | |||
| * where no keyboard events are passed through even if the | |||
| * app has mouse-focus and all other events are working. | |||
| */ | |||
| //#define XKEYFOCUSGRAB | |||
| /* show messages during initalization | |||
| */ | |||
| //#define VERBOSE_PUGL | |||
| struct PuglInternalsImpl { | |||
| Display* display; | |||
| int screen; | |||
| @@ -101,21 +90,15 @@ puglCreate(PuglNativeWindow parent, | |||
| if (!vi) { | |||
| vi = glXChooseVisual(impl->display, impl->screen, attrListSgl); | |||
| impl->doubleBuffered = False; | |||
| #ifdef VERBOSE_PUGL | |||
| printf("puGL: singlebuffered rendering will be used, no doublebuffering available\n"); | |||
| #endif | |||
| PUGL_LOG("No double buffering available\n"); | |||
| } else { | |||
| impl->doubleBuffered = True; | |||
| #ifdef VERBOSE_PUGL | |||
| printf("puGL: doublebuffered rendering available\n"); | |||
| #endif | |||
| PUGL_LOG("Double buffered rendering enabled\n"); | |||
| } | |||
| int glxMajor, glxMinor; | |||
| glXQueryVersion(impl->display, &glxMajor, &glxMinor); | |||
| #ifdef VERBOSE_PUGL | |||
| printf("puGL: GLX-Version %d.%d\n", glxMajor, glxMinor); | |||
| #endif | |||
| PUGL_LOGF("GLX Version %d.%d\n", glxMajor, glxMinor); | |||
| impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE); | |||
| @@ -163,34 +146,14 @@ puglCreate(PuglNativeWindow parent, | |||
| XSetWMProtocols(impl->display, impl->win, &wmDelete, 1); | |||
| } | |||
| #if 0 | |||
| if (true) { // stay on top | |||
| Atom type = XInternAtom(impl->display, "_NET_WM_STATE_ABOVE", False); | |||
| XChangeProperty(impl->display, | |||
| impl->win, | |||
| XInternAtom(impl->display, "_NET_WM_STATE", False), | |||
| XInternAtom(impl->display, "ATOM", False), | |||
| 32, | |||
| PropModeReplace, | |||
| (unsigned char *)&type, | |||
| 1 | |||
| ); | |||
| } | |||
| #endif | |||
| if (visible) { | |||
| XMapRaised(impl->display, impl->win); | |||
| } | |||
| if (glXIsDirect(impl->display, impl->ctx)) { | |||
| #ifdef VERBOSE_PUGL | |||
| printf("puGL: DRI enabled\n"); | |||
| printf("If you have drawing issues, try setting LIBGL_ALWAYS_INDIRECT=1 in your environment.\n" ); | |||
| #endif | |||
| PUGL_LOG("DRI enabled (to disable, set LIBGL_ALWAYS_INDIRECT=1\n"); | |||
| } else { | |||
| #ifdef VERBOSE_PUGL | |||
| printf("puGL: No DRI available\n"); | |||
| #endif | |||
| PUGL_LOG("No DRI available\n"); | |||
| } | |||
| XFree(vi); | |||
| @@ -376,7 +339,7 @@ puglProcessEvents(PuglView* view) | |||
| case KeyPress: | |||
| setModifiers(view, event.xkey.state, event.xkey.time); | |||
| dispatchKey(view, &event, true); | |||
| break; | |||
| break; | |||
| case KeyRelease: | |||
| setModifiers(view, event.xkey.state, event.xkey.time); | |||
| if (view->ignoreKeyRepeat && | |||
| @@ -391,7 +354,7 @@ puglProcessEvents(PuglView* view) | |||
| } | |||
| } | |||
| dispatchKey(view, &event, false); | |||
| break; | |||
| break; | |||
| case ClientMessage: | |||
| if (!strcmp(XGetAtomName(view->impl->display, | |||
| event.xclient.message_type), | |||
| @@ -401,9 +364,12 @@ puglProcessEvents(PuglView* view) | |||
| } | |||
| } | |||
| break; | |||
| #ifdef XKEYFOCUSGRAB | |||
| #ifdef PUGL_GRAB_FOCUS | |||
| case EnterNotify: | |||
| XSetInputFocus(view->impl->display, view->impl->win, RevertToPointerRoot, CurrentTime); | |||
| XSetInputFocus(view->impl->display, | |||
| view->impl->win, | |||
| RevertToPointerRoot, | |||
| CurrentTime); | |||
| break; | |||
| #endif | |||
| default: | |||