Signed-off-by: falkTX <falktx@falktx.com>pull/321/head
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2022 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 | |||
| @@ -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; | |||
| }; | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| @@ -101,8 +101,8 @@ public: | |||
| void repaint(const Rectangle<uint>& 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); | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2022 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 | |||
| @@ -23,6 +23,8 @@ | |||
| # include "../distrho/extra/FileBrowserDialog.hpp" | |||
| #endif | |||
| #include <vector> | |||
| 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<ClipboardDataOffer> 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. | |||
| @@ -60,14 +60,14 @@ void TopLevelWidget::setSize(const Size<uint>& 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) | |||
| @@ -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<ClipboardDataOffer> Window::getClipboardDataOfferTypes() | |||
| { | |||
| std::vector<ClipboardDataOffer> offerTypes; | |||
| if (const uint32_t numTypes = puglGetNumClipboardTypes(pData->view)) | |||
| { | |||
| offerTypes.reserve(numTypes); | |||
| for (uint32_t i=0; i<numTypes; ++i) | |||
| { | |||
| const ClipboardDataOffer offer = { i + 1, puglGetClipboardType(pData->view, i) }; | |||
| offerTypes.push_back(offer); | |||
| } | |||
| } | |||
| return offerTypes; | |||
| } | |||
| uint32_t Window::onClipboardDataOffer() | |||
| { | |||
| return 0; | |||
| } | |||
| bool Window::onClose() | |||
| { | |||
| return true; | |||
| @@ -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 | |||
| @@ -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); | |||
| @@ -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); | |||
| @@ -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 | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2022 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 | |||
| @@ -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<DGL_NAMESPACE::ClipboardDataOffer> 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). | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2022 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 | |||
| @@ -338,6 +338,16 @@ void UI::uiScaleFactorChanged(double) | |||
| } | |||
| #if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
| std::vector<DGL_NAMESPACE::ClipboardDataOffer> UI::getClipboardDataOfferTypes() | |||
| { | |||
| return uiData->window->getClipboardDataOfferTypes(); | |||
| } | |||
| uint32_t UI::uiClipboardDataOffer() | |||
| { | |||
| return 0; | |||
| } | |||
| void UI::uiFocus(bool, DGL_NAMESPACE::CrossingMode) | |||
| { | |||
| } | |||
| @@ -238,7 +238,22 @@ public: | |||
| } | |||
| #endif | |||
| std::vector<ClipboardDataOffer> 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,); | |||
| @@ -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 | |||