diff options
Diffstat (limited to 'libs/dgl/src/Window.cpp')
-rw-r--r-- | libs/dgl/src/Window.cpp | 251 |
1 files changed, 192 insertions, 59 deletions
diff --git a/libs/dgl/src/Window.cpp b/libs/dgl/src/Window.cpp index e31b75c..c901ff2 100644 --- a/libs/dgl/src/Window.cpp +++ b/libs/dgl/src/Window.cpp @@ -15,11 +15,12 @@ */ // we need this for now -#define PUGL_GRAB_FOCUS 1 +//#define PUGL_GRAB_FOCUS 1 #include "AppPrivateData.hpp" #include "../Widget.hpp" #include "../Window.hpp" +#include "../../distrho/extra/d_string.hpp" #include "pugl/pugl.h" @@ -62,13 +63,15 @@ struct Window::PrivateData { PrivateData(App& app, Window* const self) : fApp(app), fSelf(self), - fView(puglInit(nullptr, nullptr)), + fView(puglInit()), fFirstInit(true), fVisible(false), fResizable(true), fUsingEmbed(false), fWidth(1), fHeight(1), + fTitle(nullptr), + fWidgets(), fModal(), #if defined(DISTRHO_OS_WINDOWS) hwnd(0), @@ -89,13 +92,15 @@ struct Window::PrivateData { PrivateData(App& app, Window* const self, Window& parent) : fApp(app), fSelf(self), - fView(puglInit(nullptr, nullptr)), + fView(puglInit()), fFirstInit(true), fVisible(false), fResizable(true), fUsingEmbed(false), fWidth(1), fHeight(1), + fTitle(nullptr), + fWidgets(), fModal(parent.pData), #if defined(DISTRHO_OS_WINDOWS) hwnd(0), @@ -112,23 +117,29 @@ struct Window::PrivateData { DBG("Creating window with parent..."); DBGF; init(); -#ifdef DISTRHO_OS_LINUX const PuglInternals* const parentImpl(parent.pData->fView->impl); - +#if defined(DISTRHO_OS_LINUX) XSetTransientForHint(xDisplay, xWindow, parentImpl->win); +//#elif defined(DISTRHO_OS_MAC) +// [parentImpl->window orderWindow:NSWindowBelow relativeTo:[[mView window] windowNumber]]; +#else + // unused + return; (void)parentImpl; #endif } PrivateData(App& app, Window* const self, const intptr_t parentId) : fApp(app), fSelf(self), - fView(puglInit(nullptr, nullptr)), + fView(puglInit()), fFirstInit(true), fVisible(parentId != 0), fResizable(parentId == 0), fUsingEmbed(parentId != 0), fWidth(1), fHeight(1), + fTitle(nullptr), + fWidgets(), fModal(), #if defined(DISTRHO_OS_WINDOWS) hwnd(0), @@ -136,7 +147,7 @@ struct Window::PrivateData { xDisplay(nullptr), xWindow(0), #elif defined(DISTRHO_OS_MAC) - fNeedsIdle(false), + fNeedsIdle(parentId == 0), mView(nullptr), mWindow(nullptr), #endif @@ -172,7 +183,7 @@ struct Window::PrivateData { } puglInitResizable(fView, fResizable); - puglInitWindowSize(fView, fWidth, fHeight); + puglInitWindowSize(fView, static_cast<int>(fWidth), static_cast<int>(fHeight)); puglSetHandle(fView, this); puglSetDisplayFunc(fView, onDisplayCallback); @@ -183,6 +194,7 @@ struct Window::PrivateData { puglSetSpecialFunc(fView, onSpecialCallback); puglSetReshapeFunc(fView, onReshapeCallback); puglSetCloseFunc(fView, onCloseCallback); + puglSetFileSelectedFunc(fView, fileBrowserSelectedCallback); puglCreateWindow(fView, nullptr); @@ -221,7 +233,12 @@ struct Window::PrivateData { { DBG("Destroying window..."); DBGF; - //fOnModal = false; + if (fModal.enabled) + { + exec_fini(); + close(); + } + fWidgets.clear(); if (fUsingEmbed) @@ -444,7 +461,11 @@ struct Window::PrivateData { fResizable = yesNo; -#ifdef CARLA_OS_MAC +#if defined(DISTRHO_OS_WINDOWS) + const int winFlags = fResizable ? GetWindowLong(hwnd, GWL_STYLE) | WS_SIZEBOX + : GetWindowLong(hwnd, GWL_STYLE) & ~WS_SIZEBOX; + SetWindowLong(hwnd, GWL_STYLE, winFlags); +#elif defined(DISTRHO_OS_MAC) // FIXME? const uint flags(yesNo ? (NSViewWidthSizable|NSViewHeightSizable) : 0x0); [mView setAutoresizingMask:flags]; @@ -457,7 +478,7 @@ struct Window::PrivateData { void setSize(uint width, uint height, const bool forced = false) { - if (width == 0 || height == 0) + if (width <= 1 || height <= 1) { DBGp("Window setSize called with invalid value(s) %i %i, ignoring request\n", width, height); return; @@ -472,18 +493,15 @@ struct Window::PrivateData { fWidth = width; fHeight = height; - DBGp("Window setSize called %s, size %i %i\n", forced ? "(forced)" : "(not forced)", width, height); + DBGp("Window setSize called %s, size %i %i, resizable %s\n", forced ? "(forced)" : "(not forced)", width, height, fResizable?"true":"false"); #if defined(DISTRHO_OS_WINDOWS) - int winFlags = WS_POPUPWINDOW | WS_CAPTION; - - if (fResizable) - winFlags |= WS_SIZEBOX; - + const int winFlags = WS_POPUPWINDOW | WS_CAPTION | (fResizable ? WS_SIZEBOX : 0x0); RECT wr = { 0, 0, static_cast<long>(width), static_cast<long>(height) }; - AdjustWindowRectEx(&wr, winFlags, FALSE, WS_EX_TOPMOST); + AdjustWindowRectEx(&wr, fUsingEmbed ? WS_CHILD : 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); + SetWindowPos(hwnd, 0, 0, 0, wr.right-wr.left, wr.bottom-wr.top, + SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); if (! forced) UpdateWindow(hwnd); @@ -522,10 +540,22 @@ struct Window::PrivateData { // ------------------------------------------------------------------- + const char* getTitle() const noexcept + { + static const char* const kFallback = ""; + + return fTitle != nullptr ? fTitle : kFallback; + } + void setTitle(const char* const title) { DBGp("Window setTitle \"%s\"\n", title); + if (fTitle != nullptr) + std::free(fTitle); + + fTitle = strdup(title); + #if defined(DISTRHO_OS_WINDOWS) SetWindowTextA(hwnd, title); #elif defined(DISTRHO_OS_MAC) @@ -543,7 +573,7 @@ struct Window::PrivateData { #endif } - void setTransientWinId(const intptr_t winId) + void setTransientWinId(const uintptr_t winId) { #if defined(DISTRHO_OS_LINUX) XSetTransientForHint(xDisplay, xWindow, static_cast< ::Window>(winId)); @@ -600,7 +630,7 @@ struct Window::PrivateData { // ------------------------------------------------------------------- - void onDisplay() + void onPuglDisplay() { fSelf->onDisplayBefore(); @@ -618,22 +648,35 @@ struct Window::PrivateData { if (widget->fNeedsFullViewport || (widget->fAbsolutePos.isZero() && widget->fSize == Size<uint>(fWidth, fHeight))) { // full viewport size - glViewport(0, 0, fWidth, fHeight); + glViewport(0, + 0, + static_cast<GLsizei>(fWidth), + static_cast<GLsizei>(fHeight)); } else if (! widget->fNeedsScaling) { // only set viewport pos - glViewport(widget->getAbsoluteX(), /*fView->height - widget->getHeight()*/ - widget->getAbsoluteY(), fWidth, fHeight); + glViewport(widget->getAbsoluteX(), + /*fView->height - static_cast<int>(widget->getHeight())*/ - widget->getAbsoluteY(), + static_cast<GLsizei>(fWidth), + static_cast<GLsizei>(fHeight)); // then cut the outer bounds - glScissor(widget->getAbsoluteX(), fView->height - widget->getHeight() - widget->getAbsoluteY(), widget->getWidth(), widget->getHeight()); + glScissor(widget->getAbsoluteX(), + fView->height - static_cast<int>(widget->getHeight()) - widget->getAbsoluteY(), + static_cast<GLsizei>(widget->getWidth()), + static_cast<GLsizei>(widget->getHeight())); + glEnable(GL_SCISSOR_TEST); needsDisableScissor = true; } else { // limit viewport to widget bounds - glViewport(widget->getAbsoluteX(), fView->height - widget->getHeight() - widget->getAbsoluteY(), widget->getWidth(), widget->getHeight()); + glViewport(widget->getAbsoluteX(), + fView->height - static_cast<int>(widget->getHeight()) - widget->getAbsoluteY(), + static_cast<GLsizei>(widget->getWidth()), + static_cast<GLsizei>(widget->getHeight())); } // display widget @@ -650,7 +693,7 @@ struct Window::PrivateData { fSelf->onDisplayAfter(); } - void onKeyboard(const bool press, const uint key) + void onPuglKeyboard(const bool press, const uint key) { DBGp("PUGL: onKeyboard : %i %i\n", press, key); @@ -672,7 +715,7 @@ struct Window::PrivateData { } } - void onSpecial(const bool press, const Key key) + void onPuglSpecial(const bool press, const Key key) { DBGp("PUGL: onSpecial : %i %i\n", press, key); @@ -681,9 +724,9 @@ struct Window::PrivateData { Widget::SpecialEvent ev; ev.press = press; - ev.key = key; - ev.mod = static_cast<Modifier>(puglGetModifiers(fView)); - ev.time = puglGetEventTimestamp(fView); + ev.key = key; + ev.mod = static_cast<Modifier>(puglGetModifiers(fView)); + ev.time = puglGetEventTimestamp(fView); FOR_EACH_WIDGET_INV(rit) { @@ -694,18 +737,21 @@ struct Window::PrivateData { } } - void onMouse(const int button, const bool press, const int x, const int y) + void onPuglMouse(const int button, const bool press, const int x, const int y) { DBGp("PUGL: onMouse : %i %i %i %i\n", button, press, x, y); + // FIXME - pugl sends 2 of these for each window on init, don't ask me why. we'll ignore it + if (press && button == 0 && x == 0 && y == 0) return; + if (fModal.childFocus != nullptr) return fModal.childFocus->focus(); Widget::MouseEvent ev; ev.button = button; - ev.press = press; - ev.mod = static_cast<Modifier>(puglGetModifiers(fView)); - ev.time = puglGetEventTimestamp(fView); + ev.press = press; + ev.mod = static_cast<Modifier>(puglGetModifiers(fView)); + ev.time = puglGetEventTimestamp(fView); FOR_EACH_WIDGET_INV(rit) { @@ -718,7 +764,7 @@ struct Window::PrivateData { } } - void onMotion(const int x, const int y) + void onPuglMotion(const int x, const int y) { DBGp("PUGL: onMotion : %i %i\n", x, y); @@ -740,7 +786,7 @@ struct Window::PrivateData { } } - void onScroll(const int x, const int y, const float dx, const float dy) + void onPuglScroll(const int x, const int y, const float dx, const float dy) { DBGp("PUGL: onScroll : %i %i %f %f\n", x, y, dx, dy); @@ -763,38 +809,38 @@ struct Window::PrivateData { } } - void onReshape(const int width, const int height) + void onPuglReshape(const int width, const int height) { DBGp("PUGL: onReshape : %i %i\n", width, height); - if (width == 1 && height == 1) + if (width <= 1 && height <= 1) return; - fWidth = width; - fHeight = height; + fWidth = static_cast<uint>(width); + fHeight = static_cast<uint>(height); - fSelf->onReshape(width, height); + fSelf->onReshape(fWidth, fHeight); FOR_EACH_WIDGET(it) { Widget* const widget(*it); if (widget->fNeedsFullViewport) - widget->setSize(width, height); + widget->setSize(fWidth, fHeight); } } - void onClose() + void onPuglClose() { DBG("PUGL: onClose\n"); - if (fModal.enabled && fModal.parent != nullptr) + if (fModal.enabled) exec_fini(); fSelf->onClose(); if (fModal.childFocus != nullptr) - fModal.childFocus->onClose(); + fModal.childFocus->fSelf->onClose(); close(); } @@ -811,6 +857,7 @@ struct Window::PrivateData { bool fUsingEmbed; uint fWidth; uint fHeight; + char* fTitle; std::list<Widget*> fWidgets; struct Modal { @@ -833,6 +880,8 @@ struct Window::PrivateData { DISTRHO_SAFE_ASSERT(! enabled); DISTRHO_SAFE_ASSERT(childFocus == nullptr); } + + DISTRHO_DECLARE_NON_COPY_STRUCT(Modal) } fModal; #if defined(DISTRHO_OS_WINDOWS) @@ -853,42 +902,47 @@ struct Window::PrivateData { static void onDisplayCallback(PuglView* view) { - handlePtr->onDisplay(); + handlePtr->onPuglDisplay(); } static void onKeyboardCallback(PuglView* view, bool press, uint32_t key) { - handlePtr->onKeyboard(press, key); + handlePtr->onPuglKeyboard(press, key); } static void onSpecialCallback(PuglView* view, bool press, PuglKey key) { - handlePtr->onSpecial(press, static_cast<Key>(key)); + handlePtr->onPuglSpecial(press, static_cast<Key>(key)); } static void onMouseCallback(PuglView* view, int button, bool press, int x, int y) { - handlePtr->onMouse(button, press, x, y); + handlePtr->onPuglMouse(button, press, x, y); } static void onMotionCallback(PuglView* view, int x, int y) { - handlePtr->onMotion(x, y); + handlePtr->onPuglMotion(x, y); } static void onScrollCallback(PuglView* view, int x, int y, float dx, float dy) { - handlePtr->onScroll(x, y, dx, dy); + handlePtr->onPuglScroll(x, y, dx, dy); } static void onReshapeCallback(PuglView* view, int width, int height) { - handlePtr->onReshape(width, height); + handlePtr->onPuglReshape(width, height); } static void onCloseCallback(PuglView* view) { - handlePtr->onClose(); + handlePtr->onPuglClose(); + } + + static void fileBrowserSelectedCallback(PuglView* view, const char* filename) + { + handlePtr->fSelf->fileBrowserSelected(filename); } #undef handlePtr @@ -900,13 +954,16 @@ struct Window::PrivateData { // Window Window::Window(App& app) - : pData(new PrivateData(app, this)) {} + : pData(new PrivateData(app, this)), + leakDetector_Window() {} Window::Window(App& app, Window& parent) - : pData(new PrivateData(app, this, parent)) {} + : pData(new PrivateData(app, this, parent)), + leakDetector_Window() {} Window::Window(App& app, intptr_t parentId) - : pData(new PrivateData(app, this, parentId)) {} + : pData(new PrivateData(app, this, parentId)), + leakDetector_Window() {} Window::~Window() { @@ -943,6 +1000,73 @@ void Window::repaint() noexcept puglPostRedisplay(pData->fView); } +// static int fib_filter_filename_filter(const char* const name) +// { +// return 1; +// (void)name; +// } + +bool Window::openFileBrowser(const FileBrowserOptions& options) +{ + using DISTRHO_NAMESPACE::d_string; + + // -------------------------------------------------------------------------- + // configure start dir + + // TODO: get abspath if needed + // TODO: cross-platform + + d_string startDir(options.startDir); + + if (startDir.isEmpty()) + { + if (char* const dir_name = get_current_dir_name()) + { + startDir = dir_name; + std::free(dir_name); + } + } + + DISTRHO_SAFE_ASSERT_RETURN(startDir.isNotEmpty(), false); + + if (! startDir.endsWith('/')) + startDir += "/"; + + DISTRHO_SAFE_ASSERT_RETURN(x_fib_configure(0, startDir) == 0, false); + + // -------------------------------------------------------------------------- + // configure title + + d_string title(options.title); + + if (title.isEmpty()) + { + title = pData->getTitle(); + + if (title.isEmpty()) + title = "FileBrowser"; + } + + DISTRHO_SAFE_ASSERT_RETURN(x_fib_configure(1, title) == 0, false); + + // -------------------------------------------------------------------------- + // configure filters + + x_fib_cfg_filter_callback(nullptr); //fib_filter_filename_filter); + + // -------------------------------------------------------------------------- + // configure buttons + + x_fib_cfg_buttons(3, options.buttons.listAllFiles-1); + x_fib_cfg_buttons(1, options.buttons.showHidden-1); + x_fib_cfg_buttons(2, options.buttons.showPlaces-1); + + // -------------------------------------------------------------------------- + // show + + return (x_fib_show(pData->xDisplay, pData->xWindow, /*options.width*/0, /*options.height*/0) == 0); +} + bool Window::isVisible() const noexcept { return pData->fVisible; @@ -988,12 +1112,17 @@ void Window::setSize(Size<uint> size) pData->setSize(size.getWidth(), size.getHeight()); } +const char* Window::getTitle() const noexcept +{ + return pData->getTitle(); +} + void Window::setTitle(const char* title) { pData->setTitle(title); } -void Window::setTransientWinId(intptr_t winId) +void Window::setTransientWinId(uintptr_t winId) { pData->setTransientWinId(winId); } @@ -1057,8 +1186,8 @@ void Window::onReshape(uint width, uint height) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glOrtho(0, width, height, 0, 0.0f, 1.0f); - glViewport(0, 0, width, height); + glOrtho(0.0, static_cast<GLdouble>(width), static_cast<GLdouble>(height), 0.0, 0.0, 1.0); + glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height)); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } @@ -1067,6 +1196,10 @@ void Window::onClose() { } +void Window::fileBrowserSelected(const char*) +{ +} + // ----------------------------------------------------------------------- END_NAMESPACE_DGL |