commit dce7676eb83ede14ff92d76beddddc30e3df674e
parent 23db12f290be2fcafddc9468bcad7ca18f5e12bc
Author: falkTX <falktx@falktx.com>
Date: Mon, 20 Apr 2020 07:33:25 +0100
Restructure of code for new pugl, WIP
Signed-off-by: falkTX <falktx@falktx.com>
Diffstat:
22 files changed, 1171 insertions(+), 979 deletions(-)
diff --git a/Makefile b/Makefile
@@ -27,9 +27,9 @@ examples: dgl
$(MAKE) all -C examples/Parameters
$(MAKE) all -C examples/States
-ifeq ($(HAVE_CAIRO),true)
- $(MAKE) all -C examples/CairoUI
-endif
+# ifeq ($(HAVE_CAIRO),true)
+# $(MAKE) all -C examples/CairoUI
+# endif
ifneq ($(MACOS_OR_WINDOWS),true)
# ExternalUI is WIP
diff --git a/dgl/Widget.hpp b/dgl/Widget.hpp
@@ -301,11 +301,14 @@ public:
*/
void setAbsolutePos(const Point<int>& pos) noexcept;
+#if 0
+ // TODO: should we remove this?
/**
Get this widget's window application.
Same as calling getParentWindow().getApp().
*/
Application& getParentApp() const noexcept;
+#endif
/**
Get parent window, as passed in the constructor.
diff --git a/dgl/Window.hpp b/dgl/Window.hpp
@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
- * Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com>
+ * Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com>
*
* 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
@@ -77,8 +77,8 @@ public:
#endif // DGL_FILE_BROWSER_DISABLED
explicit Window(Application& app);
- explicit Window(Application& app, Window& parent);
- explicit Window(Application& app, intptr_t parentId, double scaling, bool resizable);
+ explicit Window(Window& transientParentWindow);
+ explicit Window(Application& app, uintptr_t parentWindowHandle, double scaling, bool resizable);
virtual ~Window();
void show();
@@ -88,6 +88,7 @@ public:
void focus();
void repaint() noexcept;
+ void repaint(const Rectangle<uint>& rect) noexcept;
#ifndef DGL_FILE_BROWSER_DISABLED
bool openFileBrowser(const FileBrowserOptions& options);
@@ -96,10 +97,13 @@ public:
bool isEmbed() const noexcept;
bool isVisible() const noexcept;
- void setVisible(bool yesNo);
+ void setVisible(bool visible);
bool isResizable() const noexcept;
- void setResizable(bool yesNo);
+ void setResizable(bool resizable);
+
+ bool getIgnoringKeyRepeat() const noexcept;
+ void setIgnoringKeyRepeat(bool ignore) noexcept;
uint getWidth() const noexcept;
uint getHeight() const noexcept;
@@ -115,11 +119,20 @@ public:
double getScaling() const noexcept;
- bool getIgnoringKeyRepeat() const noexcept;
- void setIgnoringKeyRepeat(bool ignore) noexcept;
-
+#if 0
+ // should this be removed?
Application& getApp() const noexcept;
- uintptr_t getWindowId() const noexcept;
+#endif
+
+ /**
+ Get the "native" window handle.
+ Returned value depends on the platform:
+ - HaikuOS: This is a pointer to a `BView`.
+ - MacOS: This is a pointer to an `NSView*`.
+ - Windows: This is a `HWND`.
+ - Everything else: This is an [X11] `Window`.
+ */
+ uintptr_t getNativeWindowHandle() const noexcept;
const GraphicsContext& getGraphicsContext() const noexcept;
@@ -157,7 +170,16 @@ private:
bool handlePluginKeyboard(const bool press, const uint key);
bool handlePluginSpecial(const bool press, const Key key);
- DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Window)
+ // Prevent copies
+#ifdef DISTRHO_PROPER_CPP11_SUPPORT
+ Window& operator=(Window&) = delete;
+ Window& operator=(const Window&) = delete;
+#else
+ Window& operator=(Window&);
+ Window& operator=(const Window&);
+#endif
+
+ DISTRHO_LEAK_DETECTOR(Window);
};
// -----------------------------------------------------------------------
diff --git a/dgl/src/Application.cpp b/dgl/src/Application.cpp
@@ -35,7 +35,7 @@ void Application::idle()
void Application::exec(const uint idleTime)
{
- while (!pData->isQuitting)
+ while (! pData->isQuitting)
pData->idle(idleTime);
}
diff --git a/dgl/src/ApplicationPrivateData.hpp b/dgl/src/ApplicationPrivateData.hpp
@@ -47,6 +47,8 @@ struct Application::PrivateData {
{
puglSetWorldHandle(world, this);
+ // puglSetLogLevel(world, PUGL_LOG_LEVEL_DEBUG);
+
// TODO puglSetClassName
}
@@ -58,6 +60,7 @@ struct Application::PrivateData {
windows.clear();
idleCallbacks.clear();
+ d_stdout("calling puglFreeWorld");
puglFreeWorld(world);
}
diff --git a/dgl/src/ImageWidgets.cpp b/dgl/src/ImageWidgets.cpp
@@ -27,7 +27,7 @@ START_NAMESPACE_DGL
#ifndef DISTRHO_OS_HAIKU
ImageAboutWindow::ImageAboutWindow(Window& parent, const Image& image)
- : Window(parent.getApp(), parent),
+ : Window(parent),
Widget((Window&)*this),
fImgBackground(image)
{
@@ -37,7 +37,7 @@ ImageAboutWindow::ImageAboutWindow(Window& parent, const Image& image)
}
ImageAboutWindow::ImageAboutWindow(Widget* widget, const Image& image)
- : Window(widget->getParentApp(), widget->getParentWindow()),
+ : Window(widget->getParentWindow()),
Widget((Window&)*this),
fImgBackground(image)
{
diff --git a/dgl/src/Widget.cpp b/dgl/src/Widget.cpp
@@ -179,10 +179,12 @@ void Widget::setAbsolutePos(const Point<int>& pos) noexcept
pData->parent.repaint();
}
+#if 0
Application& Widget::getParentApp() const noexcept
{
return pData->parent.getApp();
}
+#endif
Window& Widget::getParentWindow() const noexcept
{
diff --git a/dgl/src/Window.cpp b/dgl/src/Window.cpp
@@ -14,34 +14,27 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-// we need this for now
-//#define PUGL_GRAB_FOCUS 1
-
-// #include "../Base.hpp"
#include "WindowPrivateData.hpp"
-// #include "../../distrho/extra/String.hpp"
-
START_NAMESPACE_DGL
// -----------------------------------------------------------------------
// Window
Window::Window(Application& app)
- : pData(new PrivateData(app, this)) {}
+ : pData(new PrivateData(app.pData, this)) {}
-Window::Window(Application& app, Window& parent)
- : pData(new PrivateData(app, this, parent)) {}
+Window::Window(Window& transientParentWindow)
+ : pData(new PrivateData(transientParentWindow.pData->fAppData, this, transientParentWindow)) {}
-Window::Window(Application& app, intptr_t parentId, double scaling, bool resizable)
- : pData(new PrivateData(app, this, parentId, scaling, resizable)) {}
+Window::Window(Application& app, const uintptr_t parentWindowHandle, const double scaling, const bool resizable)
+ : pData(new PrivateData(app.pData, this, parentWindowHandle, scaling, resizable)) {}
Window::~Window()
{
delete pData;
}
-#if 0
void Window::show()
{
pData->setVisible(true);
@@ -57,14 +50,19 @@ void Window::close()
pData->close();
}
+#if 0
void Window::exec(bool lockWait)
{
pData->exec(lockWait);
}
+#endif
void Window::focus()
{
- pData->focus();
+ if (! pData->fUsingEmbed)
+ puglRaiseWindow(pData->fView);
+
+ puglGrabFocus(pData->fView);
}
void Window::repaint() noexcept
@@ -72,6 +70,17 @@ void Window::repaint() noexcept
puglPostRedisplay(pData->fView);
}
+void Window::repaint(const Rectangle<uint>& rect) noexcept
+{
+ const PuglRect prect = {
+ static_cast<double>(rect.getX()),
+ static_cast<double>(rect.getY()),
+ static_cast<double>(rect.getWidth()),
+ static_cast<double>(rect.getHeight()),
+ };
+ puglPostRedisplayRect(pData->fView, prect);
+}
+
bool Window::isEmbed() const noexcept
{
return pData->fUsingEmbed;
@@ -82,88 +91,107 @@ bool Window::isVisible() const noexcept
return pData->fVisible;
}
-void Window::setVisible(bool yesNo)
+void Window::setVisible(const bool visible)
{
- pData->setVisible(yesNo);
+ pData->setVisible(visible);
}
bool Window::isResizable() const noexcept
{
- return pData->fResizable;
+ return puglGetViewHint(pData->fView, PUGL_RESIZABLE) == PUGL_TRUE;
}
-void Window::setResizable(bool yesNo)
+void Window::setResizable(const bool resizable)
{
- pData->setResizable(yesNo);
+ DISTRHO_SAFE_ASSERT_RETURN(pData->fUsingEmbed,);
+ if (pData->fUsingEmbed)
+ {
+ DGL_DBG("Window setResizable cannot be called when embedded\n");
+ return;
+ }
+
+ DGL_DBG("Window setResizable called\n");
+
+ puglSetViewHint(pData->fView, PUGL_RESIZABLE, resizable ? PUGL_TRUE : PUGL_FALSE);
+#ifdef DISTRHO_OS_WINDOWS
+ puglWin32SetWindowResizable(pData->fView, resizable);
+#endif
}
-void Window::setGeometryConstraints(uint width, uint height, bool aspect)
+bool Window::getIgnoringKeyRepeat() const noexcept
{
- pData->setGeometryConstraints(width, height, aspect);
+ return puglGetViewHint(pData->fView, PUGL_IGNORE_KEY_REPEAT) == PUGL_TRUE;
}
-uint Window::getWidth() const noexcept
+void Window::setIgnoringKeyRepeat(const bool ignore) noexcept
{
- return pData->fWidth;
+ puglSetViewHint(pData->fView, PUGL_IGNORE_KEY_REPEAT, ignore);
}
-uint Window::getHeight() const noexcept
+void Window::setGeometryConstraints(const uint width, const uint height, bool aspect)
{
- return pData->fHeight;
+ // Did you forget to set DISTRHO_UI_USER_RESIZABLE ?
+ DISTRHO_SAFE_ASSERT_RETURN(isResizable(),);
+
+ puglUpdateGeometryConstraints(pData->fView, width, height, aspect);
}
-Size<uint> Window::getSize() const noexcept
+uint Window::getWidth() const noexcept
{
- return Size<uint>(pData->fWidth, pData->fHeight);
+ return puglGetFrame(pData->fView).width;
}
-void Window::setSize(uint width, uint height)
+uint Window::getHeight() const noexcept
{
- pData->setSize(width, height);
+ return puglGetFrame(pData->fView).height;
}
-void Window::setSize(Size<uint> size)
+Size<uint> Window::getSize() const noexcept
{
- pData->setSize(size.getWidth(), size.getHeight());
+ const PuglRect rect = puglGetFrame(pData->fView);
+ return Size<uint>(rect.width, rect.height);
}
-const char* Window::getTitle() const noexcept
+void Window::setSize(const uint width, const uint height)
{
- return pData->getTitle();
+ DISTRHO_SAFE_ASSERT_INT2_RETURN(width > 1 && height > 1, width, height,);
+
+ puglSetWindowSize(pData->fView, width, height);
}
-void Window::setTitle(const char* title)
+void Window::setSize(const Size<uint> size)
{
- pData->setTitle(title);
+ setSize(size.getWidth(), size.getHeight());
}
-void Window::setTransientWinId(uintptr_t winId)
+const char* Window::getTitle() const noexcept
{
- pData->setTransientWinId(winId);
+ return puglGetWindowTitle(pData->fView);
}
-double Window::getScaling() const noexcept
+void Window::setTitle(const char* const title)
{
- return pData->getScaling();
+ puglSetWindowTitle(pData->fView, title);
}
-bool Window::getIgnoringKeyRepeat() const noexcept
+void Window::setTransientWinId(const uintptr_t winId)
{
- return pData->getIgnoringKeyRepeat();
+ puglSetTransientFor(pData->fView, winId);
}
-void Window::setIgnoringKeyRepeat(bool ignore) noexcept
+double Window::getScaling() const noexcept
{
- pData->setIgnoringKeyRepeat(ignore);
+ return pData->fScaling;
}
-#endif
+#if 0
Application& Window::getApp() const noexcept
{
return pData->fApp;
}
+#endif
-uintptr_t Window::getWindowId() const noexcept
+uintptr_t Window::getNativeWindowHandle() const noexcept
{
return puglGetNativeWindow(pData->fView);
}
@@ -177,10 +205,13 @@ const GraphicsContext& Window::getGraphicsContext() const noexcept
#endif
return context;
}
+#endif
void Window::_setAutoScaling(double scaling) noexcept
{
- pData->setAutoScaling(scaling);
+ DISTRHO_SAFE_ASSERT_RETURN(scaling > 0.0,);
+
+ pData->fAutoScaling = scaling;
}
void Window::_addWidget(Widget* const widget)
@@ -195,9 +226,8 @@ void Window::_removeWidget(Widget* const widget)
void Window::_idle()
{
- pData->idle();
+ pData->windowSpecificIdle();
}
-#endif
// -----------------------------------------------------------------------
@@ -205,14 +235,14 @@ void Window::addIdleCallback(IdleCallback* const callback)
{
DISTRHO_SAFE_ASSERT_RETURN(callback != nullptr,)
- pData->fApp.pData->idleCallbacks.push_back(callback);
+ pData->fAppData->idleCallbacks.push_back(callback);
}
void Window::removeIdleCallback(IdleCallback* const callback)
{
DISTRHO_SAFE_ASSERT_RETURN(callback != nullptr,)
- pData->fApp.pData->idleCallbacks.remove(callback);
+ pData->fAppData->idleCallbacks.remove(callback);
}
// -----------------------------------------------------------------------
@@ -242,21 +272,20 @@ void Window::fileBrowserSelected(const char*)
}
#endif
-#if 0
bool Window::handlePluginKeyboard(const bool press, const uint key)
{
- return pData->handlePluginKeyboard(press, key);
+ // TODO
+ return false;
+ // return pData->handlePluginKeyboard(press, key);
}
bool Window::handlePluginSpecial(const bool press, const Key key)
{
- return pData->handlePluginSpecial(press, key);
+ // TODO
+ return false;
+ // return pData->handlePluginSpecial(press, key);
}
-#endif
// -----------------------------------------------------------------------
END_NAMESPACE_DGL
-
-#undef DBG
-#undef DBGF
diff --git a/dgl/src/WindowPrivateData.cpp b/dgl/src/WindowPrivateData.cpp
@@ -27,6 +27,7 @@
extern "C" {
#include "pugl-upstream/src/implementation.c"
+#include "pugl-extra/extras.c"
}
#if defined(DISTRHO_OS_HAIKU)
@@ -41,18 +42,336 @@ extern "C" {
# undef max
# undef min
#else
-# include <sys/types.h>
-# include <unistd.h>
+# define DGL_PUGL_USING_X11
extern "C" {
# include "pugl-upstream/src/x11.c"
+// # ifdef DGL_CAIRO
+// # include "pugl-upstream/src/x11_cairo.c"
+// # endif
+# ifdef DGL_OPENGL
+# include "pugl-upstream/src/x11_gl.c"
+# endif
+# define PUGL_DETAIL_X11_H_INCLUDED
+# include "pugl-extra/x11.c"
}
#endif
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
START_NAMESPACE_DGL
// -----------------------------------------------------------------------
-void DGL::Window::PrivateData::Fallback::onDisplayBefore()
+void Window::PrivateData::init(const bool resizable)
+{
+ if (fSelf == nullptr || fView == nullptr)
+ {
+ DGL_DBG("Failed!\n");
+ return;
+ }
+
+// #ifdef DGL_CAIRO
+// puglSetBackend(fView, puglCairoBackend());
+// #endif
+#ifdef DGL_OPENGL
+ puglSetBackend(fView, puglGlBackend());
+#endif
+
+ puglSetHandle(fView, this);
+ puglSetViewHint(fView, PUGL_RESIZABLE, resizable ? PUGL_TRUE : PUGL_FALSE);
+ puglSetViewHint(fView, PUGL_IGNORE_KEY_REPEAT, PUGL_FALSE);
+ puglSetEventFunc(fView, puglEventCallback);
+// #ifndef DGL_FILE_BROWSER_DISABLED
+// puglSetFileSelectedFunc(fView, fileBrowserSelectedCallback);
+// #endif
+
+ fAppData->windows.push_back(fSelf);
+
+ DGL_DBG("Success!\n");
+}
+
+void Window::PrivateData::setVisible(const bool visible)
+{
+ if (fVisible == visible)
+ {
+ DGL_DBG("Window setVisible matches current state, ignoring request\n");
+ return;
+ }
+ if (fUsingEmbed)
+ {
+ DGL_DBG("Window setVisible cannot be called when embedded\n");
+ return;
+ }
+
+ DGL_DBG("Window setVisible called\n");
+
+ fVisible = visible;
+
+ if (visible)
+ {
+#if 0 && defined(DISTRHO_OS_MAC)
+ if (mWindow != nullptr)
+ {
+ if (mParentWindow != nullptr)
+ [mParentWindow addChildWindow:mWindow
+ ordered:NSWindowAbove];
+ }
+#endif
+
+ if (fFirstInit)
+ {
+ puglRealize(fView);
+#ifdef DISTRHO_OS_WINDOWS
+ puglShowWindowCentered(fView);
+#else
+ puglShowWindow(fView);
+#endif
+ fAppData->oneWindowShown();
+ fFirstInit = false;
+ }
+ else
+ {
+#ifdef DISTRHO_OS_WINDOWS
+ puglWin32RestoreWindow(fView);
+#else
+ puglShowWindow(fView);
+#endif
+ }
+ }
+ else
+ {
+#if 0 && defined(DISTRHO_OS_MAC)
+ if (mWindow != nullptr)
+ {
+ if (mParentWindow != nullptr)
+ [mParentWindow removeChildWindow:mWindow];
+ }
+#endif
+
+ puglHideWindow(fView);
+
+// if (fModal.enabled)
+// exec_fini();
+ }
+}
+
+void Window::PrivateData::windowSpecificIdle()
+{
+#if defined(DISTRHO_OS_WINDOWS) && !defined(DGL_FILE_BROWSER_DISABLED)
+ if (fSelectedFile.isNotEmpty())
+ {
+ char* const buffer = fSelectedFile.getAndReleaseBuffer();
+ fView->fileSelectedFunc(fView, buffer);
+ std::free(buffer);
+ }
+#endif
+
+ if (fModal.enabled && fModal.parent != nullptr)
+ fModal.parent->windowSpecificIdle();
+}
+
+// -----------------------------------------------------------------------
+
+static inline int
+printModifiers(const uint32_t mods)
+{
+ return fprintf(stderr, "Modifiers:%s%s%s%s\n",
+ (mods & PUGL_MOD_SHIFT) ? " Shift" : "",
+ (mods & PUGL_MOD_CTRL) ? " Ctrl" : "",
+ (mods & PUGL_MOD_ALT) ? " Alt" : "",
+ (mods & PUGL_MOD_SUPER) ? " Super" : "");
+}
+
+static inline int
+printEvent(const PuglEvent* event, const char* prefix, const bool verbose)
+{
+#define FFMT "%6.1f"
+#define PFMT FFMT " " FFMT
+#define PRINT(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
+
+ switch (event->type) {
+ case PUGL_NOTHING:
+ return 0;
+ case PUGL_KEY_PRESS:
+ return PRINT("%sKey press code %3u key U+%04X\n",
+ prefix,
+ event->key.keycode,
+ event->key.key);
+ case PUGL_KEY_RELEASE:
+ return PRINT("%sKey release code %3u key U+%04X\n",
+ prefix,
+ event->key.keycode,
+ event->key.key);
+ case PUGL_TEXT:
+ return PRINT("%sText entry code %3u char U+%04X (%s)\n",
+ prefix,
+ event->text.keycode,
+ event->text.character,
+ event->text.string);
+ case PUGL_BUTTON_PRESS:
+ case PUGL_BUTTON_RELEASE:
+ return (PRINT("%sMouse %u %s at " PFMT " ",
+ prefix,
+ event->button.button,
+ (event->type == PUGL_BUTTON_PRESS) ? "down" : "up ",
+ event->button.x,
+ event->button.y) +
+ printModifiers(event->scroll.state));
+ case PUGL_SCROLL:
+ return (PRINT("%sScroll %5.1f %5.1f at " PFMT " ",
+ prefix,
+ event->scroll.dx,
+ event->scroll.dy,
+ event->scroll.x,
+ event->scroll.y) +
+ printModifiers(event->scroll.state));
+ case PUGL_POINTER_IN:
+ return PRINT("%sMouse enter at " PFMT "\n",
+ prefix,
+ event->crossing.x,
+ event->crossing.y);
+ case PUGL_POINTER_OUT:
+ return PRINT("%sMouse leave at " PFMT "\n",
+ prefix,
+ event->crossing.x,
+ event->crossing.y);
+ case PUGL_FOCUS_IN:
+ return PRINT("%sFocus in %i\n",
+ prefix,
+ event->focus.mode);
+ case PUGL_FOCUS_OUT:
+ return PRINT("%sFocus out %i\n",
+ prefix,
+ event->focus.mode);
+ case PUGL_CLIENT:
+ return PRINT("%sClient %" PRIXPTR " %" PRIXPTR "\n",
+ prefix,
+ event->client.data1,
+ event->client.data2);
+ case PUGL_TIMER:
+ return PRINT("%sTimer %" PRIuPTR "\n", prefix, event->timer.id);
+ default:
+ break;
+ }
+
+ if (verbose) {
+ switch (event->type) {
+ case PUGL_CREATE:
+ return fprintf(stderr, "%sCreate\n", prefix);
+ case PUGL_DESTROY:
+ return fprintf(stderr, "%sDestroy\n", prefix);
+ case PUGL_MAP:
+ return fprintf(stderr, "%sMap\n", prefix);
+ case PUGL_UNMAP:
+ return fprintf(stderr, "%sUnmap\n", prefix);
+ case PUGL_UPDATE:
+ return fprintf(stderr, "%sUpdate\n", prefix);
+ case PUGL_CONFIGURE:
+ return PRINT("%sConfigure " PFMT " " PFMT "\n",
+ prefix,
+ event->configure.x,
+ event->configure.y,
+ event->configure.width,
+ event->configure.height);
+ case PUGL_EXPOSE:
+ return PRINT("%sExpose " PFMT " " PFMT "\n",
+ prefix,
+ event->expose.x,
+ event->expose.y,
+ event->expose.width,
+ event->expose.height);
+ case PUGL_CLOSE:
+ return PRINT("%sClose\n", prefix);
+ case PUGL_MOTION:
+ return PRINT("%sMouse motion at " PFMT "\n",
+ prefix,
+ event->motion.x,
+ event->motion.y);
+ default:
+ return PRINT("%sUnknown event type %d\n", prefix, (int)event->type);
+ }
+ }
+
+#undef PRINT
+#undef PFMT
+#undef FFMT
+
+ return 0;
+}
+
+PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const PuglEvent* const event)
+{
+ printEvent(event, "", true);
+ Window::PrivateData* const pData = (Window::PrivateData*)puglGetHandle(view);
+
+ switch (event->type)
+ {
+ ///< No event
+ case PUGL_NOTHING:
+ break;
+
+ ///< View created, a #PuglEventCreate
+ case PUGL_CREATE:
+#ifdef DGL_PUGL_USING_X11
+ if (! pData->fUsingEmbed)
+ puglExtraSetWindowTypeAndPID(view);
+#endif
+ break;
+
+ ///< View destroyed, a #PuglEventDestroy
+ case PUGL_DESTROY:
+ break;
+
+ ///< View moved/resized, a #PuglEventConfigure
+ case PUGL_CONFIGURE:
+ pData->onPuglReshape(event->configure.width, event->configure.height);
+ break;
+
+ case PUGL_MAP: ///< View made visible, a #PuglEventMap
+ case PUGL_UNMAP: ///< View made invisible, a #PuglEventUnmap
+ break;
+
+ ///< View ready to draw, a #PuglEventUpdate
+ case PUGL_UPDATE:
+ break;
+
+ ///< View must be drawn, a #PuglEventExpose
+ case PUGL_EXPOSE:
+ pData->onPuglDisplay();
+ break;
+
+ ///< View will be closed, a #PuglEventClose
+ case PUGL_CLOSE:
+ pData->onPuglClose();
+ break;
+
+ case PUGL_FOCUS_IN: ///< Keyboard focus entered view, a #PuglEventFocus
+ case PUGL_FOCUS_OUT: ///< Keyboard focus left view, a #PuglEventFocus
+ case PUGL_KEY_PRESS: ///< Key pressed, a #PuglEventKey
+ case PUGL_KEY_RELEASE: ///< Key released, a #PuglEventKey
+ case PUGL_TEXT: ///< Character entered, a #PuglEventText
+ case PUGL_POINTER_IN: ///< Pointer entered view, a #PuglEventCrossing
+ case PUGL_POINTER_OUT: ///< Pointer left view, a #PuglEventCrossing
+ case PUGL_BUTTON_PRESS: ///< Mouse button pressed, a #PuglEventButton
+ case PUGL_BUTTON_RELEASE: ///< Mouse button released, a #PuglEventButton
+ case PUGL_MOTION: ///< Pointer moved, a #PuglEventMotion
+ case PUGL_SCROLL: ///< Scrolled, a #PuglEventScroll
+ case PUGL_CLIENT: ///< Custom client message, a #PuglEventClient
+ case PUGL_TIMER: ///< Timer triggered, a #PuglEventTimer
+ break;
+ }
+
+ return PUGL_SUCCESS;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::PrivateData::Fallback::onDisplayBefore()
{
#ifdef DGL_OPENGL
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -60,11 +379,11 @@ void DGL::Window::PrivateData::Fallback::onDisplayBefore()
#endif
}
-void DGL::Window::PrivateData::Fallback::onDisplayAfter()
+void Window::PrivateData::Fallback::onDisplayAfter()
{
}
-void DGL::Window::PrivateData::Fallback::onReshape(const uint width, const uint height)
+void Window::PrivateData::Fallback::onReshape(const uint width, const uint height)
{
#ifdef DGL_OPENGL
glEnable(GL_BLEND);
diff --git a/dgl/src/WindowPrivateData.hpp b/dgl/src/WindowPrivateData.hpp
@@ -18,9 +18,12 @@
#define DGL_WINDOW_PRIVATE_DATA_HPP_INCLUDED
#include "../Window.hpp"
+
#include "ApplicationPrivateData.hpp"
+#include "WidgetPrivateData.hpp"
#include "pugl-upstream/include/pugl/pugl.h"
+#include "pugl-extra/extras.h"
#include <vector>
@@ -30,14 +33,16 @@
#define FOR_EACH_WIDGET_INV(rit) \
for (std::list<Widget*>::reverse_iterator rit = fWidgets.rbegin(); rit != fWidgets.rend(); ++rit)
+#define DGL_DEBUG_EVENTS
+
#if defined(DEBUG) && defined(DGL_DEBUG_EVENTS)
-# define DBG(msg) std::fprintf(stderr, "%s", msg);
-# define DBGp(...) std::fprintf(stderr, __VA_ARGS__);
-# define DBGF std::fflush(stderr);
+# define DGL_DBG(msg) std::fprintf(stderr, "%s", msg);
+# define DGL_DBGp(...) std::fprintf(stderr, __VA_ARGS__);
+# define DGL_DBGF std::fflush(stderr);
#else
-# define DBG(msg)
-# define DBGp(...)
-# define DBGF
+# define DGL_DBG(msg)
+# define DGL_DBGp(...)
+# define DGL_DBGF
#endif
START_NAMESPACE_DGL
@@ -45,13 +50,66 @@ START_NAMESPACE_DGL
// -----------------------------------------------------------------------
struct Window::PrivateData {
- Application& fApp;
- Window* fSelf;
- PuglView* fView;
+ typedef Application::PrivateData AppData;
+
+ AppData* const fAppData;
+ Window* const fSelf;
+ PuglView* const fView;
// this one depends on build type
// GraphicsContext fContext;
+ bool fFirstInit;
+ bool fVisible;
+ bool fUsingEmbed;
+ double fScaling;
+ double fAutoScaling;
+ std::list<Widget*> fWidgets;
+
+ struct Modal {
+ bool enabled;
+ PrivateData* parent;
+ PrivateData* childFocus;
+
+ Modal()
+ : enabled(false),
+ parent(nullptr),
+ childFocus(nullptr) {}
+
+ Modal(PrivateData* const p)
+ : enabled(false),
+ parent(p),
+ childFocus(nullptr) {}
+
+ ~Modal()
+ {
+ DISTRHO_SAFE_ASSERT(! enabled);
+ DISTRHO_SAFE_ASSERT(childFocus == nullptr);
+ }
+
+ DISTRHO_DECLARE_NON_COPY_STRUCT(Modal)
+ } fModal;
+
+// #if defined(DISTRHO_OS_HAIKU)
+// BApplication* bApplication;
+// BView* bView;
+// BWindow* bWindow;
+#if defined(DISTRHO_OS_MAC)
+// NSView<PuglGenericView>* mView;
+// id mWindow;
+// id mParentWindow;
+# ifndef DGL_FILE_BROWSER_DISABLED
+ NSOpenPanel* fOpenFilePanel;
+ id fFilePanelDelegate;
+# endif
+#elif defined(DISTRHO_OS_WINDOWS)
+// HWND hwnd;
+// HWND hwndParent;
+# ifndef DGL_FILE_BROWSER_DISABLED
+ String fSelectedFile;
+# endif
+#endif
+
// Fallback build-specific Window functions
struct Fallback {
static void onDisplayBefore();
@@ -59,6 +117,7 @@ struct Window::PrivateData {
static void onReshape(uint width, uint height);
};
+ /*
PrivateData(Application& app, Window* const self)
: fApp(app),
fSelf(self)
@@ -76,301 +135,99 @@ struct Window::PrivateData {
fSelf(self)
{
}
-
-#ifdef DISTRHO_DEFINES_H_INCLUDED
- friend class DISTRHO_NAMESPACE::UI;
-#endif
-
- DISTRHO_DECLARE_NON_COPY_STRUCT(PrivateData)
-};
-
-// -----------------------------------------------------------------------
-
-END_NAMESPACE_DGL
-
-#endif // DGL_WINDOW_PRIVATE_DATA_HPP_INCLUDED
-
-
-
-
-#if 0
-// -----------------------------------------------------------------------
-// Window Private
-
-struct Window::PrivateData {
- PrivateData(Application& app, Window* const self)
- : fApp(app),
+ */
+ PrivateData(Application::PrivateData* const appData, Window* const self)
+ : fAppData(appData),
fSelf(self),
- fView(puglInit()),
+ fView(puglNewView(appData->world)),
fFirstInit(true),
fVisible(false),
- fResizable(true),
fUsingEmbed(false),
- fWidth(1),
- fHeight(1),
fScaling(1.0),
fAutoScaling(1.0),
- fTitle(nullptr),
fWidgets(),
- fModal(),
-#if defined(DISTRHO_OS_HAIKU)
- bApplication(nullptr),
- bView(nullptr),
- bWindow(nullptr)
-#elif defined(DISTRHO_OS_MAC)
- fNeedsIdle(true),
- mView(nullptr),
- mWindow(nullptr),
- mParentWindow(nullptr)
-# ifndef DGL_FILE_BROWSER_DISABLED
- , fOpenFilePanel(nullptr),
- fFilePanelDelegate(nullptr)
-# endif
-#elif defined(DISTRHO_OS_WINDOWS)
- hwnd(nullptr),
- hwndParent(nullptr)
-#else
- xDisplay(nullptr),
- xWindow(0)
-#endif
+ fModal()
{
- DBG("Creating window without parent..."); DBGF;
+ DGL_DBG("Creating window without parent..."); DGL_DBGF;
init();
}
- PrivateData(Application& app, Window* const self, Window& parent)
- : fApp(app),
+ PrivateData(Application::PrivateData* const appData, Window* const self, Window& transientWindow)
+ : fAppData(appData),
fSelf(self),
- fView(puglInit()),
+ fView(puglNewView(appData->world)),
fFirstInit(true),
fVisible(false),
- fResizable(true),
fUsingEmbed(false),
- fWidth(1),
- fHeight(1),
fScaling(1.0),
fAutoScaling(1.0),
- fTitle(nullptr),
fWidgets(),
- fModal(parent.pData),
-#if defined(DISTRHO_OS_HAIKU)
- bApplication(nullptr),
- bView(nullptr),
- bWindow(nullptr)
-#elif defined(DISTRHO_OS_MAC)
- fNeedsIdle(false),
- mView(nullptr),
- mWindow(nullptr),
- mParentWindow(nullptr)
-# ifndef DGL_FILE_BROWSER_DISABLED
- , fOpenFilePanel(nullptr),
- fFilePanelDelegate(nullptr)
-# endif
-#elif defined(DISTRHO_OS_WINDOWS)
- hwnd(nullptr),
- hwndParent(nullptr)
-#else
- xDisplay(nullptr),
- xWindow(0)
-#endif
+ fModal(transientWindow.pData)
{
- DBG("Creating window with parent..."); DBGF;
+ DGL_DBG("Creating window with parent..."); DGL_DBGF;
init();
- const PuglInternals* const parentImpl(parent.pData->fView->impl);
-
- // NOTE: almost a 1:1 copy of setTransientWinId()
-#if defined(DISTRHO_OS_HAIKU)
- // TODO
-#elif defined(DISTRHO_OS_MAC)
- mParentWindow = parentImpl->window;
-#elif defined(DISTRHO_OS_WINDOWS)
- hwndParent = parentImpl->hwnd;
- SetWindowLongPtr(hwnd, GWLP_HWNDPARENT, (LONG_PTR)hwndParent);
-#else
- XSetTransientForHint(xDisplay, xWindow, parentImpl->win);
-#endif
+ puglSetTransientFor(fView, transientWindow.getNativeWindowHandle());
}
- PrivateData(Application& app, Window* const self, const intptr_t parentId, const double scaling, const bool resizable)
- : fApp(app),
+ PrivateData(Application::PrivateData* const appData, Window* const self,
+ const uintptr_t parentWindowHandle,
+ const double scaling,
+ const bool resizable)
+ : fAppData(appData),
fSelf(self),
- fView(puglInit()),
+ fView(puglNewView(appData->world)),
fFirstInit(true),
- fVisible(parentId != 0),
- fResizable(resizable),
- fUsingEmbed(parentId != 0),
- fWidth(1),
- fHeight(1),
+ fVisible(parentWindowHandle != 0),
+ fUsingEmbed(parentWindowHandle != 0),
fScaling(scaling),
fAutoScaling(1.0),
- fTitle(nullptr),
fWidgets(),
- fModal(),
-#if defined(DISTRHO_OS_HAIKU)
- bApplication(nullptr),
- bView(nullptr),
- bWindow(nullptr)
-#elif defined(DISTRHO_OS_MAC)
- fNeedsIdle(parentId == 0),
- mView(nullptr),
- mWindow(nullptr),
- mParentWindow(nullptr)
-# ifndef DGL_FILE_BROWSER_DISABLED
- , fOpenFilePanel(nullptr),
- fFilePanelDelegate(nullptr)
-# endif
-#elif defined(DISTRHO_OS_WINDOWS)
- hwnd(nullptr),
- hwndParent(nullptr)
-#else
- xDisplay(nullptr),
- xWindow(0)
-#endif
+ fModal()
{
if (fUsingEmbed)
{
- DBG("Creating embedded window..."); DBGF;
- puglInitWindowParent(fView, parentId);
+ DGL_DBG("Creating embedded window..."); DGL_DBGF;
+ puglSetParentWindow(fView, parentWindowHandle);
}
else
{
- DBG("Creating window without parent..."); DBGF;
+ DGL_DBG("Creating window without parent..."); DGL_DBGF;
}
- init();
+ init(resizable);
if (fUsingEmbed)
{
- DBG("NOTE: Embed window is always visible and non-resizable\n");
- puglShowWindow(fView);
- fApp.pData->oneShown();
- fFirstInit = false;
+ DGL_DBG("NOTE: Embed window is always visible and non-resizable\n");
+// puglShowWindow(fView);
+// fAppData->oneWindowShown();
+// fFirstInit = false;
}
}
- void init()
- {
- if (fSelf == nullptr || fView == nullptr)
- {
- DBG("Failed!\n");
- return;
- }
-
- puglInitUserResizable(fView, fResizable);
- puglInitWindowSize(fView, static_cast<int>(fWidth), static_cast<int>(fHeight));
-
- puglSetHandle(fView, this);
- puglSetDisplayFunc(fView, onDisplayCallback);
- puglSetKeyboardFunc(fView, onKeyboardCallback);
- puglSetMotionFunc(fView, onMotionCallback);
- puglSetMouseFunc(fView, onMouseCallback);
- puglSetScrollFunc(fView, onScrollCallback);
- puglSetSpecialFunc(fView, onSpecialCallback);
- puglSetReshapeFunc(fView, onReshapeCallback);
- puglSetCloseFunc(fView, onCloseCallback);
-#ifndef DGL_FILE_BROWSER_DISABLED
- puglSetFileSelectedFunc(fView, fileBrowserSelectedCallback);
-#endif
-
- puglCreateWindow(fView, nullptr);
-
- PuglInternals* impl = fView->impl;
-
-#if defined(DISTRHO_OS_HAIKU)
- bApplication = impl->app;
- bView = impl->view;
- bWindow = impl->window;
-#elif defined(DISTRHO_OS_MAC)
- mView = impl->view;
- mWindow = impl->window;
- DISTRHO_SAFE_ASSERT(mView != nullptr);
- if (fUsingEmbed) {
- DISTRHO_SAFE_ASSERT(mWindow == nullptr);
- } else {
- DISTRHO_SAFE_ASSERT(mWindow != nullptr);
- }
-#elif defined(DISTRHO_OS_WINDOWS)
- hwnd = impl->hwnd;
- DISTRHO_SAFE_ASSERT(hwnd != 0);
-#else
- xDisplay = impl->display;
- xWindow = impl->win;
- DISTRHO_SAFE_ASSERT(xWindow != 0);
-
- if (! fUsingEmbed)
- {
- const pid_t pid = getpid();
- const Atom _nwp = XInternAtom(xDisplay, "_NET_WM_PID", False);
- XChangeProperty(xDisplay, xWindow, _nwp, XA_CARDINAL, 32, PropModeReplace, (const uchar*)&pid, 1);
-
- const Atom _wt = XInternAtom(xDisplay, "_NET_WM_WINDOW_TYPE", False);
-
- // Setting the window to both dialog and normal will produce a decorated floating dialog
- // Order is important: DIALOG needs to come before NORMAL
- const Atom _wts[2] = {
- XInternAtom(xDisplay, "_NET_WM_WINDOW_TYPE_DIALOG", False),
- XInternAtom(xDisplay, "_NET_WM_WINDOW_TYPE_NORMAL", False)
- };
- XChangeProperty(xDisplay, xWindow, _wt, XA_ATOM, 32, PropModeReplace, (const uchar*)&_wts, 2);
- }
-#endif
- puglEnterContext(fView);
-
- fApp.pData->windows.push_back(fSelf);
-
- DBG("Success!\n");
- }
-
~PrivateData()
{
- DBG("Destroying window..."); DBGF;
+ DGL_DBG("Destroying window..."); DGL_DBGF;
+#if 0
if (fModal.enabled)
{
exec_fini();
close();
}
+#endif
fWidgets.clear();
if (fUsingEmbed)
{
- puglHideWindow(fView);
- fApp.pData->oneHidden();
+// puglHideWindow(fView);
+// fAppData->oneWindowHidden();
}
if (fSelf != nullptr)
- {
- fApp.pData->windows.remove(fSelf);
- fSelf = nullptr;
- }
-
- if (fView != nullptr)
- {
- puglDestroy(fView);
- fView = nullptr;
- }
-
- if (fTitle != nullptr)
- {
- std::free(fTitle);
- fTitle = nullptr;
- }
-
-#if defined(DISTRHO_OS_HAIKU)
- bApplication = nullptr;
- bView = nullptr;
- bWindow = nullptr;
-#elif defined(DISTRHO_OS_MAC)
- mView = nullptr;
- mWindow = nullptr;
-#elif defined(DISTRHO_OS_WINDOWS)
- hwnd = 0;
-#else
- xDisplay = nullptr;
- xWindow = 0;
-#endif
+ fAppData->windows.remove(fSelf);
#if defined(DISTRHO_OS_MAC) && !defined(DGL_FILE_BROWSER_DISABLED)
if (fOpenFilePanel)
@@ -385,561 +242,194 @@ struct Window::PrivateData {
}
#endif
- DBG("Success!\n");
- }
-
- // -------------------------------------------------------------------
-
- void close()
- {
- DBG("Window close\n");
-
- if (fUsingEmbed)
- return;
-
- setVisible(false);
-
- if (! fFirstInit)
- {
- fApp.pData->oneHidden();
- fFirstInit = true;
- }
- }
-
- void exec(const bool lockWait)
- {
- DBG("Window exec\n");
- exec_init();
-
- if (lockWait)
- {
- for (; fVisible && fModal.enabled;)
- {
- idle();
- d_msleep(10);
- }
-
- exec_fini();
- }
- else
- {
- idle();
- }
- }
-
- // -------------------------------------------------------------------
-
- void exec_init()
- {
- DBG("Window modal loop starting..."); DBGF;
- DISTRHO_SAFE_ASSERT_RETURN(fModal.parent != nullptr, setVisible(true));
-
- fModal.enabled = true;
- fModal.parent->fModal.childFocus = this;
-
- fModal.parent->setVisible(true);
- setVisible(true);
-
- DBG("Ok\n");
- }
-
- void exec_fini()
- {
- DBG("Window modal loop stopping..."); DBGF;
- fModal.enabled = false;
-
- if (fModal.parent != nullptr)
- {
- fModal.parent->fModal.childFocus = nullptr;
-
- // the mouse position probably changed since the modal appeared,
- // so send a mouse motion event to the modal's parent window
-#if defined(DISTRHO_OS_HAIKU)
- // TODO
-#elif defined(DISTRHO_OS_MAC)
- // TODO
-#elif defined(DISTRHO_OS_WINDOWS)
- // TODO
-#else
- int i, wx, wy;
- uint u;
- ::Window w;
- if (XQueryPointer(fModal.parent->xDisplay, fModal.parent->xWindow, &w, &w, &i, &i, &wx, &wy, &u) == True)
- fModal.parent->onPuglMotion(wx, wy);
-#endif
- }
-
- DBG("Ok\n");
- }
-
- // -------------------------------------------------------------------
-
- void focus()
- {
- DBG("Window focus\n");
-#if defined(DISTRHO_OS_HAIKU)
- if (bWindow != nullptr)
- {
- if (bWindow->LockLooper())
- {
- bWindow->Activate(true);
- bWindow->UnlockLooper();
- }
- }
- else
- {
- bView->MakeFocus(true);
- }
-#elif defined(DISTRHO_OS_MAC)
- if (mWindow != nullptr)
- [mWindow makeKeyWindow];
-#elif defined(DISTRHO_OS_WINDOWS)
- SetForegroundWindow(hwnd);
- SetActiveWindow(hwnd);
- SetFocus(hwnd);
-#else
- XRaiseWindow(xDisplay, xWindow);
- XSetInputFocus(xDisplay, xWindow, RevertToPointerRoot, CurrentTime);
- XFlush(xDisplay);
-#endif
- }
-
- // -------------------------------------------------------------------
-
- void setVisible(const bool yesNo)
- {
- if (fVisible == yesNo)
- {
- DBG("Window setVisible matches current state, ignoring request\n");
- return;
- }
- if (fUsingEmbed)
- {
- DBG("Window setVisible cannot be called when embedded\n");
- return;
- }
-
- DBG("Window setVisible called\n");
-
- fVisible = yesNo;
-
- if (yesNo && fFirstInit)
- setSize(fWidth, fHeight, true);
-
-#if defined(DISTRHO_OS_HAIKU)
- if (bWindow != nullptr)
- {
- if (bWindow->LockLooper())
- {
- if (yesNo)
- bWindow->Show();
- else
- bWindow->Hide();
-
- // TODO use flush?
- bWindow->Sync();
- bWindow->UnlockLooper();
- }
- }
- else
- {
- if (yesNo)
- bView->Show();
- else
- bView->Hide();
- }
-#elif defined(DISTRHO_OS_MAC)
- if (yesNo)
- {
- if (mWindow != nullptr)
- {
- if (mParentWindow != nullptr)
- [mParentWindow addChildWindow:mWindow
- ordered:NSWindowAbove];
-
- [mWindow setIsVisible:YES];
- }
- else
- {
- [mView setHidden:NO];
- }
- }
- else
- {
- if (mWindow != nullptr)
- {
- if (mParentWindow != nullptr)
- [mParentWindow removeChildWindow:mWindow];
-
- [mWindow setIsVisible:NO];
- }
- else
- {
- [mView setHidden:YES];
- }
- }
-#elif defined(DISTRHO_OS_WINDOWS)
- if (yesNo)
- {
- if (fFirstInit)
- {
- RECT rectChild, rectParent;
-
- if (hwndParent != nullptr &&
- GetWindowRect(hwnd, &rectChild) &&
- GetWindowRect(hwndParent, &rectParent))
- {
- SetWindowPos(hwnd, hwndParent,
- rectParent.left + (rectChild.right-rectChild.left)/2,
- rectParent.top + (rectChild.bottom-rectChild.top)/2,
- 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE);
- }
- else
- {
- ShowWindow(hwnd, SW_SHOWNORMAL);
- }
- }
- else
- {
- ShowWindow(hwnd, SW_RESTORE);
- }
- }
- else
- {
- ShowWindow(hwnd, SW_HIDE);
- }
-
- UpdateWindow(hwnd);
-#else
- if (yesNo)
- XMapRaised(xDisplay, xWindow);
- else
- XUnmapWindow(xDisplay, xWindow);
-
- XFlush(xDisplay);
-#endif
-
- if (yesNo)
- {
- if (fFirstInit)
- {
- fApp.pData->oneShown();
- fFirstInit = false;
- }
- }
- else if (fModal.enabled)
- exec_fini();
- }
-
- // -------------------------------------------------------------------
-
- void setResizable(const bool yesNo)
- {
- if (fResizable == yesNo)
- {
- DBG("Window setResizable matches current state, ignoring request\n");
- return;
- }
- if (fUsingEmbed)
- {
- DBG("Window setResizable cannot be called when embedded\n");
- return;
- }
-
- DBG("Window setResizable called\n");
-
- fResizable = yesNo;
- fView->user_resizable = yesNo;
-
-#if defined(DISTRHO_OS_HAIKU)
- // TODO
- // B_NO_BORDER
- // B_TITLED_WINDOW_LOOK
- // bWindow->SetFlags();
-#elif defined(DISTRHO_OS_MAC)
- const uint flags = yesNo ? (NSViewWidthSizable|NSViewHeightSizable) : 0x0;
- [mView setAutoresizingMask:flags];
-#elif 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);
-#endif
-
- setSize(fWidth, fHeight, true);
- }
-
- // -------------------------------------------------------------------
-
- void setGeometryConstraints(uint width, uint height, bool aspect)
- {
- // Did you forget to set DISTRHO_UI_USER_RESIZABLE ?
- DISTRHO_SAFE_ASSERT_RETURN(fResizable,);
-
- fView->min_width = width;
- fView->min_height = height;
- puglUpdateGeometryConstraints(fView, width, height, aspect);
- }
-
- // -------------------------------------------------------------------
-
- void setSize(uint width, uint height, const bool forced = false)
- {
- if (width <= 1 || height <= 1)
- {
- DBGp("Window setSize called with invalid value(s) %i %i, ignoring request\n", width, height);
- return;
- }
-
- if (fWidth == width && fHeight == height && ! forced)
- {
- DBGp("Window setSize matches current size, ignoring request (%i %i)\n", width, height);
- return;
- }
-
- fWidth = width;
- fHeight = 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_HAIKU)
- bView->ResizeTo(width, height);
-
- if (bWindow != nullptr && bWindow->LockLooper())
- {
- bWindow->MoveTo(50, 50);
- bWindow->ResizeTo(width, height);
-
- if (! forced)
- bWindow->Flush();
-
- bWindow->UnlockLooper();
- }
- // TODO resizable
-#elif defined(DISTRHO_OS_MAC)
- [mView setFrame:NSMakeRect(0, 0, width, height)];
-
- if (mWindow != nullptr)
- {
- const NSSize size = NSMakeSize(width, height);
- [mWindow setContentSize:size];
-
- if (fResizable)
- {
- [mWindow setContentMinSize:NSMakeSize(1, 1)];
- [mWindow setContentMaxSize:NSMakeSize(99999, 99999)];
- [[mWindow standardWindowButton:NSWindowZoomButton] setHidden:NO];
- }
- else
- {
- [mWindow setContentMinSize:size];
- [mWindow setContentMaxSize:size];
- [[mWindow standardWindowButton:NSWindowZoomButton] setHidden:YES];
- }
- }
-#elif defined(DISTRHO_OS_WINDOWS)
- 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, 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);
-
- if (! forced)
- UpdateWindow(hwnd);
-#else
-
- if (! fResizable)
- {
- XSizeHints sizeHints;
- memset(&sizeHints, 0, sizeof(sizeHints));
-
- sizeHints.flags = PSize|PMinSize|PMaxSize;
- sizeHints.width = static_cast<int>(width);
- sizeHints.height = static_cast<int>(height);
- sizeHints.min_width = static_cast<int>(width);
- sizeHints.min_height = static_cast<int>(height);
- sizeHints.max_width = static_cast<int>(width);
- sizeHints.max_height = static_cast<int>(height);
-
- XSetWMNormalHints(xDisplay, xWindow, &sizeHints);
- }
-
- XResizeWindow(xDisplay, xWindow, width, height);
-
- if (! forced)
- XFlush(xDisplay);
-#endif
+ if (fView != nullptr)
+ puglFreeView(fView);
- puglPostRedisplay(fView);
+ DGL_DBG("Success!\n");
}
// -------------------------------------------------------------------
+ // stuff that uses pugl internals or build-specific things
- const char* getTitle() const noexcept
- {
- static const char* const kFallback = "";
+ void init(const bool resizable = false);
+ void setVisible(const bool visible);
+ void windowSpecificIdle();
+ static PuglStatus puglEventCallback(PuglView* const view, const PuglEvent* const event);
- return fTitle != nullptr ? fTitle : kFallback;
- }
+ // -------------------------------------------------------------------
- void setTitle(const char* const title)
+ void close()
{
- DBGp("Window setTitle \"%s\"\n", title);
+ DGL_DBG("Window close\n");
- if (fTitle != nullptr)
- std::free(fTitle);
+ if (fUsingEmbed)
+ return;
- fTitle = strdup(title);
+ setVisible(false);
-#if defined(DISTRHO_OS_HAIKU)
- if (bWindow != nullptr&& bWindow->LockLooper())
- {
- bWindow->SetTitle(title);
- bWindow->UnlockLooper();
- }
-#elif defined(DISTRHO_OS_MAC)
- if (mWindow != nullptr)
+ if (! fFirstInit)
{
- NSString* titleString = [[NSString alloc]
- initWithBytes:title
- length:strlen(title)
- encoding:NSUTF8StringEncoding];
-
- [mWindow setTitle:titleString];
+ fAppData->oneWindowHidden();
+ fFirstInit = true;
}
-#elif defined(DISTRHO_OS_WINDOWS)
- SetWindowTextA(hwnd, title);
-#else
- XStoreName(xDisplay, xWindow, title);
- Atom netWmName = XInternAtom(xDisplay, "_NET_WM_NAME", False);
- Atom utf8String = XInternAtom(xDisplay, "UTF8_STRING", False);
- XChangeProperty(xDisplay, xWindow, netWmName, utf8String, 8, PropModeReplace, (unsigned char *)title, strlen(title));
-#endif
- }
-
- void setTransientWinId(const uintptr_t winId)
- {
- DISTRHO_SAFE_ASSERT_RETURN(winId != 0,);
-
-#if defined(DISTRHO_OS_HAIKU)
- // TODO
-#elif defined(DISTRHO_OS_MAC)
- NSWindow* const parentWindow = [NSApp windowWithWindowNumber:winId];
- DISTRHO_SAFE_ASSERT_RETURN(parentWindow != nullptr,);
-
- [parentWindow addChildWindow:mWindow
- ordered:NSWindowAbove];
-#elif defined(DISTRHO_OS_WINDOWS)
- hwndParent = (HWND)winId;
- SetWindowLongPtr(hwnd, GWLP_HWNDPARENT, (LONG_PTR)winId);
-#else
- XSetTransientForHint(xDisplay, xWindow, static_cast< ::Window>(winId));
-#endif
}
// -------------------------------------------------------------------
- double getScaling() const noexcept
+ void addWidget(Widget* const widget)
{
- return fScaling;
+ fWidgets.push_back(widget);
}
- void setAutoScaling(const double scaling) noexcept
+ void removeWidget(Widget* const widget)
{
- DISTRHO_SAFE_ASSERT_RETURN(scaling > 0.0,);
-
- fAutoScaling = scaling;
+ fWidgets.remove(widget);
}
// -------------------------------------------------------------------
- bool getIgnoringKeyRepeat() const noexcept
+ void onPuglClose()
{
- return fView->ignoreKeyRepeat;
- }
+ DGL_DBG("PUGL: onClose\n");
- void setIgnoringKeyRepeat(bool ignore) noexcept
- {
- puglIgnoreKeyRepeat(fView, ignore);
- }
+// if (fModal.enabled)
+// exec_fini();
- // -------------------------------------------------------------------
+ fSelf->onClose();
- void addWidget(Widget* const widget)
- {
- fWidgets.push_back(widget);
+ if (fModal.childFocus != nullptr)
+ fModal.childFocus->fSelf->onClose();
+
+ close();
}
- void removeWidget(Widget* const widget)
+ void onPuglDisplay()
{
- fWidgets.remove(widget);
+ fSelf->onDisplayBefore();
+
+ if (fWidgets.size() != 0)
+ {
+ const PuglRect rect = puglGetFrame(fView);
+ const int width = rect.width;
+ const int height = rect.height;
+
+ FOR_EACH_WIDGET(it)
+ {
+ Widget* const widget(*it);
+ widget->pData->display(width, height, fAutoScaling, false);
+ }
+ }
+
+ fSelf->onDisplayAfter();
}
- void idle()
+ void onPuglReshape(const int width, const int height)
{
- puglProcessEvents(fView);
+ DISTRHO_SAFE_ASSERT_INT2_RETURN(width > 1 && height > 1, width, height,);
+
+ DGL_DBGp("PUGL: onReshape : %i %i\n", width, height);
-#ifdef DISTRHO_OS_HAIKU
- if (bApplication != nullptr)
+ fSelf->onReshape(width, height);
+
+ FOR_EACH_WIDGET(it)
{
- // bApplication->Lock();
- // bApplication->Loop();
- // bApplication->Unlock();
+ Widget* const widget(*it);
+
+ if (widget->pData->needsFullViewport)
+ widget->setSize(width, height);
}
+ }
+
+ // -------------------------------------------------------------------
+
+#ifdef DISTRHO_DEFINES_H_INCLUDED
+ friend class DISTRHO_NAMESPACE::UI;
#endif
+ DISTRHO_DECLARE_NON_COPY_STRUCT(PrivateData)
+};
-#ifdef DISTRHO_OS_MAC
- if (fNeedsIdle)
- {
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSEvent* event;
+// -----------------------------------------------------------------------
- for (;;)
- {
- event = [NSApp
- nextEventMatchingMask:NSAnyEventMask
- untilDate:[NSDate distantPast]
- inMode:NSDefaultRunLoopMode
- dequeue:YES];
+END_NAMESPACE_DGL
+
+
+#if 0
+// -----------------------------------------------------------------------
+// Window Private
+
+struct Window::PrivateData {
+ // -------------------------------------------------------------------
- if (event == nil)
- break;
+ void exec(const bool lockWait)
+ {
+ DBG("Window exec\n");
+ exec_init();
- [NSApp sendEvent: event];
+ if (lockWait)
+ {
+ for (; fVisible && fModal.enabled;)
+ {
+ idle();
+ d_msleep(10);
}
- [pool release];
+ exec_fini();
}
-#endif
-
-#if defined(DISTRHO_OS_WINDOWS) && !defined(DGL_FILE_BROWSER_DISABLED)
- if (fSelectedFile.isNotEmpty())
+ else
{
- char* const buffer = fSelectedFile.getAndReleaseBuffer();
- fView->fileSelectedFunc(fView, buffer);
- std::free(buffer);
+ idle();
}
-#endif
-
- if (fModal.enabled && fModal.parent != nullptr)
- fModal.parent->idle();
}
// -------------------------------------------------------------------
- void onPuglDisplay()
+ void exec_init()
{
- fSelf->onDisplayBefore();
+ DBG("Window modal loop starting..."); DBGF;
+ DISTRHO_SAFE_ASSERT_RETURN(fModal.parent != nullptr, setVisible(true));
- FOR_EACH_WIDGET(it)
+ fModal.enabled = true;
+ fModal.parent->fModal.childFocus = this;
+
+ fModal.parent->setVisible(true);
+ setVisible(true);
+
+ DBG("Ok\n");
+ }
+
+ void exec_fini()
+ {
+ DBG("Window modal loop stopping..."); DBGF;
+ fModal.enabled = false;
+
+ if (fModal.parent != nullptr)
{
- Widget* const widget(*it);
- widget->pData->display(fWidth, fHeight, fAutoScaling, false);
+ fModal.parent->fModal.childFocus = nullptr;
+
+ // the mouse position probably changed since the modal appeared,
+ // so send a mouse motion event to the modal's parent window
+#if defined(DISTRHO_OS_HAIKU)
+ // TODO
+#elif defined(DISTRHO_OS_MAC)
+ // TODO
+#elif defined(DISTRHO_OS_WINDOWS)
+ // TODO
+#else
+ int i, wx, wy;
+ uint u;
+ ::Window w;
+ if (XQueryPointer(fModal.parent->xDisplay, fModal.parent->xWindow, &w, &w, &i, &i, &wx, &wy, &u) == True)
+ fModal.parent->onPuglMotion(wx, wy);
+#endif
}
- fSelf->onDisplayAfter();
+ DBG("Ok\n");
}
+ // -------------------------------------------------------------------
+
+ // -------------------------------------------------------------------
+
int onPuglKeyboard(const bool press, const uint key)
{
DBGp("PUGL: onKeyboard : %i %i\n", press, key);
@@ -1077,42 +567,6 @@ struct Window::PrivateData {
}
}
- void onPuglReshape(const int width, const int height)
- {
- DBGp("PUGL: onReshape : %i %i\n", width, height);
-
- if (width <= 1 && height <= 1)
- return;
-
- fWidth = static_cast<uint>(width);
- fHeight = static_cast<uint>(height);
-
- fSelf->onReshape(fWidth, fHeight);
-
- FOR_EACH_WIDGET(it)
- {
- Widget* const widget(*it);
-
- if (widget->pData->needsFullViewport)
- widget->setSize(fWidth, fHeight);
- }
- }
-
- void onPuglClose()
- {
- DBG("PUGL: onClose\n");
-
- if (fModal.enabled)
- exec_fini();
-
- fSelf->onClose();
-
- if (fModal.childFocus != nullptr)
- fModal.childFocus->fSelf->onClose();
-
- close();
- }
-
// -------------------------------------------------------------------
bool handlePluginKeyboard(const bool press, const uint key)
@@ -1232,124 +686,11 @@ struct Window::PrivateData {
// -------------------------------------------------------------------
- Application& fApp;
- Window* fSelf;
- GraphicsContext fContext;
- PuglView* fView;
-
- bool fFirstInit;
- bool fVisible;
- bool fResizable;
- bool fUsingEmbed;
- uint fWidth;
- uint fHeight;
- double fScaling;
- double fAutoScaling;
- char* fTitle;
- std::list<Widget*> fWidgets;
-
- struct Modal {
- bool enabled;
- PrivateData* parent;
- PrivateData* childFocus;
-
- Modal()
- : enabled(false),
- parent(nullptr),
- childFocus(nullptr) {}
-
- Modal(PrivateData* const p)
- : enabled(false),
- parent(p),
- childFocus(nullptr) {}
-
- ~Modal()
- {
- DISTRHO_SAFE_ASSERT(! enabled);
- DISTRHO_SAFE_ASSERT(childFocus == nullptr);
- }
-
- DISTRHO_DECLARE_NON_COPY_STRUCT(Modal)
- } fModal;
-
-#if defined(DISTRHO_OS_HAIKU)
- BApplication* bApplication;
- BView* bView;
- BWindow* bWindow;
-#elif defined(DISTRHO_OS_MAC)
- bool fNeedsIdle;
- NSView<PuglGenericView>* mView;
- id mWindow;
- id mParentWindow;
-# ifndef DGL_FILE_BROWSER_DISABLED
- NSOpenPanel* fOpenFilePanel;
- id fFilePanelDelegate;
-# endif
-#elif defined(DISTRHO_OS_WINDOWS)
- HWND hwnd;
- HWND hwndParent;
-# ifndef DGL_FILE_BROWSER_DISABLED
- String fSelectedFile;
-# endif
-#else
- Display* xDisplay;
- ::Window xWindow;
-#endif
-
- // -------------------------------------------------------------------
- // Callbacks
-
- #define handlePtr ((PrivateData*)puglGetHandle(view))
-
- static void onDisplayCallback(PuglView* view)
- {
- handlePtr->onPuglDisplay();
- }
-
- static int onKeyboardCallback(PuglView* view, bool press, uint32_t key)
- {
- return handlePtr->onPuglKeyboard(press, key);
- }
-
- static int onSpecialCallback(PuglView* view, bool press, PuglKey key)
- {
- return handlePtr->onPuglSpecial(press, static_cast<Key>(key));
- }
-
- static void onMouseCallback(PuglView* view, int button, bool press, int x, int y)
- {
- handlePtr->onPuglMouse(button, press, x, y);
- }
-
- static void onMotionCallback(PuglView* view, int x, int y)
- {
- handlePtr->onPuglMotion(x, y);
- }
-
- static void onScrollCallback(PuglView* view, int x, int y, float dx, float dy)
- {
- handlePtr->onPuglScroll(x, y, dx, dy);
- }
-
- static void onReshapeCallback(PuglView* view, int width, int height)
- {
- handlePtr->onPuglReshape(width, height);
- }
-
- static void onCloseCallback(PuglView* view)
- {
- handlePtr->onPuglClose();
- }
-
-#ifndef DGL_FILE_BROWSER_DISABLED
- static void fileBrowserSelectedCallback(PuglView* view, const char* filename)
- {
- handlePtr->fSelf->fileBrowserSelected(filename);
- }
-#endif
-
- #undef handlePtr
-
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData)
};
#endif
+
+// #undef DGL_DBG
+// #undef DGL_DBGF
+
+#endif // DGL_WINDOW_PRIVATE_DATA_HPP_INCLUDED
diff --git a/dgl/src/pugl-extra/extras.c b/dgl/src/pugl-extra/extras.c
@@ -0,0 +1,29 @@
+/*
+ Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com>
+
+ 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 extras.c pugl extra implementations for DPF.
+*/
+
+#include "extras.h"
+
+#include "../pugl-upstream/src/implementation.h"
+
+const char*
+puglGetWindowTitle(const PuglView* view)
+{
+ return view->title;
+}
diff --git a/dgl/src/pugl-extra/extras.h b/dgl/src/pugl-extra/extras.h
@@ -0,0 +1,50 @@
+/*
+ Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com>
+
+ 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 pugl extra API for DPF.
+*/
+
+#ifndef PUGL_EXTRAS_PUGL_H
+#define PUGL_EXTRAS_PUGL_H
+
+#include "../pugl-upstream/include/pugl/pugl.h"
+
+PUGL_BEGIN_DECLS
+
+PUGL_API const char*
+puglGetWindowTitle(const PuglView* view);
+
+PUGL_API int
+puglGetViewHint(const PuglView* view, PuglViewHint hint);
+
+PUGL_API void
+puglRaiseWindow(PuglView* view);
+
+PUGL_API void
+puglSetWindowSize(PuglView* view, unsigned int width, unsigned int height);
+
+PUGL_API void
+puglUpdateGeometryConstraints(PuglView* view, unsigned int width, unsigned int height, bool aspect);
+
+#ifdef DISTRHO_OS_WINDOWS
+PUGL_API void
+puglWin32SetWindowResizable(PuglView* view, bool resizable);
+#endif
+
+PUGL_END_DECLS
+
+#endif // PUGL_EXTRAS_PUGL_H
diff --git a/dgl/src/pugl-extra/haiku.cpp b/dgl/src/pugl-extra/haiku.cpp
@@ -0,0 +1,81 @@
+/*
+ Copyright 2012-2019 David Robillard <http://drobilla.net>
+ Copyright 2019-2020 Filipe Coelho <falktx@falktx.com>
+
+ 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 mac.cpp HaikuOS implementation.
+*/
+
+#include "haiku.h"
+
+#include "pugl/detail/implementation.h"
+
+PuglStatus
+puglGrabFocus(PuglView* view)
+{
+ view->impl->bView->MakeFocus(true);
+ return PUGL_SUCCESS;
+}
+
+// extras follow
+
+void
+puglRaiseWindow(PuglView* view)
+{
+}
+
+void
+puglSetWindowSize(PuglView* view, unsigned int width, unsigned int height)
+{
+ bView->ResizeTo(width, height);
+
+ if (bWindow != nullptr && bWindow->LockLooper())
+ {
+ bWindow->MoveTo(50, 50);
+ bWindow->ResizeTo(width, height);
+
+ if (! forced)
+ bWindow->Flush();
+
+ bWindow->UnlockLooper();
+ }
+ // TODO resizable
+}
+
+void setVisible(const bool yesNo)
+{
+ if (bWindow != nullptr)
+ {
+ if (bWindow->LockLooper())
+ {
+ if (yesNo)
+ bWindow->Show();
+ else
+ bWindow->Hide();
+
+ // TODO use flush?
+ bWindow->Sync();
+ bWindow->UnlockLooper();
+ }
+ }
+ else
+ {
+ if (yesNo)
+ bView->Show();
+ else
+ bView->Hide();
+ }
+}
diff --git a/dgl/src/pugl-extra/haiku.h b/dgl/src/pugl-extra/haiku.h
@@ -0,0 +1,35 @@
+/*
+ Copyright 2012-2019 David Robillard <http://drobilla.net>
+ Copyright 2019-2020 Filipe Coelho <falktx@falktx.com>
+
+ 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 haiku.h Shared definitions for HaikuOS implementation.
+*/
+
+#include "pugl/pugl.h"
+
+#include <Application.h>
+#include <Window.h>
+// using? interface/
+
+struct PuglWorldInternalsImpl {
+ BApplication* app;
+};
+
+struct PuglInternalsImpl {
+ BViewType* view;
+ BWindow* window;
+};
diff --git a/dgl/src/pugl-extra/mac.m b/dgl/src/pugl-extra/mac.m
@@ -0,0 +1,48 @@
+/*
+ Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com>
+
+ 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 mac.m MacOS extra implementation for DPF.
+*/
+
+#include "pugl/detail/mac.h"
+
+void
+puglRaiseWindow(PuglView* view)
+{
+}
+
+void
+puglSetWindowSize(PuglView* view, unsigned int width, unsigned int height)
+{
+ // NOTE: pugl mac code does nothing with x and y
+ const PuglRect frame = { 0.0, 0.0, (double)width, (double)height };
+ puglSetFrame(view, frame);
+}
+
+void
+puglUpdateGeometryConstraints(PuglView* view, unsigned int width, unsigned int height, bool aspect)
+{
+ // NOTE this is a combination of puglSetMinSize and puglSetAspectRatio
+ view->minWidth = width;
+ view->minHeight = height;
+
+ [view->impl->window setContentMinSize:sizePoints(view, width, height)];
+
+ if (aspect) {
+ [view->impl->window setContentAspectRatio:sizePoints(view, width, height)];
+ }
+}
diff --git a/dgl/src/pugl-extra/win.c b/dgl/src/pugl-extra/win.c
@@ -0,0 +1,118 @@
+/*
+ Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com>
+
+ 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 win.c Windows extra implementation for DPF.
+*/
+
+#include "pugl/detail/win.h"
+
+#include "pugl/detail/implementation.h"
+
+void
+puglRaiseWindow(PuglView* view)
+{
+ SetForegroundWindow(view->impl->hwnd);
+ SetActiveWindow(view->impl->hwnd);
+ return PUGL_SUCCESS;
+}
+
+void
+puglSetWindowSize(PuglView* view, unsigned int width, unsigned int height)
+{
+ view->frame.width = width;
+ view->frame.height = height;
+
+ // NOTE the following code matches upstream pugl, except we add SWP_NOMOVE flag
+ if (view->impl->hwnd) {
+ RECT rect = { (long)frame.x,
+ (long)frame.y,
+ (long)frame.x + (long)frame.width,
+ (long)frame.y + (long)frame.height };
+
+ AdjustWindowRectEx(&rect, puglWinGetWindowFlags(view),
+ FALSE,
+ puglWinGetWindowExFlags(view));
+
+ SetWindowPos(view->impl->hwnd,
+ HWND_TOP,
+ rect.left,
+ rect.top,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER);
+ }
+}
+
+void
+puglUpdateGeometryConstraints(PuglView* view, unsigned int width, unsigned int height, bool aspect)
+{
+ // NOTE this is a combination of puglSetMinSize and puglSetAspectRatio, but stilL TODO on pugl
+ Display* display = view->world->impl->display;
+
+ view->minWidth = width;
+ view->minHeight = height;
+
+ if (aspect) {
+ view->minAspectX = width;
+ view->minAspectY = height;
+ view->maxAspectX = width;
+ view->maxAspectY = height;
+ }
+}
+
+void
+puglWin32RestoreWindow(PuglView* view)
+{
+ PuglInternals* impl = view->impl;
+
+ ShowWindow(impl->hwnd, SW_RESTORE);
+ SetFocus(impl->hwnd);
+}
+
+void
+puglWin32ShowWindowCentered(PuglView* view)
+{
+ PuglInternals* impl = view->impl;
+
+ RECT rectChild, rectParent;
+
+ if (impl->transientParent != 0 &&
+ GetWindowRect(impl->hwnd, &rectChild) &&
+ GetWindowRect(impl->transientParent, &rectParent))
+ {
+ SetWindowPos(impl->hwnd, (HWND)impl->transientParent,
+ rectParent.left + (rectChild.right-rectChild.left)/2,
+ rectParent.top + (rectChild.bottom-rectChild.top)/2,
+ 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE);
+ }
+ else
+ {
+ ShowWindow(hwnd, SW_SHOWNORMAL);
+ }
+
+ SetFocus(impl->hwnd);
+}
+
+void
+puglWin32SetWindowResizable(PuglView* view, bool resizable)
+{
+ PuglInternals* impl = view->impl;
+
+ const int winFlags = resizable ? GetWindowLong(hwnd, GWL_STYLE) | WS_SIZEBOX
+ : GetWindowLong(hwnd, GWL_STYLE) & ~WS_SIZEBOX;
+ SetWindowLong(impl->hwnd, GWL_STYLE, winFlags);
+}
diff --git a/dgl/src/pugl-extra/x11.c b/dgl/src/pugl-extra/x11.c
@@ -0,0 +1,111 @@
+/*
+ Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com>
+
+ 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 x11.c X11 extra implementation for DPF.
+*/
+
+// NOTE can't import this file twice!
+#ifndef PUGL_DETAIL_X11_H_INCLUDED
+#include "../pugl-upstream/src/x11.h"
+#endif
+
+#include "../pugl-upstream/src/implementation.h"
+
+#include <sys/types.h>
+#include <unistd.h>
+
+void
+puglRaiseWindow(PuglView* view)
+{
+ XRaiseWindow(view->impl->display, view->impl->win);
+}
+
+void
+puglSetWindowSize(PuglView* view, unsigned int width, unsigned int height)
+{
+ view->frame.width = width;
+ view->frame.height = height;
+
+ if (view->impl->win) {
+#if 0
+ if (! fResizable)
+ {
+ XSizeHints sizeHints;
+ memset(&sizeHints, 0, sizeof(sizeHints));
+
+ sizeHints.flags = PSize|PMinSize|PMaxSize;
+ sizeHints.width = static_cast<int>(width);
+ sizeHints.height = static_cast<int>(height);
+ sizeHints.min_width = static_cast<int>(width);
+ sizeHints.min_height = static_cast<int>(height);
+ sizeHints.max_width = static_cast<int>(width);
+ sizeHints.max_height = static_cast<int>(height);
+
+ XSetWMNormalHints(xDisplay, xWindow, &sizeHints);
+ }
+#endif
+
+ XResizeWindow(view->world->impl->display, view->impl->win, width, height);
+ }
+}
+
+void
+puglUpdateGeometryConstraints(PuglView* view, unsigned int width, unsigned int height, bool aspect)
+{
+ // NOTE this is a combination of puglSetMinSize and puglSetAspectRatio
+ Display* display = view->world->impl->display;
+
+ view->minWidth = width;
+ view->minHeight = height;
+
+ if (aspect) {
+ view->minAspectX = width;
+ view->minAspectY = height;
+ view->maxAspectX = width;
+ view->maxAspectY = height;
+ }
+
+#if 0
+ if (view->impl->win) {
+ XSizeHints sizeHints = getSizeHints(view);
+ XSetNormalHints(display, view->impl->win, &sizeHints);
+ // NOTE old code used this instead
+ // XSetWMNormalHints(display, view->impl->win, &sizeHints);
+ }
+#endif
+}
+
+void
+puglExtraSetWindowTypeAndPID(PuglView* view)
+{
+ PuglInternals* const impl = view->impl;
+
+ const pid_t pid = getpid();
+ const Atom _nwp = XInternAtom(impl->display, "_NET_WM_PID", False);
+ XChangeProperty(impl->display, impl->win, _nwp, XA_CARDINAL, 32, PropModeReplace, (const uchar*)&pid, 1);
+
+ const Atom _wt = XInternAtom(impl->display, "_NET_WM_WINDOW_TYPE", False);
+
+ // Setting the window to both dialog and normal will produce a decorated floating dialog
+ // Order is important: DIALOG needs to come before NORMAL
+ const Atom _wts[2] = {
+ XInternAtom(impl->display, "_NET_WM_WINDOW_TYPE_DIALOG", False),
+ XInternAtom(impl->display, "_NET_WM_WINDOW_TYPE_NORMAL", False)
+ };
+
+ XChangeProperty(impl->display, impl->win, _wt, XA_ATOM, 32, PropModeReplace, (const uchar*)&_wts, 2);
+}
diff --git a/distrho/src/DistrhoPluginVST.cpp b/distrho/src/DistrhoPluginVST.cpp
@@ -22,6 +22,7 @@
#endif
#if DISTRHO_PLUGIN_HAS_UI
+# define DISTRHO_UI_IS_STANDALONE 0
# include "DistrhoUIInternal.hpp"
#endif
diff --git a/distrho/src/DistrhoUI.cpp b/distrho/src/DistrhoUI.cpp
@@ -38,7 +38,6 @@ Window* d_lastUiWindow = nullptr;
// -----------------------------------------------------------------------------------------------------------
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
-static inline
UI* createUiWrapper(void* const dspPtr, const uintptr_t winId, const double scaleFactor, const char* const bundlePath)
{
d_lastUiDspPtr = dspPtr;
@@ -53,7 +52,6 @@ UI* createUiWrapper(void* const dspPtr, const uintptr_t winId, const double scal
return ret;
}
#else
-static inline
UI* createUiWrapper(void* const dspPtr, Window* const window)
{
d_lastUiDspPtr = dspPtr;
diff --git a/distrho/src/DistrhoUIDSSI.cpp b/distrho/src/DistrhoUIDSSI.cpp
@@ -14,6 +14,7 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#define DISTRHO_UI_IS_STANDALONE 1
#include "DistrhoUIInternal.hpp"
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
diff --git a/distrho/src/DistrhoUIInternal.hpp b/distrho/src/DistrhoUIInternal.hpp
@@ -203,7 +203,7 @@ public:
return fUI->isRunning();
}
- intptr_t getWindowId() const noexcept
+ uintptr_t getNativeWindowHandle() const noexcept
{
return 0;
}
@@ -223,9 +223,9 @@ public:
return glWindow.isVisible();
}
- intptr_t getWindowId() const noexcept
+ uintptr_t getNativeWindowHandle() const noexcept
{
- return glWindow.getWindowId();
+ return glWindow.getNativeWindowHandle();
}
#endif
diff --git a/distrho/src/DistrhoUILV2.cpp b/distrho/src/DistrhoUILV2.cpp
@@ -14,6 +14,7 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#define DISTRHO_UI_IS_STANDALONE 0
#include "DistrhoUIInternal.hpp"
#include "../extra/String.hpp"
@@ -100,7 +101,7 @@ public:
fUiResize->ui_resize(fUiResize->handle, fUI.getWidth(), fUI.getHeight());
if (widget != nullptr)
- *widget = (LV2UI_Widget)fUI.getWindowId();
+ *widget = (LV2UI_Widget)fUI.getNativeWindowHandle();
#if DISTRHO_PLUGIN_WANT_STATE
// tell the DSP we're ready to receive msgs