diff --git a/source/libs/distrho/dgl/Window.hpp b/source/libs/distrho/dgl/Window.hpp index 73f5b5a12..f1e302dc3 100644 --- a/source/libs/distrho/dgl/Window.hpp +++ b/source/libs/distrho/dgl/Window.hpp @@ -61,10 +61,6 @@ public: setVisible(false); } -#if DISTRHO_OS_WINDOWS - Rectangle getBounds(); -#endif - private: class Private; Private* const kPrivate; diff --git a/source/libs/distrho/dgl/src/ImageAboutWindow.cpp b/source/libs/distrho/dgl/src/ImageAboutWindow.cpp index 8c80fcaa0..92dbb9a6a 100644 --- a/source/libs/distrho/dgl/src/ImageAboutWindow.cpp +++ b/source/libs/distrho/dgl/src/ImageAboutWindow.cpp @@ -27,13 +27,12 @@ ImageAboutWindow::ImageAboutWindow(App* app, Window* parent, const Image& image) { #if DISTRHO_OS_WINDOWS // FIXME - Window::setSize(image.getWidth()+1, image.getHeight()+1); + Window::setSize(image.getWidth(), image.getHeight()+1); #else Window::setSize(image.getWidth(), image.getHeight()); #endif Window::setWindowTitle("About"); - Window::show(); } void ImageAboutWindow::onDisplay() diff --git a/source/libs/distrho/dgl/src/Widget.cpp b/source/libs/distrho/dgl/src/Widget.cpp index 1891c9cf4..49c9c7652 100644 --- a/source/libs/distrho/dgl/src/Widget.cpp +++ b/source/libs/distrho/dgl/src/Widget.cpp @@ -214,19 +214,10 @@ void Widget::onReshape(int width, int height) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glMatrixMode(GL_PROJECTION); glLoadIdentity(); - -#if DISTRHO_OS_WINDOWS - Rectangle r(fParent->getBounds()); - glOrtho(r.getX(), r.getWidth(), r.getHeight(), r.getY(), -1.0f, 1.0f); - glViewport(0, 0, r.getWidth() - r.getX(), r.getHeight() - r.getY()); -#else glOrtho(0, width, height, 0, 0.0f, 1.0f); glViewport(0, 0, width, height); -#endif - glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } diff --git a/source/libs/distrho/dgl/src/Window.cpp b/source/libs/distrho/dgl/src/Window.cpp index abb0c215a..b59ff7bd5 100644 --- a/source/libs/distrho/dgl/src/Window.cpp +++ b/source/libs/distrho/dgl/src/Window.cpp @@ -53,6 +53,7 @@ public: fChildFocus(nullptr), fVisible(false), fClosed(false), + fResizable(false), #if DISTRHO_OS_WINDOWS hwnd(0) #elif DISTRHO_OS_LINUX @@ -85,7 +86,6 @@ public: #if DISTRHO_OS_WINDOWS hwnd = impl->hwnd; - #elif DISTRHO_OS_LINUX xDisplay = impl->display; xWindow = impl->win; @@ -116,17 +116,32 @@ public: void exec() { fClosed = false; - show(); if (fParent != nullptr) { + fParent->fChildFocus = this; + #if DISTRHO_OS_WINDOWS - EnableWindow(fParent->hwnd, FALSE); + // Center this window + PuglInternals* parentImpl = fParent->kView->impl; + + RECT curRect; + RECT parentRect; + GetWindowRect(hwnd, &curRect); + GetWindowRect(parentImpl->hwnd, &parentRect); + + int x = parentRect.left+(parentRect.right-curRect.right)/2; + int y = parentRect.top+(parentRect.bottom-curRect.bottom)/2; + + SetWindowPos(hwnd, 0, x, y, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER); + UpdateWindow(hwnd); #endif - fParent->fChildFocus = this; + fParent->show(); } + show(); + while (isVisible() && ! fClosed) { idle(); @@ -142,9 +157,6 @@ public: if (fParent != nullptr) { fParent->fChildFocus = nullptr; -#if DISTRHO_OS_WINDOWS - EnableWindow(fParent->hwnd, TRUE); -#endif } } @@ -224,14 +236,15 @@ public: void setSize(unsigned int width, unsigned int height) { #if DISTRHO_OS_WINDOWS - RECT rcClient; - RECT rcWindow; - POINT ptDiff; - GetClientRect(hwnd, &rcClient); - GetWindowRect(hwnd, &rcWindow); - ptDiff.x = (rcWindow.right - rcWindow.left) - rcClient.right; - ptDiff.y = (rcWindow.bottom - rcWindow.top) - rcClient.bottom; - SetWindowPos(hwnd, 0, 0, 0, width + ptDiff.x, height + ptDiff.y, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); + int winFlags = WS_POPUPWINDOW | WS_CAPTION; + + if (fResizable) + winFlags |= WS_SIZEBOX; + + RECT wr = { 0, 0, (long)width, (long)height }; + AdjustWindowRectEx(&wr, winFlags, FALSE, WS_EX_TOPMOST); + + SetWindowPos(hwnd, 0, 0, 0, wr.right-wr.left, wr.bottom-wr.top, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); UpdateWindow(hwnd); #elif DISTRHO_OS_LINUX XSizeHints sizeHints; @@ -284,16 +297,6 @@ public: fWidgets.remove(widget); } -#if DISTRHO_OS_WINDOWS - Rectangle getBounds() - { - RECT rcClient; - GetClientRect(hwnd, &rcClient); - - return Rectangle(rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); - } -#endif - protected: void onDisplay() { @@ -422,6 +425,7 @@ private: Private* fChildFocus; bool fVisible; bool fClosed; + bool fResizable; std::list fWidgets; @@ -563,13 +567,6 @@ void Window::removeWidget(Widget* widget) kPrivate->removeWidget(widget); } -#if DISTRHO_OS_WINDOWS -Rectangle Window::getBounds() -{ - return kPrivate->getBounds(); -} -#endif - // ------------------------------------------------- END_NAMESPACE_DISTRHO diff --git a/source/libs/distrho/dgl/src/pugl/pugl.h b/source/libs/distrho/dgl/src/pugl/pugl.h index 4c4366fa1..2a11ad3ed 100644 --- a/source/libs/distrho/dgl/src/pugl/pugl.h +++ b/source/libs/distrho/dgl/src/pugl/pugl.h @@ -54,7 +54,9 @@ # define PUGL_API #endif -#ifndef __cplusplus +#ifdef __cplusplus +extern "C" { +#else # include #endif @@ -224,8 +226,7 @@ puglCreate(PuglNativeWindow parent, int width, int height, bool resizable, - bool addToDesktop = true, - const char* x11Display = nullptr); + bool addToDesktop = true); /** Set the handle to be passed to all callbacks. @@ -245,6 +246,12 @@ puglSetHandle(PuglView* view, PuglHandle handle); PUGL_API PuglHandle puglGetHandle(PuglView* view); +/** + Return the timestamp (if any) of the currently-processing event. +*/ +PUGL_API uint32_t +puglGetEventTimestamp(PuglView* view); + /** Get the currently active modifiers (PuglMod flags). @@ -338,4 +345,8 @@ puglDestroy(PuglView* view); @} */ +#ifdef __cplusplus +} /* extern "C" */ +#endif + #endif /* PUGL_H_INCLUDED */ diff --git a/source/libs/distrho/dgl/src/pugl/pugl_internal.h b/source/libs/distrho/dgl/src/pugl/pugl_internal.h index a94b6cc95..8cdada87f 100644 --- a/source/libs/distrho/dgl/src/pugl/pugl_internal.h +++ b/source/libs/distrho/dgl/src/pugl/pugl_internal.h @@ -39,11 +39,13 @@ struct PuglViewImpl { PuglInternals* impl; - int width; - int height; - int mods; - bool ignoreKeyRepeat; - bool redisplay; + int width; + int height; + int mods; + bool mouse_in_view; + bool ignoreKeyRepeat; + bool redisplay; + uint32_t event_timestamp_ms; }; void @@ -58,13 +60,19 @@ puglGetHandle(PuglView* view) return view->handle; } +uint32_t +puglGetEventTimestamp(PuglView* view) +{ + return view->event_timestamp_ms; +} + int puglGetModifiers(PuglView* view) { return view->mods; } -static inline void +void puglDefaultReshape(PuglView* view, int width, int height) { glMatrixMode(GL_PROJECTION); diff --git a/source/libs/distrho/dgl/src/pugl/pugl_osx.m b/source/libs/distrho/dgl/src/pugl/pugl_osx.m index 7b1c17588..29cc122b0 100644 --- a/source/libs/distrho/dgl/src/pugl/pugl_osx.m +++ b/source/libs/distrho/dgl/src/pugl/pugl_osx.m @@ -24,12 +24,64 @@ #include "pugl_internal.h" +@interface PuglWindow : NSWindow +{ +@public + PuglView* puglview; +} + +- (id) initWithContentRect:(NSRect)contentRect + styleMask:(unsigned int)aStyle + backing:(NSBackingStoreType)bufferingType + defer:(BOOL)flag; +- (void) setPuglview:(PuglView*)view; +- (BOOL) windowShouldClose:(id)sender; +- (void) becomeKeyWindow:(id)sender; +- (BOOL) canBecomeKeyWindow:(id)sender; +@end + +@implementation PuglWindow + +- (id)initWithContentRect:(NSRect)contentRect + styleMask:(unsigned int)aStyle + backing:(NSBackingStoreType)bufferingType + defer:(BOOL)flag +{ + NSWindow* result = [super initWithContentRect:contentRect + styleMask:(NSClosableWindowMask | + NSTitledWindowMask | + NSResizableWindowMask) + backing:NSBackingStoreBuffered defer:NO]; + + [result setAcceptsMouseMovedEvents:YES]; + [result setLevel: CGShieldingWindowLevel() + 1]; + + return result; +} + +- (void)setPuglview:(PuglView*)view +{ + puglview = view; + [self setContentSize:NSMakeSize(view->width, view->height) ]; +} + +- (BOOL)windowShouldClose:(id)sender +{ + if (puglview->closeFunc) + puglview->closeFunc(puglview); + return YES; +} + +@end + @interface PuglOpenGLView : NSOpenGLView { int colorBits; int depthBits; @public - PuglView* view; + PuglView* puglview; + + NSTrackingArea* trackingArea; } - (id) initWithFrame:(NSRect)frame @@ -38,6 +90,7 @@ - (void) reshape; - (void) drawRect:(NSRect)rect; - (void) mouseMoved:(NSEvent*)event; +- (void) mouseDragged:(NSEvent*)event; - (void) mouseDown:(NSEvent*)event; - (void) mouseUp:(NSEvent*)event; - (void) rightMouseDown:(NSEvent*)event; @@ -92,33 +145,37 @@ int width = bounds.size.width; int height = bounds.size.height; - if (view->reshapeFunc) { - view->reshapeFunc(view, width, height); - } else { - puglDefaultReshape(view, width, height); - } + if (puglview) { + /* NOTE: Apparently reshape gets called when the GC gets around to + deleting the view (?), so we must have reset puglview to NULL when + this comes around. + */ + if (puglview->reshapeFunc) { + puglview->reshapeFunc(puglview, width, height); + } else { + puglDefaultReshape(puglview, width, height); + } - view->width = width; - view->height = height; + puglview->width = width; + puglview->height = height; + } } - (void) drawRect:(NSRect)rect { - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glLoadIdentity(); - - if (self->view->displayFunc) { - self->view->displayFunc(self->view); - } - + puglDisplay(puglview); glFlush(); glSwapAPPLE(); } -static int -getModifiers(unsigned modifierFlags) +static unsigned +getModifiers(PuglView* view, NSevent* ev) { - int mods = 0; + const unsigned modifierFlags = [ev modifierFlags] + + view->event_timestamp_ms = fmod([ev timestamp] * 1000.0, UINT32_MAX); + + unsigned mods = 0; mods |= (modifierFlags & NSShiftKeyMask) ? PUGL_MOD_SHIFT : 0; mods |= (modifierFlags & NSControlKeyMask) ? PUGL_MOD_CTRL : 0; mods |= (modifierFlags & NSAlternateKeyMask) ? PUGL_MOD_ALT : 0; @@ -126,99 +183,135 @@ getModifiers(unsigned modifierFlags) return mods; } +-(void)updateTrackingAreas +{ + if (trackingArea != nil) { + [self removeTrackingArea:trackingArea]; + [trackingArea release]; + } + + const int opts = (NSTrackingMouseEnteredAndExited | + NSTrackingMouseMoved | + NSTrackingActiveAlways); + trackingArea = [ [NSTrackingArea alloc] initWithRect:[self bounds] + options:opts + owner:self + userInfo:nil]; + [self addTrackingArea:trackingArea]; +} + +- (void)mouseEntered:(NSEvent*)theEvent +{ + [self updateTrackingAreas]; +} + +- (void)mouseExited:(NSEvent*)theEvent +{ +} + - (void) mouseMoved:(NSEvent*)event { - if (view->motionFunc) { + if (puglview->motionFunc) { NSPoint loc = [event locationInWindow]; - view->mods = getModifiers([event modifierFlags]); - view->motionFunc(view, loc.x, loc.y); + puglview->mods = getModifiers(puglview, event); + puglview->motionFunc(puglview, loc.x, puglview->height - loc.y); + } +} + +- (void) mouseDragged:(NSEvent*)event +{ + if (puglview->motionFunc) { + NSPoint loc = [event locationInWindow]; + puglview->mods = getModifiers(puglview, event); + puglview->motionFunc(puglview, loc.x, puglview->height - loc.y); } } - (void) mouseDown:(NSEvent*)event { - if (view->mouseFunc) { + if (puglview->mouseFunc) { NSPoint loc = [event locationInWindow]; - view->mods = getModifiers([event modifierFlags]); - view->mouseFunc(view, 1, true, loc.x, loc.y); + puglview->mods = getModifiers(puglview, event); + puglview->mouseFunc(puglview, 1, true, loc.x, puglview->height - loc.y); } } - (void) mouseUp:(NSEvent*)event { - if (view->mouseFunc) { + if (puglview->mouseFunc) { NSPoint loc = [event locationInWindow]; - view->mods = getModifiers([event modifierFlags]); - view->mouseFunc(view, 1, false, loc.x, loc.y); + puglview->mods = getModifiers(puglview, event); + puglview->mouseFunc(puglview, 1, false, loc.x, puglview->height - loc.y); } + [self updateTrackingAreas]; } - (void) rightMouseDown:(NSEvent*)event { - if (view->mouseFunc) { + if (puglview->mouseFunc) { NSPoint loc = [event locationInWindow]; - view->mods = getModifiers([event modifierFlags]); - view->mouseFunc(view, 3, true, loc.x, loc.y); + puglview->mods = getModifiers(puglview, event); + puglview->mouseFunc(puglview, 3, true, loc.x, puglview->height - loc.y); } } - (void) rightMouseUp:(NSEvent*)event { - if (view->mouseFunc) { + if (puglview->mouseFunc) { NSPoint loc = [event locationInWindow]; - view->mods = getModifiers([event modifierFlags]); - view->mouseFunc(view, 3, false, loc.x, loc.y); + puglview->mods = getModifiers(puglview, event); + puglview->mouseFunc(puglview, 3, false, loc.x, puglview->height - loc.y); } } - (void) scrollWheel:(NSEvent*)event { - if (view->scrollFunc) { - view->mods = getModifiers([event modifierFlags]); - view->scrollFunc(view, [event deltaX], [event deltaY]); + if (puglview->scrollFunc) { + puglview->mods = getModifiers(puglview, event); + puglview->scrollFunc(puglview, [event deltaX], [event deltaY]); } + [self updateTrackingAreas]; } - (void) keyDown:(NSEvent*)event { - if (view->keyboardFunc && !(view->ignoreKeyRepeat && [event isARepeat])) { + if (puglview->keyboardFunc && !(puglview->ignoreKeyRepeat && [event isARepeat])) { NSString* chars = [event characters]; - view->mods = getModifiers([event modifierFlags]); - view->keyboardFunc(view, true, [chars characterAtIndex:0]); + puglview->mods = getModifiers(puglview, event); + puglview->keyboardFunc(puglview, true, [chars characterAtIndex:0]); } } - (void) keyUp:(NSEvent*)event { - if (view->keyboardFunc) { + if (puglview->keyboardFunc) { NSString* chars = [event characters]; - view->mods = getModifiers([event modifierFlags]); - view->keyboardFunc(view, false, [chars characterAtIndex:0]); + puglview->mods = getModifiers(puglview, event); + puglview->keyboardFunc(puglview, false, [chars characterAtIndex:0]); } } - (void) flagsChanged:(NSEvent*)event { - if (view->specialFunc) { - int mods = getModifiers([event modifierFlags]); - if ((mods & PUGL_MOD_SHIFT) != (view->mods & PUGL_MOD_SHIFT)) { - view->specialFunc(view, mods & PUGL_MOD_SHIFT, PUGL_KEY_SHIFT); - } else if ((mods & PUGL_MOD_CTRL) != (view->mods & PUGL_MOD_CTRL)) { - view->specialFunc(view, mods & PUGL_MOD_CTRL, PUGL_KEY_CTRL); - } else if ((mods & PUGL_MOD_ALT) != (view->mods & PUGL_MOD_ALT)) { - view->specialFunc(view, mods & PUGL_MOD_ALT, PUGL_KEY_ALT); - } else if ((mods & PUGL_MOD_SUPER) != (view->mods & PUGL_MOD_SUPER)) { - view->specialFunc(view, mods & PUGL_MOD_SUPER, PUGL_KEY_SUPER); + if (puglview->specialFunc) { + const unsigned mods = getModifiers(puglview, [event modifierFlags]); + if ((mods & PUGL_MOD_SHIFT) != (puglview->mods & PUGL_MOD_SHIFT)) { + puglview->specialFunc(puglview, mods & PUGL_MOD_SHIFT, PUGL_KEY_SHIFT); + } else if ((mods & PUGL_MOD_CTRL) != (puglview->mods & PUGL_MOD_CTRL)) { + puglview->specialFunc(puglview, mods & PUGL_MOD_CTRL, PUGL_KEY_CTRL); + } else if ((mods & PUGL_MOD_ALT) != (puglview->mods & PUGL_MOD_ALT)) { + puglview->specialFunc(puglview, mods & PUGL_MOD_ALT, PUGL_KEY_ALT); + } else if ((mods & PUGL_MOD_SUPER) != (puglview->mods & PUGL_MOD_SUPER)) { + puglview->specialFunc(puglview, mods & PUGL_MOD_SUPER, PUGL_KEY_SUPER); } - view->mods = mods; + puglview->mods = mods; } } @end struct PuglInternalsImpl { - PuglOpenGLView* view; - NSModalSession session; + PuglOpenGLView* glview; id window; }; @@ -228,8 +321,7 @@ puglCreate(PuglNativeWindow parent, int width, int height, bool resizable, - bool addToDesktop, - const char* x11Display) + bool addToDesktop) { PuglView* view = (PuglView*)calloc(1, sizeof(PuglView)); PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); @@ -243,46 +335,37 @@ puglCreate(PuglNativeWindow parent, [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]; + id window = [[PuglWindow new]retain]; - [window cascadeTopLeftFromPoint:NSMakePoint(20, 20)]; + [window setPuglview:view]; [window setTitle:titleString]; - [window setAcceptsMouseMovedEvents:YES]; - impl->view = [PuglOpenGLView new]; + impl->glview = [PuglOpenGLView new]; impl->window = window; - impl->view->view = view; + impl->glview->puglview = view; - [window setContentView:impl->view]; + [window setContentView:impl->glview]; [NSApp activateIgnoringOtherApps:YES]; - [window makeFirstResponder:impl->view]; + [window makeFirstResponder:impl->glview]; - impl->session = [NSApp beginModalSessionForWindow:view->impl->window]; + [window makeKeyAndOrderFront:window]; return view; - - // unused - (void)addToDesktop; - (void)x11Display; } void puglDestroy(PuglView* view) { - [NSApp endModalSession:view->impl->session]; - [view->impl->view release]; + view->impl->glview->puglview = NULL; + [view->impl->window close]; + [view->impl->glview release]; + [view->impl->window release]; free(view->impl); free(view); } @@ -290,30 +373,15 @@ puglDestroy(PuglView* view) void puglDisplay(PuglView* view) { - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glLoadIdentity(); - if (view->displayFunc) { view->displayFunc(view); } - - glFlush(); - view->redisplay = false; } PuglStatus puglProcessEvents(PuglView* view) { - NSInteger response = [NSApp runModalSession:view->impl->session]; - if (response != NSRunContinuesResponse) { - if (view->closeFunc) { - view->closeFunc(view); - } - } - - if (view->redisplay) { - puglDisplay(view); - } + [view->impl->glview setNeedsDisplay: YES]; return PUGL_SUCCESS; } @@ -327,5 +395,5 @@ puglPostRedisplay(PuglView* view) PuglNativeWindow puglGetNativeWindow(PuglView* view) { - return (PuglNativeWindow)view->impl->view; + return (PuglNativeWindow)view->impl->glview; } diff --git a/source/libs/distrho/dgl/src/pugl/pugl_win.cpp b/source/libs/distrho/dgl/src/pugl/pugl_win.cpp index d39efa886..444a60283 100644 --- a/source/libs/distrho/dgl/src/pugl/pugl_win.cpp +++ b/source/libs/distrho/dgl/src/pugl/pugl_win.cpp @@ -22,6 +22,9 @@ #include #include +#include +#include + #include "pugl_internal.h" #ifndef WM_MOUSEWHEEL @@ -30,11 +33,17 @@ #ifndef WM_MOUSEHWHEEL # define WM_MOUSEHWHEEL 0x020E #endif +#ifndef WHEEL_DELTA +# define WHEEL_DELTA 120 +#endif + +const int LOCAL_CLOSE_MSG = WM_USER + 50; struct PuglInternalsImpl { - HWND hwnd; - HDC hdc; - HGLRC hglrc; + HWND hwnd; + HDC hdc; + HGLRC hglrc; + WNDCLASS wc; }; LRESULT CALLBACK @@ -46,8 +55,7 @@ puglCreate(PuglNativeWindow parent, int width, int height, bool resizable, - bool addToDesktop, - const char* x11Display) + bool addToDesktop) { PuglView* view = (PuglView*)calloc(1, sizeof(PuglView)); PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); @@ -59,30 +67,47 @@ puglCreate(PuglNativeWindow parent, view->width = width; view->height = height; - WNDCLASS wc; - wc.style = CS_OWNDC; - wc.lpfnWndProc = wndProc; - 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, - (addToDesktop ? WS_VISIBLE : 0) | (parent ? WS_CHILD : (WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX)), - CW_USEDEFAULT, CW_USEDEFAULT, width, height, + // FIXME: This is nasty, and pugl should not have static anything. + // Should class be a parameter? Does this make sense on other platforms? + static int wc_count = 0; + char classNameBuf[256]; + _snprintf(classNameBuf, sizeof(classNameBuf), "%s_%d\n", title, wc_count++); + + impl->wc.style = CS_OWNDC; + impl->wc.lpfnWndProc = wndProc; + impl->wc.cbClsExtra = 0; + impl->wc.cbWndExtra = 0; + impl->wc.hInstance = 0; + impl->wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); + impl->wc.hCursor = LoadCursor(NULL, IDC_ARROW); + impl->wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + impl->wc.lpszMenuName = NULL; + impl->wc.lpszClassName = classNameBuf; + RegisterClass(&impl->wc); + + int winFlags = WS_POPUPWINDOW | WS_CAPTION; + if (resizable) { + winFlags |= WS_SIZEBOX; + } + + // Adjust the overall window size to accomodate our requested client size + RECT wr = { 0, 0, width, height }; + AdjustWindowRectEx( + &wr, winFlags, FALSE, WS_EX_TOPMOST); + + impl->hwnd = CreateWindowEx( + WS_EX_TOPMOST, + classNameBuf, title, + (addToDesktop ? WS_VISIBLE : 0) | (parent ? WS_CHILD : winFlags), + 0, 0, wr.right-wr.left, wr.bottom-wr.top, (HWND)parent, NULL, NULL, NULL); + if (!impl->hwnd) { free(impl); free(view); return NULL; } - + SetWindowLongPtr(impl->hwnd, GWL_USERDATA, (LONG)view); impl->hdc = GetDC(impl->hwnd); @@ -107,10 +132,6 @@ puglCreate(PuglNativeWindow parent, view->height = height; return view; - - // unused - (void)resizable; - (void)x11Display; } void @@ -120,11 +141,12 @@ puglDestroy(PuglView* view) wglDeleteContext(view->impl->hglrc); ReleaseDC(view->impl->hwnd, view->impl->hdc); DestroyWindow(view->impl->hwnd); + UnregisterClass(view->impl->wc.lpszClassName, NULL); free(view->impl); free(view); } -void +static void puglReshape(PuglView* view, int width, int height) { wglMakeCurrent(view->impl->hdc, view->impl->hglrc); @@ -192,6 +214,13 @@ keySymToSpecial(int sym) static void processMouseEvent(PuglView* view, int button, bool press, LPARAM lParam) { + view->event_timestamp_ms = GetMessageTime(); + if (press) { + SetCapture(view->impl->hwnd); + } else { + ReleaseCapture(); + } + if (view->mouseFunc) { view->mouseFunc(view, button, press, GET_X_LPARAM(lParam), @@ -221,7 +250,11 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) case WM_CREATE: case WM_SHOWWINDOW: case WM_SIZE: - puglReshape(view, view->width, view->height); + RECT rect; + GetClientRect(view->impl->hwnd, &rect); + puglReshape(view, rect.right, rect.bottom); + view->width = rect.right; + view->height = rect.bottom; break; case WM_PAINT: BeginPaint(view->impl->hwnd, &ps); @@ -230,8 +263,7 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_MOUSEMOVE: if (view->motionFunc) { - view->motionFunc( - view, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); + view->motionFunc(view, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); } break; case WM_LBUTTONDOWN: @@ -265,6 +297,7 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) } break; case WM_KEYDOWN: + view->event_timestamp_ms = (GetMessageTime()); if (view->ignoreKeyRepeat && (lParam & (1 << 30))) { break; } // else nobreak @@ -278,6 +311,7 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) } break; case WM_QUIT: + case LOCAL_CLOSE_MSG: if (view->closeFunc) { view->closeFunc(view); } @@ -298,8 +332,9 @@ puglProcessEvents(PuglView* view) handleMessage(view, msg.message, msg.wParam, msg.lParam); } + if (view->redisplay) { - puglDisplay(view); + InvalidateRect(view->impl->hwnd, NULL, FALSE); } return PUGL_SUCCESS; @@ -314,14 +349,10 @@ wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) PostMessage(hwnd, WM_SHOWWINDOW, TRUE, 0); return 0; case WM_CLOSE: - PostQuitMessage(0); + PostMessage(hwnd, LOCAL_CLOSE_MSG, wParam, lParam); return 0; case WM_DESTROY: return 0; - case WM_MOUSEWHEEL: - case WM_MOUSEHWHEEL: - PostMessage(hwnd, message, wParam, lParam); - return 0; default: if (view) { return handleMessage(view, message, wParam, lParam); diff --git a/source/libs/distrho/dgl/src/pugl/pugl_x11.c b/source/libs/distrho/dgl/src/pugl/pugl_x11.c index 759cd8801..f7b682837 100644 --- a/source/libs/distrho/dgl/src/pugl/pugl_x11.c +++ b/source/libs/distrho/dgl/src/pugl/pugl_x11.c @@ -23,9 +23,22 @@ #include #include -#include "pugl_x11.h" +#include +#include +#include +#include +#include + #include "pugl_internal.h" +struct PuglInternalsImpl { + Display* display; + int screen; + Window win; + GLXContext ctx; + Bool doubleBuffered; +}; + /** Attributes for single-buffered RGBA with at least 4 bits per color and a 16 bit depth buffer. @@ -58,20 +71,19 @@ puglCreate(PuglNativeWindow parent, int width, int height, bool resizable, - bool addToDesktop, - const char* x11Display) + bool addToDesktop) { PuglView* view = (PuglView*)calloc(1, sizeof(PuglView)); PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); if (!view || !impl) { - return nullptr; + return NULL; } view->impl = impl; view->width = width; view->height = height; - impl->display = XOpenDisplay(x11Display); + impl->display = XOpenDisplay(0); impl->screen = DefaultScreen(impl->display); XVisualInfo* vi = glXChooseVisual(impl->display, impl->screen, attrListDbl); @@ -88,7 +100,7 @@ puglCreate(PuglNativeWindow parent, glXQueryVersion(impl->display, &glxMajor, &glxMinor); printf("GLX-Version %d.%d\n", glxMajor, glxMinor); - impl->ctx = glXCreateContext(impl->display, vi, nullptr, GL_TRUE); + impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE); Window xParent = parent ? (Window)parent @@ -108,7 +120,7 @@ puglCreate(PuglNativeWindow parent, impl->win = XCreateWindow( impl->display, xParent, - 0, 0, (unsigned int)view->width, (unsigned int)view->height, 0, vi->depth, InputOutput, vi->visual, + 0, 0, view->width, view->height, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask, &attr); XSizeHints sizeHints; @@ -138,7 +150,7 @@ puglCreate(PuglNativeWindow parent, if (glXIsDirect(impl->display, impl->ctx)) { printf("DRI enabled\n"); } else { - printf("no DRI available\n"); + printf("No DRI available\n"); } XFree(vi); @@ -232,8 +244,10 @@ keySymToSpecial(KeySym sym) } static void -setModifiers(PuglView* view, int xstate) +setModifiers(PuglView* view, unsigned xstate, unsigned xtime) { + view->event_timestamp_ms = xtime; + view->mods = 0; view->mods |= (xstate & ShiftMask) ? PUGL_MOD_SHIFT : 0; view->mods |= (xstate & ControlMask) ? PUGL_MOD_CTRL : 0; @@ -264,16 +278,15 @@ puglProcessEvents(PuglView* view) break; } puglDisplay(view); - view->redisplay = false; break; case MotionNotify: - setModifiers(view, (int)event.xmotion.state); + setModifiers(view, event.xmotion.state, event.xmotion.time); if (view->motionFunc) { view->motionFunc(view, event.xmotion.x, event.xmotion.y); } break; case ButtonPress: - setModifiers(view, (int)event.xbutton.state); + setModifiers(view, event.xbutton.state, event.xbutton.time); if (event.xbutton.button >= 4 && event.xbutton.button <= 7) { if (view->scrollFunc) { float dx = 0, dy = 0; @@ -289,23 +302,23 @@ puglProcessEvents(PuglView* view) } // nobreak case ButtonRelease: - setModifiers(view, (int)event.xbutton.state); + setModifiers(view, event.xbutton.state, event.xbutton.time); if (view->mouseFunc && (event.xbutton.button < 4 || event.xbutton.button > 7)) { view->mouseFunc(view, - (int)event.xbutton.button, event.type == ButtonPress, + event.xbutton.button, event.type == ButtonPress, event.xbutton.x, event.xbutton.y); } break; case KeyPress: { - setModifiers(view, (int)event.xkey.state); + setModifiers(view, event.xkey.state, event.xkey.time); KeySym sym; char str[5]; - int n = XLookupString(&event.xkey, str, 4, &sym, nullptr); + int n = XLookupString(&event.xkey, str, 4, &sym, NULL); PuglKey key = keySymToSpecial(sym); if (!key && view->keyboardFunc) { if (n == 1) { - view->keyboardFunc(view, true, (uint32_t)str[0]); + view->keyboardFunc(view, true, str[0]); } else { fprintf(stderr, "warning: Unknown key %X\n", (int)sym); } @@ -314,7 +327,7 @@ puglProcessEvents(PuglView* view) } } break; case KeyRelease: { - setModifiers(view, (int)event.xkey.state); + setModifiers(view, event.xkey.state, event.xkey.time); bool repeated = false; if (view->ignoreKeyRepeat && XEventsQueued(view->impl->display, QueuedAfterReading)) { @@ -330,10 +343,10 @@ puglProcessEvents(PuglView* view) if (!repeated && view->keyboardFunc) { KeySym sym = XKeycodeToKeysym( - view->impl->display, (KeyCode)event.xkey.keycode, 0); + view->impl->display, event.xkey.keycode, 0); PuglKey special = keySymToSpecial(sym); if (!special) { - view->keyboardFunc(view, false, (uint32_t)sym); + view->keyboardFunc(view, false, sym); } else if (view->specialFunc) { view->specialFunc(view, false, special); } @@ -369,11 +382,5 @@ puglPostRedisplay(PuglView* view) PuglNativeWindow puglGetNativeWindow(PuglView* view) { - return static_cast(view->impl->win); -} - -PuglInternals* -puglGetInternalsImpl(PuglView* view) -{ - return view->impl; + return view->impl->win; } diff --git a/source/libs/distrho/dgl/src/pugl/pugl_x11.h b/source/libs/distrho/dgl/src/pugl/pugl_x11.h deleted file mode 100644 index 3d592a792..000000000 --- a/source/libs/distrho/dgl/src/pugl/pugl_x11.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright 2012 David Robillard - Copyright 2011-2012 Ben Loftis, Harrison Consoles - - 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_x11.h X11 Pugl Implementation (PuglInternalsImpl only). -*/ - -#ifndef PUGL_X11_H_INCLUDED -#define PUGL_X11_H_INCLUDED - -#include "pugl.h" - -#include -#include -#include -#include -#include - -struct PuglInternalsImpl { - Display* display; - int screen; - Window win; - GLXContext ctx; - Bool doubleBuffered; -}; - -typedef struct PuglInternalsImpl PuglInternals; - -PuglInternals* -puglGetInternalsImpl(PuglView* view); - -#endif /* PUGL_X11_H_INCLUDED */ diff --git a/source/libs/pugl/pugl.h b/source/libs/pugl/pugl.h deleted file mode 100644 index 4c4366fa1..000000000 --- a/source/libs/pugl/pugl.h +++ /dev/null @@ -1,341 +0,0 @@ -/* - Copyright 2012 David Robillard - - 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.h API for Pugl, a minimal portable API for OpenGL. -*/ - -#ifndef PUGL_H_INCLUDED -#define PUGL_H_INCLUDED - -#include - -/* - 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" -#else -# ifdef _WIN32 -# include /* Broken Windows GL headers require this */ -# endif -# include "GL/gl.h" -#endif - -#ifdef PUGL_SHARED -# ifdef _WIN32 -# define PUGL_LIB_IMPORT __declspec(dllimport) -# define PUGL_LIB_EXPORT __declspec(dllexport) -# else -# define PUGL_LIB_IMPORT __attribute__((visibility("default"))) -# define PUGL_LIB_EXPORT __attribute__((visibility("default"))) -# endif -# ifdef PUGL_INTERNAL -# define PUGL_API PUGL_LIB_EXPORT -# else -# define PUGL_API PUGL_LIB_IMPORT -# endif -#else -# define PUGL_API -#endif - -#ifndef __cplusplus -# include -#endif - -/** - @defgroup pugl Pugl - A minimal portable API for OpenGL. - @{ -*/ - -/** - An OpenGL view. -*/ -typedef struct PuglViewImpl PuglView; - -/** - A native window handle. - - On X11, this is a Window. - On OSX, this is an NSView*. - On Windows, this is a HWND. -*/ -typedef intptr_t PuglNativeWindow; - -/** - Return status code. -*/ -typedef enum { - PUGL_SUCCESS = 0 -} PuglStatus; - -/** - Convenience symbols for ASCII control characters. -*/ -typedef enum { - PUGL_CHAR_BACKSPACE = 0x08, - PUGL_CHAR_ESCAPE = 0x1B, - PUGL_CHAR_DELETE = 0x7F -} PuglChar; - -/** - Special (non-Unicode) keyboard keys. -*/ -typedef enum { - PUGL_KEY_F1 = 1, - PUGL_KEY_F2, - PUGL_KEY_F3, - PUGL_KEY_F4, - PUGL_KEY_F5, - PUGL_KEY_F6, - PUGL_KEY_F7, - PUGL_KEY_F8, - PUGL_KEY_F9, - PUGL_KEY_F10, - PUGL_KEY_F11, - PUGL_KEY_F12, - PUGL_KEY_LEFT, - PUGL_KEY_UP, - PUGL_KEY_RIGHT, - PUGL_KEY_DOWN, - PUGL_KEY_PAGE_UP, - PUGL_KEY_PAGE_DOWN, - PUGL_KEY_HOME, - PUGL_KEY_END, - PUGL_KEY_INSERT, - PUGL_KEY_SHIFT, - PUGL_KEY_CTRL, - PUGL_KEY_ALT, - PUGL_KEY_SUPER -} PuglKey; - -/** - Keyboard modifier flags. -*/ -typedef enum { - PUGL_MOD_SHIFT = 1, /**< Shift key */ - PUGL_MOD_CTRL = 1 << 1, /**< Control key */ - PUGL_MOD_ALT = 1 << 2, /**< Alt/Option key */ - PUGL_MOD_SUPER = 1 << 3 /**< Mod4/Command/Windows key */ -} PuglMod; - -/** - Handle for opaque user data. -*/ -typedef void* PuglHandle; - -/** - A function called when the window is closed. -*/ -typedef void (*PuglCloseFunc)(PuglView* view); - -/** - A function called to draw the view contents with OpenGL. -*/ -typedef void (*PuglDisplayFunc)(PuglView* view); - -/** - A function called when a key is pressed or released. - @param view The view the event occured in. - @param press True if the key was pressed, false if released. - @param key Unicode point of the key pressed. -*/ -typedef void (*PuglKeyboardFunc)(PuglView* view, bool press, uint32_t key); - -/** - A function called when the pointer moves. - @param view The view the event occured in. - @param x The window-relative x coordinate of the pointer. - @param y The window-relative y coordinate of the pointer. -*/ -typedef void (*PuglMotionFunc)(PuglView* view, int x, int y); - -/** - A function called when a mouse button is pressed or released. - @param view The view the event occured in. - @param button The button number (1 = left, 2 = middle, 3 = right). - @param press True if the key was pressed, false if released. - @param x The window-relative x coordinate of the pointer. - @param y The window-relative y coordinate of the pointer. -*/ -typedef void (*PuglMouseFunc)( - PuglView* view, int button, bool press, int x, int y); - -/** - A function called when the view is resized. - @param view The view being resized. - @param width The new view width. - @param height The new view height. -*/ -typedef void (*PuglReshapeFunc)(PuglView* view, int width, int height); - -/** - A function called on scrolling (e.g. mouse wheel or track pad). - - The distances used here are in "lines", a single tick of a clicking mouse - wheel. For example, @p dy = 1.0 scrolls 1 line up. Some systems and - devices support finer resolution and/or higher values for fast scrolls, - so programs should handle any value gracefully. - - @param view The view being scrolled. - @param dx The scroll x distance. - @param dx The scroll y distance. -*/ -typedef void (*PuglScrollFunc)(PuglView* view, float dx, float dy); - -/** - A function called when a special key is pressed or released. - - This callback allows the use of keys that do not have unicode points. Note - that some non-printable keys - @param view The view the event occured in. - @param press True if the key was pressed, false if released. - @param key The key pressed. -*/ -typedef void (*PuglSpecialFunc)(PuglView* view, bool press, PuglKey key); - -/** - Create a new GL window. - @param parent Parent window, or 0 for top level. - @param title Window title, or NULL. - @param width Window width in pixels. - @param height Window height in pixels. - @param resizable Whether window should be user resizable. -*/ -PUGL_API PuglView* -puglCreate(PuglNativeWindow parent, - const char* title, - int width, - int height, - bool resizable, - bool addToDesktop = true, - const char* x11Display = nullptr); - -/** - Set the handle to be passed to all callbacks. - - This is generally a pointer to a struct which contains all necessary state. - Everything needed in callbacks should be here, not in static variables. - - Note the lack of this facility makes GLUT unsuitable for plugins or - non-trivial programs; this mistake is largely why Pugl exists. -*/ -PUGL_API void -puglSetHandle(PuglView* view, PuglHandle handle); - -/** - Get the handle to be passed to all callbacks. -*/ -PUGL_API PuglHandle -puglGetHandle(PuglView* view); - -/** - Get the currently active modifiers (PuglMod flags). - - This should only be called from an event handler. -*/ -PUGL_API int -puglGetModifiers(PuglView* view); - -/** - Ignore synthetic repeated key events. -*/ -PUGL_API void -puglIgnoreKeyRepeat(PuglView* view, bool ignore); - -/** - Set the function to call when the window is closed. -*/ -PUGL_API void -puglSetCloseFunc(PuglView* view, PuglCloseFunc closeFunc); - -/** - Set the display function which should draw the UI using GL. -*/ -PUGL_API void -puglSetDisplayFunc(PuglView* view, PuglDisplayFunc displayFunc); - -/** - Set the function to call on keyboard events. -*/ -PUGL_API void -puglSetKeyboardFunc(PuglView* view, PuglKeyboardFunc keyboardFunc); - -/** - Set the function to call on mouse motion. -*/ -PUGL_API void -puglSetMotionFunc(PuglView* view, PuglMotionFunc motionFunc); - -/** - Set the function to call on mouse button events. -*/ -PUGL_API void -puglSetMouseFunc(PuglView* view, PuglMouseFunc mouseFunc); - -/** - Set the function to call on scroll events. -*/ -PUGL_API void -puglSetScrollFunc(PuglView* view, PuglScrollFunc scrollFunc); - -/** - Set the function to call on special events. -*/ -PUGL_API void -puglSetSpecialFunc(PuglView* view, PuglSpecialFunc specialFunc); - -/** - Set the function to call when the window size changes. -*/ -PUGL_API void -puglSetReshapeFunc(PuglView* view, PuglReshapeFunc reshapeFunc); - -/** - Return the native window handle. -*/ -PUGL_API PuglNativeWindow -puglGetNativeWindow(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. -*/ -PUGL_API PuglStatus -puglProcessEvents(PuglView* view); - -/** - Request a redisplay on the next call to puglProcessEvents(). -*/ -PUGL_API void -puglPostRedisplay(PuglView* view); - -/** - Destroy a GL window. -*/ -PUGL_API void -puglDestroy(PuglView* view); - -/** - @} -*/ - -#endif /* PUGL_H_INCLUDED */ diff --git a/source/libs/pugl/pugl_internal.h b/source/libs/pugl/pugl_internal.h deleted file mode 100644 index a94b6cc95..000000000 --- a/source/libs/pugl/pugl_internal.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - Copyright 2012 David Robillard - - 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_internal.h Private platform-independent definitions. - - 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. -*/ - -#include "pugl.h" - -typedef struct PuglInternalsImpl PuglInternals; - -struct PuglViewImpl { - PuglHandle handle; - PuglCloseFunc closeFunc; - PuglDisplayFunc displayFunc; - PuglKeyboardFunc keyboardFunc; - PuglMotionFunc motionFunc; - PuglMouseFunc mouseFunc; - PuglReshapeFunc reshapeFunc; - PuglScrollFunc scrollFunc; - PuglSpecialFunc specialFunc; - - PuglInternals* impl; - - int width; - int height; - int mods; - bool ignoreKeyRepeat; - bool redisplay; -}; - -void -puglSetHandle(PuglView* view, PuglHandle handle) -{ - view->handle = handle; -} - -PuglHandle -puglGetHandle(PuglView* view) -{ - return view->handle; -} - -int -puglGetModifiers(PuglView* view) -{ - return view->mods; -} - -static inline void -puglDefaultReshape(PuglView* view, int width, int height) -{ - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, width, height, 0, 0, 1); - glViewport(0, 0, width, height); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - return; - - // unused - (void)view; -} - -void -puglIgnoreKeyRepeat(PuglView* view, bool ignore) -{ - view->ignoreKeyRepeat = ignore; -} - -void -puglSetCloseFunc(PuglView* view, PuglCloseFunc closeFunc) -{ - view->closeFunc = closeFunc; -} - -void -puglSetDisplayFunc(PuglView* view, PuglDisplayFunc displayFunc) -{ - view->displayFunc = displayFunc; -} - -void -puglSetKeyboardFunc(PuglView* view, PuglKeyboardFunc keyboardFunc) -{ - view->keyboardFunc = keyboardFunc; -} - -void -puglSetMotionFunc(PuglView* view, PuglMotionFunc motionFunc) -{ - view->motionFunc = motionFunc; -} - -void -puglSetMouseFunc(PuglView* view, PuglMouseFunc mouseFunc) -{ - view->mouseFunc = mouseFunc; -} - -void -puglSetReshapeFunc(PuglView* view, PuglReshapeFunc reshapeFunc) -{ - view->reshapeFunc = reshapeFunc; -} - -void -puglSetScrollFunc(PuglView* view, PuglScrollFunc scrollFunc) -{ - view->scrollFunc = scrollFunc; -} - -void -puglSetSpecialFunc(PuglView* view, PuglSpecialFunc specialFunc) -{ - view->specialFunc = specialFunc; -} diff --git a/source/libs/pugl/pugl_osx.m b/source/libs/pugl/pugl_osx.m deleted file mode 100644 index 7b1c17588..000000000 --- a/source/libs/pugl/pugl_osx.m +++ /dev/null @@ -1,331 +0,0 @@ -/* - Copyright 2012 David Robillard - - 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_osx.m OSX/Cocoa Pugl Implementation. -*/ - -#include - -#import - -#include "pugl_internal.h" - -@interface PuglOpenGLView : NSOpenGLView -{ - int colorBits; - int depthBits; -@public - PuglView* view; -} - -- (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; -- (void) flagsChanged:(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 (view->reshapeFunc) { - view->reshapeFunc(view, width, height); - } else { - puglDefaultReshape(view, width, height); - } - - view->width = width; - view->height = height; -} - -- (void) drawRect:(NSRect)rect -{ - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glLoadIdentity(); - - if (self->view->displayFunc) { - self->view->displayFunc(self->view); - } - - glFlush(); - glSwapAPPLE(); -} - -static int -getModifiers(unsigned modifierFlags) -{ - int mods = 0; - mods |= (modifierFlags & NSShiftKeyMask) ? PUGL_MOD_SHIFT : 0; - mods |= (modifierFlags & NSControlKeyMask) ? PUGL_MOD_CTRL : 0; - mods |= (modifierFlags & NSAlternateKeyMask) ? PUGL_MOD_ALT : 0; - mods |= (modifierFlags & NSCommandKeyMask) ? PUGL_MOD_SUPER : 0; - return mods; -} - -- (void) mouseMoved:(NSEvent*)event -{ - if (view->motionFunc) { - NSPoint loc = [event locationInWindow]; - view->mods = getModifiers([event modifierFlags]); - view->motionFunc(view, loc.x, loc.y); - } -} - -- (void) mouseDown:(NSEvent*)event -{ - if (view->mouseFunc) { - NSPoint loc = [event locationInWindow]; - view->mods = getModifiers([event modifierFlags]); - view->mouseFunc(view, 1, true, loc.x, loc.y); - } -} - -- (void) mouseUp:(NSEvent*)event -{ - if (view->mouseFunc) { - NSPoint loc = [event locationInWindow]; - view->mods = getModifiers([event modifierFlags]); - view->mouseFunc(view, 1, false, loc.x, loc.y); - } -} - -- (void) rightMouseDown:(NSEvent*)event -{ - if (view->mouseFunc) { - NSPoint loc = [event locationInWindow]; - view->mods = getModifiers([event modifierFlags]); - view->mouseFunc(view, 3, true, loc.x, loc.y); - } -} - -- (void) rightMouseUp:(NSEvent*)event -{ - if (view->mouseFunc) { - NSPoint loc = [event locationInWindow]; - view->mods = getModifiers([event modifierFlags]); - view->mouseFunc(view, 3, false, loc.x, loc.y); - } -} - -- (void) scrollWheel:(NSEvent*)event -{ - if (view->scrollFunc) { - view->mods = getModifiers([event modifierFlags]); - view->scrollFunc(view, [event deltaX], [event deltaY]); - } -} - -- (void) keyDown:(NSEvent*)event -{ - if (view->keyboardFunc && !(view->ignoreKeyRepeat && [event isARepeat])) { - NSString* chars = [event characters]; - view->mods = getModifiers([event modifierFlags]); - view->keyboardFunc(view, true, [chars characterAtIndex:0]); - } -} - -- (void) keyUp:(NSEvent*)event -{ - if (view->keyboardFunc) { - NSString* chars = [event characters]; - view->mods = getModifiers([event modifierFlags]); - view->keyboardFunc(view, false, [chars characterAtIndex:0]); - } -} - -- (void) flagsChanged:(NSEvent*)event -{ - if (view->specialFunc) { - int mods = getModifiers([event modifierFlags]); - if ((mods & PUGL_MOD_SHIFT) != (view->mods & PUGL_MOD_SHIFT)) { - view->specialFunc(view, mods & PUGL_MOD_SHIFT, PUGL_KEY_SHIFT); - } else if ((mods & PUGL_MOD_CTRL) != (view->mods & PUGL_MOD_CTRL)) { - view->specialFunc(view, mods & PUGL_MOD_CTRL, PUGL_KEY_CTRL); - } else if ((mods & PUGL_MOD_ALT) != (view->mods & PUGL_MOD_ALT)) { - view->specialFunc(view, mods & PUGL_MOD_ALT, PUGL_KEY_ALT); - } else if ((mods & PUGL_MOD_SUPER) != (view->mods & PUGL_MOD_SUPER)) { - view->specialFunc(view, mods & PUGL_MOD_SUPER, PUGL_KEY_SUPER); - } - view->mods = mods; - } -} - -@end - -struct PuglInternalsImpl { - PuglOpenGLView* view; - NSModalSession session; - id window; -}; - -PuglView* -puglCreate(PuglNativeWindow parent, - const char* title, - int width, - int height, - bool resizable, - bool addToDesktop, - const char* x11Display) -{ - PuglView* view = (PuglView*)calloc(1, sizeof(PuglView)); - PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); - if (!view || !impl) { - return NULL; - } - - view->impl = impl; - view->width = width; - view->height = height; - - [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->view = view; - - [window setContentView:impl->view]; - [NSApp activateIgnoringOtherApps:YES]; - [window makeFirstResponder:impl->view]; - - impl->session = [NSApp beginModalSessionForWindow:view->impl->window]; - - return view; - - // unused - (void)addToDesktop; - (void)x11Display; -} - -void -puglDestroy(PuglView* view) -{ - [NSApp endModalSession:view->impl->session]; - [view->impl->view release]; - free(view->impl); - free(view); -} - -void -puglDisplay(PuglView* view) -{ - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glLoadIdentity(); - - if (view->displayFunc) { - view->displayFunc(view); - } - - glFlush(); - view->redisplay = false; -} - -PuglStatus -puglProcessEvents(PuglView* view) -{ - NSInteger response = [NSApp runModalSession:view->impl->session]; - if (response != NSRunContinuesResponse) { - if (view->closeFunc) { - view->closeFunc(view); - } - } - - if (view->redisplay) { - puglDisplay(view); - } - - return PUGL_SUCCESS; -} - -void -puglPostRedisplay(PuglView* view) -{ - view->redisplay = true; -} - -PuglNativeWindow -puglGetNativeWindow(PuglView* view) -{ - return (PuglNativeWindow)view->impl->view; -} diff --git a/source/libs/pugl/pugl_win.cpp b/source/libs/pugl/pugl_win.cpp deleted file mode 100644 index a5d71912d..000000000 --- a/source/libs/pugl/pugl_win.cpp +++ /dev/null @@ -1,344 +0,0 @@ -/* - Copyright 2012 David Robillard - - 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_win.cpp Windows/WGL Pugl Implementation. -*/ - -#include -#include -#include - -#include "pugl_internal.h" - -#ifndef WM_MOUSEWHEEL -# define WM_MOUSEWHEEL 0x020A -#endif -#ifndef WM_MOUSEHWHEEL -# define WM_MOUSEHWHEEL 0x020E -#endif - -struct PuglInternalsImpl { - HWND hwnd; - HDC hdc; - HGLRC hglrc; -}; - -LRESULT CALLBACK -wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); - -PuglView* -puglCreate(PuglNativeWindow parent, - const char* title, - int width, - int height, - bool resizable, - bool addToDesktop, - const char* x11Display) -{ - PuglView* view = (PuglView*)calloc(1, sizeof(PuglView)); - PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); - if (!view || !impl) { - return NULL; - } - - view->impl = impl; - view->width = width; - view->height = height; - - WNDCLASS wc; - wc.style = CS_OWNDC; - wc.lpfnWndProc = wndProc; - 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, - (addToDesktop ? WS_VISIBLE : 0) | (parent ? WS_CHILD : (WS_POPUPWINDOW | WS_CAPTION)), - 0, 0, width, height, - (HWND)parent, NULL, NULL, NULL); - if (!impl->hwnd) { - free(impl); - free(view); - return NULL; - } - - SetWindowLongPtr(impl->hwnd, GWL_USERDATA, (LONG)view); - - 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); - - view->width = width; - view->height = height; - - return view; - - // unused - (void)resizable; - (void)x11Display; -} - -void -puglDestroy(PuglView* view) -{ - wglMakeCurrent(NULL, NULL); - wglDeleteContext(view->impl->hglrc); - ReleaseDC(view->impl->hwnd, view->impl->hdc); - DestroyWindow(view->impl->hwnd); - free(view->impl); - free(view); -} - -void -puglReshape(PuglView* view, int width, int height) -{ - wglMakeCurrent(view->impl->hdc, view->impl->hglrc); - - if (view->reshapeFunc) { - view->reshapeFunc(view, width, height); - } else { - puglDefaultReshape(view, width, height); - } - - view->width = width; - view->height = height; -} - -void -puglDisplay(PuglView* view) -{ - wglMakeCurrent(view->impl->hdc, view->impl->hglrc); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glLoadIdentity(); - - if (view->displayFunc) { - view->displayFunc(view); - } - - glFlush(); - SwapBuffers(view->impl->hdc); - view->redisplay = false; -} - -static PuglKey -keySymToSpecial(int sym) -{ - switch (sym) { - case VK_F1: return PUGL_KEY_F1; - case VK_F2: return PUGL_KEY_F2; - case VK_F3: return PUGL_KEY_F3; - case VK_F4: return PUGL_KEY_F4; - case VK_F5: return PUGL_KEY_F5; - case VK_F6: return PUGL_KEY_F6; - case VK_F7: return PUGL_KEY_F7; - case VK_F8: return PUGL_KEY_F8; - case VK_F9: return PUGL_KEY_F9; - case VK_F10: return PUGL_KEY_F10; - case VK_F11: return PUGL_KEY_F11; - case VK_F12: return PUGL_KEY_F12; - case VK_LEFT: return PUGL_KEY_LEFT; - case VK_UP: return PUGL_KEY_UP; - case VK_RIGHT: return PUGL_KEY_RIGHT; - case VK_DOWN: return PUGL_KEY_DOWN; - case VK_PRIOR: return PUGL_KEY_PAGE_UP; - case VK_NEXT: return PUGL_KEY_PAGE_DOWN; - case VK_HOME: return PUGL_KEY_HOME; - case VK_END: return PUGL_KEY_END; - case VK_INSERT: return PUGL_KEY_INSERT; - case VK_SHIFT: return PUGL_KEY_SHIFT; - case VK_CONTROL: return PUGL_KEY_CTRL; - case VK_MENU: return PUGL_KEY_ALT; - case VK_LWIN: return PUGL_KEY_SUPER; - case VK_RWIN: return PUGL_KEY_SUPER; - } - return (PuglKey)0; -} - -static void -processMouseEvent(PuglView* view, int button, bool press, LPARAM lParam) -{ - if (view->mouseFunc) { - view->mouseFunc(view, button, press, - GET_X_LPARAM(lParam), - GET_Y_LPARAM(lParam)); - } -} - -static void -setModifiers(PuglView* view) -{ - view->mods = 0; - view->mods |= (GetKeyState(VK_SHIFT) < 0) ? PUGL_MOD_SHIFT : 0; - view->mods |= (GetKeyState(VK_CONTROL) < 0) ? PUGL_MOD_CTRL : 0; - view->mods |= (GetKeyState(VK_MENU) < 0) ? PUGL_MOD_ALT : 0; - view->mods |= (GetKeyState(VK_LWIN) < 0) ? PUGL_MOD_SUPER : 0; - view->mods |= (GetKeyState(VK_RWIN) < 0) ? PUGL_MOD_SUPER : 0; -} - -static LRESULT -handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) -{ - PAINTSTRUCT ps; - PuglKey key; - - setModifiers(view); - switch (message) { - case WM_CREATE: - case WM_SHOWWINDOW: - case WM_SIZE: - puglReshape(view, view->width, view->height); - break; - case WM_PAINT: - BeginPaint(view->impl->hwnd, &ps); - puglDisplay(view); - EndPaint(view->impl->hwnd, &ps); - break; - case WM_MOUSEMOVE: - if (view->motionFunc) { - view->motionFunc( - view, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); - } - break; - case WM_LBUTTONDOWN: - processMouseEvent(view, 1, true, lParam); - break; - case WM_MBUTTONDOWN: - processMouseEvent(view, 2, true, lParam); - break; - case WM_RBUTTONDOWN: - processMouseEvent(view, 3, true, lParam); - break; - case WM_LBUTTONUP: - processMouseEvent(view, 1, false, lParam); - break; - case WM_MBUTTONUP: - processMouseEvent(view, 2, false, lParam); - break; - case WM_RBUTTONUP: - processMouseEvent(view, 3, false, lParam); - break; - case WM_MOUSEWHEEL: - if (view->scrollFunc) { - view->scrollFunc( - view, 0, (int16_t)HIWORD(wParam) / (float)WHEEL_DELTA); - } - break; - case WM_MOUSEHWHEEL: - if (view->scrollFunc) { - view->scrollFunc( - view, (int16_t)HIWORD(wParam) / float(WHEEL_DELTA), 0); - } - break; - case WM_KEYDOWN: - if (view->ignoreKeyRepeat && (lParam & (1 << 30))) { - break; - } // else nobreak - case WM_KEYUP: - if ((key = keySymToSpecial(wParam))) { - if (view->specialFunc) { - view->specialFunc(view, message == WM_KEYDOWN, key); - } - } else if (view->keyboardFunc) { - view->keyboardFunc(view, message == WM_KEYDOWN, wParam); - } - break; - case WM_QUIT: - if (view->closeFunc) { - view->closeFunc(view); - } - break; - default: - return DefWindowProc( - view->impl->hwnd, message, wParam, lParam); - } - - return 0; -} - -PuglStatus -puglProcessEvents(PuglView* view) -{ - MSG msg; - while (PeekMessage(&msg, view->impl->hwnd, 0, 0, PM_REMOVE)) { - handleMessage(view, msg.message, msg.wParam, msg.lParam); - } - - if (view->redisplay) { - puglDisplay(view); - } - - return PUGL_SUCCESS; -} - -LRESULT CALLBACK -wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - PuglView* view = (PuglView*)GetWindowLongPtr(hwnd, GWL_USERDATA); - switch (message) { - case WM_CREATE: - PostMessage(hwnd, WM_SHOWWINDOW, TRUE, 0); - return 0; - case WM_CLOSE: - PostQuitMessage(0); - return 0; - case WM_DESTROY: - return 0; - case WM_MOUSEWHEEL: - case WM_MOUSEHWHEEL: - PostMessage(hwnd, message, wParam, lParam); - return 0; - default: - if (view) { - return handleMessage(view, message, wParam, lParam); - } else { - return DefWindowProc(hwnd, message, wParam, lParam); - } - } -} - -void -puglPostRedisplay(PuglView* view) -{ - view->redisplay = true; -} - -PuglNativeWindow -puglGetNativeWindow(PuglView* view) -{ - return (PuglNativeWindow)view->impl->hwnd; -} diff --git a/source/libs/pugl/pugl_x11.c b/source/libs/pugl/pugl_x11.c deleted file mode 100644 index 759cd8801..000000000 --- a/source/libs/pugl/pugl_x11.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - Copyright 2012 David Robillard - Copyright 2011-2012 Ben Loftis, Harrison Consoles - - 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_x11.c X11 Pugl Implementation. -*/ - -#include -#include -#include - -#include "pugl_x11.h" -#include "pugl_internal.h" - -/** - Attributes for single-buffered RGBA with at least - 4 bits per color and a 16 bit depth buffer. -*/ -static int attrListSgl[] = { - GLX_RGBA, - GLX_RED_SIZE, 4, - GLX_GREEN_SIZE, 4, - GLX_BLUE_SIZE, 4, - GLX_DEPTH_SIZE, 16, - None -}; - -/** - Attributes for double-buffered RGBA with at least - 4 bits per color and a 16 bit depth buffer. -*/ -static int attrListDbl[] = { - GLX_RGBA, GLX_DOUBLEBUFFER, - GLX_RED_SIZE, 4, - GLX_GREEN_SIZE, 4, - GLX_BLUE_SIZE, 4, - GLX_DEPTH_SIZE, 16, - None -}; - -PuglView* -puglCreate(PuglNativeWindow parent, - const char* title, - int width, - int height, - bool resizable, - bool addToDesktop, - const char* x11Display) -{ - PuglView* view = (PuglView*)calloc(1, sizeof(PuglView)); - PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); - if (!view || !impl) { - return nullptr; - } - - view->impl = impl; - view->width = width; - view->height = height; - - impl->display = XOpenDisplay(x11Display); - impl->screen = DefaultScreen(impl->display); - - XVisualInfo* vi = glXChooseVisual(impl->display, impl->screen, attrListDbl); - if (!vi) { - vi = glXChooseVisual(impl->display, impl->screen, attrListSgl); - impl->doubleBuffered = False; - printf("singlebuffered rendering will be used, no doublebuffering available\n"); - } else { - impl->doubleBuffered = True; - printf("doublebuffered rendering available\n"); - } - - int glxMajor, glxMinor; - glXQueryVersion(impl->display, &glxMajor, &glxMinor); - printf("GLX-Version %d.%d\n", glxMajor, glxMinor); - - impl->ctx = glXCreateContext(impl->display, vi, nullptr, GL_TRUE); - - Window xParent = parent - ? (Window)parent - : RootWindow(impl->display, impl->screen); - - Colormap cmap = XCreateColormap( - impl->display, xParent, vi->visual, AllocNone); - - XSetWindowAttributes attr; - memset(&attr, 0, sizeof(XSetWindowAttributes)); - attr.colormap = cmap; - attr.border_pixel = 0; - - attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask - | ButtonPressMask | ButtonReleaseMask - | PointerMotionMask | StructureNotifyMask; - - impl->win = XCreateWindow( - impl->display, xParent, - 0, 0, (unsigned int)view->width, (unsigned int)view->height, 0, vi->depth, InputOutput, vi->visual, - CWBorderPixel | CWColormap | CWEventMask, &attr); - - XSizeHints sizeHints; - memset(&sizeHints, 0, sizeof(sizeHints)); - if (!resizable) { - sizeHints.flags = PMinSize|PMaxSize; - sizeHints.min_width = width; - sizeHints.min_height = height; - sizeHints.max_width = width; - sizeHints.max_height = height; - XSetNormalHints(impl->display, impl->win, &sizeHints); - } - - if (title) { - XStoreName(impl->display, impl->win, title); - } - - if (!parent) { - Atom wmDelete = XInternAtom(impl->display, "WM_DELETE_WINDOW", True); - XSetWMProtocols(impl->display, impl->win, &wmDelete, 1); - } - - if (addToDesktop) { - XMapRaised(impl->display, impl->win); - } - - if (glXIsDirect(impl->display, impl->ctx)) { - printf("DRI enabled\n"); - } else { - printf("no DRI available\n"); - } - - XFree(vi); - - return view; -} - -void -puglDestroy(PuglView* view) -{ - if (!view) { - return; - } - - glXDestroyContext(view->impl->display, view->impl->ctx); - XDestroyWindow(view->impl->display, view->impl->win); - XCloseDisplay(view->impl->display); - free(view->impl); - free(view); -} - -static void -puglReshape(PuglView* view, int width, int height) -{ - glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx); - - if (view->reshapeFunc) { - view->reshapeFunc(view, width, height); - } else { - puglDefaultReshape(view, width, height); - } - - view->width = width; - view->height = height; -} - -static void -puglDisplay(PuglView* view) -{ - glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glLoadIdentity(); - - if (view->displayFunc) { - view->displayFunc(view); - } - - glFlush(); - if (view->impl->doubleBuffered) { - glXSwapBuffers(view->impl->display, view->impl->win); - } - - view->redisplay = false; -} - -static PuglKey -keySymToSpecial(KeySym sym) -{ - switch (sym) { - case XK_F1: return PUGL_KEY_F1; - case XK_F2: return PUGL_KEY_F2; - case XK_F3: return PUGL_KEY_F3; - case XK_F4: return PUGL_KEY_F4; - case XK_F5: return PUGL_KEY_F5; - case XK_F6: return PUGL_KEY_F6; - case XK_F7: return PUGL_KEY_F7; - case XK_F8: return PUGL_KEY_F8; - case XK_F9: return PUGL_KEY_F9; - case XK_F10: return PUGL_KEY_F10; - case XK_F11: return PUGL_KEY_F11; - case XK_F12: return PUGL_KEY_F12; - case XK_Left: return PUGL_KEY_LEFT; - case XK_Up: return PUGL_KEY_UP; - case XK_Right: return PUGL_KEY_RIGHT; - case XK_Down: return PUGL_KEY_DOWN; - case XK_Page_Up: return PUGL_KEY_PAGE_UP; - case XK_Page_Down: return PUGL_KEY_PAGE_DOWN; - case XK_Home: return PUGL_KEY_HOME; - case XK_End: return PUGL_KEY_END; - case XK_Insert: return PUGL_KEY_INSERT; - case XK_Shift_L: return PUGL_KEY_SHIFT; - case XK_Shift_R: return PUGL_KEY_SHIFT; - case XK_Control_L: return PUGL_KEY_CTRL; - case XK_Control_R: return PUGL_KEY_CTRL; - case XK_Alt_L: return PUGL_KEY_ALT; - case XK_Alt_R: return PUGL_KEY_ALT; - case XK_Super_L: return PUGL_KEY_SUPER; - case XK_Super_R: return PUGL_KEY_SUPER; - } - return (PuglKey)0; -} - -static void -setModifiers(PuglView* view, int xstate) -{ - view->mods = 0; - view->mods |= (xstate & ShiftMask) ? PUGL_MOD_SHIFT : 0; - view->mods |= (xstate & ControlMask) ? PUGL_MOD_CTRL : 0; - view->mods |= (xstate & Mod1Mask) ? PUGL_MOD_ALT : 0; - view->mods |= (xstate & Mod4Mask) ? PUGL_MOD_SUPER : 0; -} - -PuglStatus -puglProcessEvents(PuglView* view) -{ - XEvent event; - while (XPending(view->impl->display) > 0) { - XNextEvent(view->impl->display, &event); - switch (event.type) { - case MapNotify: - puglReshape(view, view->width, view->height); - break; - case ConfigureNotify: - if ((event.xconfigure.width != view->width) || - (event.xconfigure.height != view->height)) { - puglReshape(view, - event.xconfigure.width, - event.xconfigure.height); - } - break; - case Expose: - if (event.xexpose.count != 0) { - break; - } - puglDisplay(view); - view->redisplay = false; - break; - case MotionNotify: - setModifiers(view, (int)event.xmotion.state); - if (view->motionFunc) { - view->motionFunc(view, event.xmotion.x, event.xmotion.y); - } - break; - case ButtonPress: - setModifiers(view, (int)event.xbutton.state); - if (event.xbutton.button >= 4 && event.xbutton.button <= 7) { - if (view->scrollFunc) { - float dx = 0, dy = 0; - switch (event.xbutton.button) { - case 4: dy = 1.0f; break; - case 5: dy = -1.0f; break; - case 6: dx = -1.0f; break; - case 7: dx = 1.0f; break; - } - view->scrollFunc(view, dx, dy); - } - break; - } - // nobreak - case ButtonRelease: - setModifiers(view, (int)event.xbutton.state); - if (view->mouseFunc && - (event.xbutton.button < 4 || event.xbutton.button > 7)) { - view->mouseFunc(view, - (int)event.xbutton.button, event.type == ButtonPress, - event.xbutton.x, event.xbutton.y); - } - break; - case KeyPress: { - setModifiers(view, (int)event.xkey.state); - KeySym sym; - char str[5]; - int n = XLookupString(&event.xkey, str, 4, &sym, nullptr); - PuglKey key = keySymToSpecial(sym); - if (!key && view->keyboardFunc) { - if (n == 1) { - view->keyboardFunc(view, true, (uint32_t)str[0]); - } else { - fprintf(stderr, "warning: Unknown key %X\n", (int)sym); - } - } else if (view->specialFunc) { - view->specialFunc(view, true, key); - } - } break; - case KeyRelease: { - setModifiers(view, (int)event.xkey.state); - bool repeated = false; - if (view->ignoreKeyRepeat && - XEventsQueued(view->impl->display, QueuedAfterReading)) { - XEvent next; - XPeekEvent(view->impl->display, &next); - if (next.type == KeyPress && - next.xkey.time == event.xkey.time && - next.xkey.keycode == event.xkey.keycode) { - XNextEvent(view->impl->display, &event); - repeated = true; - } - } - - if (!repeated && view->keyboardFunc) { - KeySym sym = XKeycodeToKeysym( - view->impl->display, (KeyCode)event.xkey.keycode, 0); - PuglKey special = keySymToSpecial(sym); - if (!special) { - view->keyboardFunc(view, false, (uint32_t)sym); - } else if (view->specialFunc) { - view->specialFunc(view, false, special); - } - } - } break; - case ClientMessage: - if (!strcmp(XGetAtomName(view->impl->display, - event.xclient.message_type), - "WM_PROTOCOLS")) { - if (view->closeFunc) { - view->closeFunc(view); - } - } - break; - default: - break; - } - } - - if (view->redisplay) { - puglDisplay(view); - } - - return PUGL_SUCCESS; -} - -void -puglPostRedisplay(PuglView* view) -{ - view->redisplay = true; -} - -PuglNativeWindow -puglGetNativeWindow(PuglView* view) -{ - return static_cast(view->impl->win); -} - -PuglInternals* -puglGetInternalsImpl(PuglView* view) -{ - return view->impl; -} diff --git a/source/libs/pugl/pugl_x11.h b/source/libs/pugl/pugl_x11.h deleted file mode 100644 index 3d592a792..000000000 --- a/source/libs/pugl/pugl_x11.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright 2012 David Robillard - Copyright 2011-2012 Ben Loftis, Harrison Consoles - - 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_x11.h X11 Pugl Implementation (PuglInternalsImpl only). -*/ - -#ifndef PUGL_X11_H_INCLUDED -#define PUGL_X11_H_INCLUDED - -#include "pugl.h" - -#include -#include -#include -#include -#include - -struct PuglInternalsImpl { - Display* display; - int screen; - Window win; - GLXContext ctx; - Bool doubleBuffered; -}; - -typedef struct PuglInternalsImpl PuglInternals; - -PuglInternals* -puglGetInternalsImpl(PuglView* view); - -#endif /* PUGL_X11_H_INCLUDED */