diff --git a/dgl/Base.hpp b/dgl/Base.hpp index c49740ad..1ecdb64d 100644 --- a/dgl/Base.hpp +++ b/dgl/Base.hpp @@ -1,6 +1,6 @@ /* * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2021 Filipe Coelho + * Copyright (C) 2012-2022 Filipe Coelho * * 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 @@ -159,15 +159,15 @@ enum MouseButton { This is a portable subset of mouse cursors that exist on X11, MacOS, and Windows. */ enum MouseCursor { - kMouseCursorArrow, ///< Default pointing arrow - kMouseCursorCaret, ///< Caret (I-Beam) for text entry - kMouseCursorCrosshair, ///< Cross-hair - kMouseCursorHand, ///< Hand with a pointing finger - kMouseCursorNotAllowed, ///< Operation not allowed - kMouseCursorLeftRight, ///< Left/right arrow for horizontal resize - kMouseCursorUpDown, ///< Up/down arrow for vertical resize - kMouseCursorDiagonal, ///< Top-left to bottom-right arrow for diagonal resize - kMouseCursorAntiDiagonal ///< Bottom-left to top-right arrow for diagonal resize + kMouseCursorArrow, ///< Default pointing arrow + kMouseCursorCaret, ///< Caret (I-Beam) for text entry + kMouseCursorCrosshair, ///< Cross-hair + kMouseCursorHand, ///< Hand with a pointing finger + kMouseCursorNotAllowed, ///< Operation not allowed + kMouseCursorLeftRight, ///< Left/right arrow for horizontal resize + kMouseCursorUpDown, ///< Up/down arrow for vertical resize + kMouseCursorDiagonal, ///< Top-left to bottom-right arrow for diagonal resize + kMouseCursorAntiDiagonal ///< Bottom-left to top-right arrow for diagonal resize }; /** @@ -178,11 +178,29 @@ enum MouseCursor { while a smooth scroll is for those with arbitrary scroll direction freedom, like some touchpads. */ enum ScrollDirection { - kScrollUp, ///< Scroll up - kScrollDown, ///< Scroll down - kScrollLeft, ///< Scroll left - kScrollRight, ///< Scroll right - kScrollSmooth ///< Smooth scroll in any direction + kScrollUp, ///< Scroll up + kScrollDown, ///< Scroll down + kScrollLeft, ///< Scroll left + kScrollRight, ///< Scroll right + kScrollSmooth ///< Smooth scroll in any direction +}; + +/** + A clipboard data offer. + @see Window::onClipboardDataOffer +*/ +struct ClipboardDataOffer { + /** + The id of this data offer. + @note The value 0 is reserved for null/invalid. + */ + uint32_t id; + + /** + The type of this data offer. + Usually a MIME type, but may also be another platform-specific type identifier. + */ + const char* type; }; // -------------------------------------------------------------------------------------------------------------------- diff --git a/dgl/TopLevelWidget.hpp b/dgl/TopLevelWidget.hpp index a9438552..47015a62 100644 --- a/dgl/TopLevelWidget.hpp +++ b/dgl/TopLevelWidget.hpp @@ -101,8 +101,8 @@ public: void repaint(const Rectangle& rect) noexcept; // TODO group stuff after here, convenience functions present in Window class + const void* getClipboard(size_t& dataSize); bool setClipboard(const char* mimeType, const void* data, size_t dataSize); - const void* getClipboard(const char*& mimeType, size_t& dataSize); bool setCursor(MouseCursor cursor); bool addIdleCallback(IdleCallback* callback, uint timerFrequencyInMs = 0); bool removeIdleCallback(IdleCallback* callback); diff --git a/dgl/Window.hpp b/dgl/Window.hpp index 51a7d2a3..5e80b1a9 100644 --- a/dgl/Window.hpp +++ b/dgl/Window.hpp @@ -1,6 +1,6 @@ /* * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2021 Filipe Coelho + * Copyright (C) 2012-2022 Filipe Coelho * * 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 @@ -23,6 +23,8 @@ # include "../distrho/extra/FileBrowserDialog.hpp" #endif +#include + START_NAMESPACE_DGL class Application; @@ -298,6 +300,16 @@ public: */ void setIgnoringKeyRepeat(bool ignore) noexcept; + /** + Get the clipboard contents. + + This gets the system clipboard contents, + which may have been set with setClipboard() or copied from another application. + + returns the clipboard contents, or null. + */ + const void* getClipboard(size_t& dataSize); + /** Set the clipboard contents. @@ -309,16 +321,6 @@ public: */ bool setClipboard(const char* mimeType, const void* data, size_t dataSize); - /** - Get the clipboard contents. - - This gets the system clipboard contents, - which may have been set with setClipboard() or copied from another application. - - returns the clipboard contents, or null. - */ - const void* getClipboard(const char*& mimeType, size_t& dataSize); - /** Set the mouse cursor. @@ -450,6 +452,23 @@ public: inline void exec(bool blockWait = false) { runAsModal(blockWait); } protected: + /** + Get the types available for the data in a clipboard. + Must only be called within the context of onClipboardDataOffer. + */ + std::vector getClipboardDataOfferTypes(); + + /** + A function called when clipboard has data present, possibly with several datatypes. + While handling this event, the data types can be investigated with getClipboardDataOfferTypes() to decide whether to accept the offer. + + Reimplement and return a non-zero id to accept the clipboard data offer for a particular type. + Applications must ignore any type they do not recognize. + + The default implementation does nothing. + */ + virtual uint32_t onClipboardDataOffer(); + /** A function called when the window is attempted to be closed. Returning true closes the window, which is the default behaviour. diff --git a/dgl/src/TopLevelWidget.cpp b/dgl/src/TopLevelWidget.cpp index f577a1c9..ab1fa4bf 100644 --- a/dgl/src/TopLevelWidget.cpp +++ b/dgl/src/TopLevelWidget.cpp @@ -60,14 +60,14 @@ void TopLevelWidget::setSize(const Size& size) pData->window.setSize(size); } -bool TopLevelWidget::setClipboard(const char* const mimeType, const void* const data, const size_t dataSize) +const void* TopLevelWidget::getClipboard(size_t& dataSize) { - return pData->window.setClipboard(mimeType, data, dataSize); + return pData->window.getClipboard(dataSize); } -const void* TopLevelWidget::getClipboard(const char*& mimeType, size_t& dataSize) +bool TopLevelWidget::setClipboard(const char* const mimeType, const void* const data, const size_t dataSize) { - return pData->window.getClipboard(mimeType, dataSize); + return pData->window.setClipboard(mimeType, data, dataSize); } bool TopLevelWidget::setCursor(const MouseCursor cursor) diff --git a/dgl/src/Window.cpp b/dgl/src/Window.cpp index 5ac3d8a7..dee9d189 100644 --- a/dgl/src/Window.cpp +++ b/dgl/src/Window.cpp @@ -319,15 +319,20 @@ void Window::setIgnoringKeyRepeat(const bool ignore) noexcept puglSetViewHint(pData->view, PUGL_IGNORE_KEY_REPEAT, ignore); } -bool Window::setClipboard(const char* const mimeType, const void* const data, const size_t dataSize) +const void* Window::getClipboard(size_t& dataSize) { - return puglSetClipboard(pData->view, mimeType, data, dataSize) == PUGL_SUCCESS; + if (pData->clipboardTypeIndex == 0) + { + dataSize = 0; + return nullptr; + } + + return puglGetClipboard(pData->view, pData->clipboardTypeIndex, &dataSize); } -const void* Window::getClipboard(const char*& mimeType, size_t& dataSize) +bool Window::setClipboard(const char* const mimeType, const void* const data, const size_t dataSize) { - const void* const clipboard = nullptr; // puglGetClipboard(pData->view, &mimeType, &dataSize); - return clipboard; + return puglSetClipboard(pData->view, mimeType, data, dataSize) == PUGL_SUCCESS; } bool Window::setCursor(const MouseCursor cursor) @@ -466,6 +471,29 @@ void Window::setGeometryConstraints(uint minimumWidth, } } +std::vector Window::getClipboardDataOfferTypes() +{ + std::vector offerTypes; + + if (const uint32_t numTypes = puglGetNumClipboardTypes(pData->view)) + { + offerTypes.reserve(numTypes); + + for (uint32_t i=0; iview, i) }; + offerTypes.push_back(offer); + } + } + + return offerTypes; +} + +uint32_t Window::onClipboardDataOffer() +{ + return 0; +} + bool Window::onClose() { return true; diff --git a/dgl/src/WindowPrivateData.cpp b/dgl/src/WindowPrivateData.cpp index 54a13673..2885704d 100644 --- a/dgl/src/WindowPrivateData.cpp +++ b/dgl/src/WindowPrivateData.cpp @@ -109,6 +109,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s) minHeight(0), keepAspectRatio(false), ignoreIdleCallbacks(false), + clipboardTypeIndex(0), filenameToRenderInto(nullptr), #ifndef DGL_FILE_BROWSER_DISABLED fileBrowserHandle(nullptr), @@ -135,6 +136,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, PrivateData* c minHeight(0), keepAspectRatio(false), ignoreIdleCallbacks(false), + clipboardTypeIndex(0), filenameToRenderInto(nullptr), #ifndef DGL_FILE_BROWSER_DISABLED fileBrowserHandle(nullptr), @@ -163,6 +165,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, minHeight(0), keepAspectRatio(false), ignoreIdleCallbacks(false), + clipboardTypeIndex(0), filenameToRenderInto(nullptr), #ifndef DGL_FILE_BROWSER_DISABLED fileBrowserHandle(nullptr), @@ -192,6 +195,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, minHeight(0), keepAspectRatio(false), ignoreIdleCallbacks(false), + clipboardTypeIndex(0), filenameToRenderInto(nullptr), #ifndef DGL_FILE_BROWSER_DISABLED fileBrowserHandle(nullptr), @@ -753,6 +757,13 @@ void Window::PrivateData::onPuglScroll(const Widget::ScrollEvent& ev) #endif } +uint32_t Window::PrivateData::onClipboardDataOffer() +{ + DGL_DBG("onClipboardDataOffer\n"); + + return clipboardTypeIndex = self->onClipboardDataOffer(); +} + #if defined(DEBUG) && defined(DGL_DEBUG_EVENTS) static int printEvent(const PuglEvent* event, const char* prefix, const bool verbose); #endif @@ -933,6 +944,8 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu ///< Data offered from clipboard, a #PuglDataOfferEvent case PUGL_DATA_OFFER: + if (const uint32_t offerId = pData->onClipboardDataOffer()) + puglAcceptOffer(view, &event->offer, offerId - 1); break; ///< Data available from clipboard, a #PuglDataEvent diff --git a/dgl/src/WindowPrivateData.hpp b/dgl/src/WindowPrivateData.hpp index 6cb8a4d6..07a94163 100644 --- a/dgl/src/WindowPrivateData.hpp +++ b/dgl/src/WindowPrivateData.hpp @@ -80,6 +80,9 @@ struct Window::PrivateData : IdleCallback { /** Whether to ignore idle callback requests, useful for temporary windows. */ bool ignoreIdleCallbacks; + /** The type index returned by the last onClipboardDataOffer call. */ + uint32_t clipboardTypeIndex; + /** Render to a picture file when non-null, automatically free+unset after saving. */ char* filenameToRenderInto; @@ -182,6 +185,7 @@ struct Window::PrivateData : IdleCallback { void onPuglMouse(const Widget::MouseEvent& ev); void onPuglMotion(const Widget::MotionEvent& ev); void onPuglScroll(const Widget::ScrollEvent& ev); + uint32_t onClipboardDataOffer(); // Pugl event handling entry point static PuglStatus puglEventCallback(PuglView* view, const PuglEvent* event); diff --git a/dgl/src/pugl.cpp b/dgl/src/pugl.cpp index 3f697d3d..2ff3bf9f 100644 --- a/dgl/src/pugl.cpp +++ b/dgl/src/pugl.cpp @@ -476,8 +476,8 @@ void puglMacOSShowCentered(PuglView* const view) const NSRect ourFrame = [view->impl->window frame]; const NSRect transientFrame = [transientWindow frame]; - const int x = transientFrame.origin.x + transientFrame.size.width / 2 - ourFrame.size.width / 2; - const int y = transientFrame.origin.y + transientFrame.size.height / 2 + ourFrame.size.height / 2; + const int x = transientFrame.origin.x + (transientFrame.size.width - ourFrame.size.width) / 2; + const int y = transientFrame.origin.y + (transientFrame.size.height - ourFrame.size.height) / 2; [view->impl->window setFrameTopLeftPoint:NSMakePoint(x, y)]; } @@ -543,8 +543,8 @@ void puglWin32ShowCentered(PuglView* const view) if (GetMonitorInfo(MonitorFromWindow(impl->hwnd, MONITOR_DEFAULTTOPRIMARY), &mInfo)) SetWindowPos(impl->hwnd, HWND_TOP, - mInfo.rcWork.left + (mInfo.rcWork.right - view->frame.width) / 2, - mInfo.rcWork.top + (mInfo.rcWork.bottom - view->frame.height) / 2, + mInfo.rcWork.left + (mInfo.rcWork.right - mInfo.rcWork.left - view->frame.width) / 2, + mInfo.rcWork.top + (mInfo.rcWork.bottom - mInfo.rcWork.top - view->frame.height) / 2, 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE); else ShowWindow(impl->hwnd, SW_NORMAL); diff --git a/dgl/src/pugl.hpp b/dgl/src/pugl.hpp index 7ebbc736..610ebe82 100644 --- a/dgl/src/pugl.hpp +++ b/dgl/src/pugl.hpp @@ -35,20 +35,12 @@ #define PUGL_NO_INCLUDE_GL_H #define PUGL_NO_INCLUDE_GLU_H -// do not set extern "C" -// #define __cplusplus_backup __cplusplus -// #undef __cplusplus - -// give warning if defined as something else -// #define PUGL_BEGIN_DECLS -// #define PUGL_END_DECLS - -// -------------------------------------------------------------------------------------------------------------------- - START_NAMESPACE_DGL #include "pugl-upstream/include/pugl/pugl.h" +// -------------------------------------------------------------------------------------------------------------------- + // DGL specific, expose backend enter bool puglBackendEnter(PuglView* view); @@ -85,30 +77,24 @@ void puglFallbackOnResize(PuglView* view); #if defined(DISTRHO_OS_MAC) // macOS specific, allow standalone window to gain focus -PUGL_API void -puglMacOSActivateApp(); +void puglMacOSActivateApp(); // macOS specific, add another view's window as child -PUGL_API PuglStatus -puglMacOSAddChildWindow(PuglView* view, PuglView* child); +PuglStatus puglMacOSAddChildWindow(PuglView* view, PuglView* child); // macOS specific, remove another view's window as child -PUGL_API PuglStatus -puglMacOSRemoveChildWindow(PuglView* view, PuglView* child); +PuglStatus puglMacOSRemoveChildWindow(PuglView* view, PuglView* child); // macOS specific, center view based on parent coordinates (if there is one) -PUGL_API void -puglMacOSShowCentered(PuglView* view); +void puglMacOSShowCentered(PuglView* view); #elif defined(DISTRHO_OS_WINDOWS) // win32 specific, call ShowWindow with SW_RESTORE -PUGL_API void -puglWin32RestoreWindow(PuglView* view); +void puglWin32RestoreWindow(PuglView* view); // win32 specific, center view based on parent coordinates (if there is one) -PUGL_API void -puglWin32ShowCentered(PuglView* view); +void puglWin32ShowCentered(PuglView* view); #elif defined(HAVE_X11) @@ -121,7 +107,4 @@ void puglX11SetWindowTypeAndPID(const PuglView* view, bool isStandalone); END_NAMESPACE_DGL -// #define __cplusplus __cplusplus_backup -// #undef __cplusplus_backup - #endif // DGL_PUGL_HPP_INCLUDED diff --git a/distrho/DistrhoUI.hpp b/distrho/DistrhoUI.hpp index 1526d302..3b0bd007 100644 --- a/distrho/DistrhoUI.hpp +++ b/distrho/DistrhoUI.hpp @@ -1,6 +1,6 @@ /* * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2021 Filipe Coelho + * Copyright (C) 2012-2022 Filipe Coelho * * 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 @@ -296,6 +296,23 @@ protected: virtual void uiScaleFactorChanged(double scaleFactor); #if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + /** + Get the types available for the data in a clipboard. + Must only be called within the context of uiClipboardDataOffer. + */ + std::vector getClipboardDataOfferTypes(); + + /** + Window clipboard data offer function, called when clipboard has data present, possibly with several datatypes. + While handling this event, the data types can be investigated with getClipboardDataOfferTypes() to decide whether to accept the offer. + + Reimplement and return a non-zero id to accept the clipboard data offer for a particular type. + UIs must ignore any type they do not recognize. + + The default implementation does nothing. + */ + virtual uint32_t uiClipboardDataOffer(); + /** Windows focus function, called when the window gains or loses the keyboard focus. This function is for plugin UIs to be able to override Window::onFocus(bool, CrossingMode). diff --git a/distrho/src/DistrhoUI.cpp b/distrho/src/DistrhoUI.cpp index 5e98c289..f3b5c642 100644 --- a/distrho/src/DistrhoUI.cpp +++ b/distrho/src/DistrhoUI.cpp @@ -1,6 +1,6 @@ /* * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2021 Filipe Coelho + * Copyright (C) 2012-2022 Filipe Coelho * * 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 @@ -338,6 +338,16 @@ void UI::uiScaleFactorChanged(double) } #if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI +std::vector UI::getClipboardDataOfferTypes() +{ + return uiData->window->getClipboardDataOfferTypes(); +} + +uint32_t UI::uiClipboardDataOffer() +{ + return 0; +} + void UI::uiFocus(bool, DGL_NAMESPACE::CrossingMode) { } diff --git a/distrho/src/DistrhoUIPrivateData.hpp b/distrho/src/DistrhoUIPrivateData.hpp index c0985344..a2cf3084 100644 --- a/distrho/src/DistrhoUIPrivateData.hpp +++ b/distrho/src/DistrhoUIPrivateData.hpp @@ -238,7 +238,22 @@ public: } #endif + std::vector getClipboardDataOfferTypes() + { + return Window::getClipboardDataOfferTypes(); + } + protected: + uint32_t onClipboardDataOffer() override + { + DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr, 0); + + if (initializing) + return 0; + + return ui->uiClipboardDataOffer(); + } + void onFocus(const bool focus, const DGL_NAMESPACE::CrossingMode mode) override { DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,); diff --git a/pugl-updates-notes.txt b/pugl-updates-notes.txt index 3430c529..8e22c015 100644 --- a/pugl-updates-notes.txt +++ b/pugl-updates-notes.txt @@ -1,9 +1,10 @@ puglClearMinSize needed? -clipboard todo - puglSetWindowSize was used on first show, still needed? +transientParentView needed? remove from WindowPrivateData -pugl namespace details finalized +update distrhoui.cpp get scale factor to match new parent request setup and pugl -window starts centered for screen or parent finalized +clipboard todo + +pugl namespace details finalized