diff --git a/dgl/src/Window.cpp b/dgl/src/Window.cpp index dee9d189..e44ffd18 100644 --- a/dgl/src/Window.cpp +++ b/dgl/src/Window.cpp @@ -321,18 +321,12 @@ void Window::setIgnoringKeyRepeat(const bool ignore) noexcept const void* Window::getClipboard(size_t& dataSize) { - if (pData->clipboardTypeIndex == 0) - { - dataSize = 0; - return nullptr; - } - - return puglGetClipboard(pData->view, pData->clipboardTypeIndex, &dataSize); + return pData->getClipboard(dataSize); } bool Window::setClipboard(const char* const mimeType, const void* const data, const size_t dataSize) { - return puglSetClipboard(pData->view, mimeType, data, dataSize) == PUGL_SUCCESS; + return puglSetClipboard(pData->view, mimeType != nullptr ? mimeType : "text/plain", data, dataSize) == PUGL_SUCCESS; } bool Window::setCursor(const MouseCursor cursor) diff --git a/dgl/src/WindowPrivateData.cpp b/dgl/src/WindowPrivateData.cpp index 2885704d..522da6b5 100644 --- a/dgl/src/WindowPrivateData.cpp +++ b/dgl/src/WindowPrivateData.cpp @@ -109,7 +109,8 @@ Window::PrivateData::PrivateData(Application& a, Window* const s) minHeight(0), keepAspectRatio(false), ignoreIdleCallbacks(false), - clipboardTypeIndex(0), + waitingForClipboard(false), + clipboardTypeId(0), filenameToRenderInto(nullptr), #ifndef DGL_FILE_BROWSER_DISABLED fileBrowserHandle(nullptr), @@ -136,7 +137,8 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, PrivateData* c minHeight(0), keepAspectRatio(false), ignoreIdleCallbacks(false), - clipboardTypeIndex(0), + waitingForClipboard(false), + clipboardTypeId(0), filenameToRenderInto(nullptr), #ifndef DGL_FILE_BROWSER_DISABLED fileBrowserHandle(nullptr), @@ -165,7 +167,8 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, minHeight(0), keepAspectRatio(false), ignoreIdleCallbacks(false), - clipboardTypeIndex(0), + waitingForClipboard(false), + clipboardTypeId(0), filenameToRenderInto(nullptr), #ifndef DGL_FILE_BROWSER_DISABLED fileBrowserHandle(nullptr), @@ -195,7 +198,8 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, minHeight(0), keepAspectRatio(false), ignoreIdleCallbacks(false), - clipboardTypeIndex(0), + waitingForClipboard(false), + clipboardTypeId(0), filenameToRenderInto(nullptr), #ifndef DGL_FILE_BROWSER_DISABLED fileBrowserHandle(nullptr), @@ -757,11 +761,59 @@ void Window::PrivateData::onPuglScroll(const Widget::ScrollEvent& ev) #endif } +const void* Window::PrivateData::getClipboard(size_t& dataSize) +{ + clipboardTypeId = 0; + waitingForClipboard = true; + + if (puglPaste(view) != PUGL_SUCCESS) + { + dataSize = 0; + waitingForClipboard = false; + return nullptr; + } + + // wait for type request + while (waitingForClipboard && clipboardTypeId == 0) + puglUpdate(appData->world, 0.03); + + if (clipboardTypeId == 0) + { + dataSize = 0; + waitingForClipboard = false; + return nullptr; + } + + // wait for actual data + while (waitingForClipboard) + puglUpdate(appData->world, 0.03); + + if (clipboardTypeId == 0) + { + dataSize = 0; + return nullptr; + } + + return puglGetClipboard(view, clipboardTypeId - 1, &dataSize); +} + uint32_t Window::PrivateData::onClipboardDataOffer() { DGL_DBG("onClipboardDataOffer\n"); - return clipboardTypeIndex = self->onClipboardDataOffer(); + if ((clipboardTypeId = self->onClipboardDataOffer()) != 0) + return clipboardTypeId; + + waitingForClipboard = false; + return 0; +} + +void Window::PrivateData::onClipboardData(const uint32_t typeId) +{ + if (clipboardTypeId != typeId) + clipboardTypeId = 0; + + waitingForClipboard = false; } #if defined(DEBUG) && defined(DGL_DEBUG_EVENTS) @@ -777,6 +829,29 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu } #endif + if (pData->waitingForClipboard) + { + switch (event->type) + { + case PUGL_UPDATE: + case PUGL_EXPOSE: + case PUGL_FOCUS_IN: + case PUGL_FOCUS_OUT: + case PUGL_KEY_PRESS: + case PUGL_KEY_RELEASE: + case PUGL_TEXT: + case PUGL_POINTER_IN: + case PUGL_POINTER_OUT: + case PUGL_BUTTON_PRESS: + case PUGL_BUTTON_RELEASE: + case PUGL_MOTION: + case PUGL_SCROLL: + return PUGL_SUCCESS; + default: + break; + } + } + switch (event->type) { ///< No event @@ -944,12 +1019,13 @@ 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); + if (const uint32_t offerTypeId = pData->onClipboardDataOffer()) + puglAcceptOffer(view, &event->offer, offerTypeId - 1); break; ///< Data available from clipboard, a #PuglDataEvent case PUGL_DATA: + pData->onClipboardData(event->data.typeIndex + 1); break; } diff --git a/dgl/src/WindowPrivateData.hpp b/dgl/src/WindowPrivateData.hpp index 07a94163..f4912cab 100644 --- a/dgl/src/WindowPrivateData.hpp +++ b/dgl/src/WindowPrivateData.hpp @@ -80,8 +80,11 @@ 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; + /** Whether we are waiting to receive clipboard data, ignoring some events in the process. */ + bool waitingForClipboard; + + /** The type id returned by the last onClipboardDataOffer call. */ + uint32_t clipboardTypeId; /** Render to a picture file when non-null, automatically free+unset after saving. */ char* filenameToRenderInto; @@ -185,7 +188,11 @@ struct Window::PrivateData : IdleCallback { void onPuglMouse(const Widget::MouseEvent& ev); void onPuglMotion(const Widget::MotionEvent& ev); void onPuglScroll(const Widget::ScrollEvent& ev); + + // clipboard related handling + const void* getClipboard(size_t& dataSize); uint32_t onClipboardDataOffer(); + void onClipboardData(uint32_t typeId); // Pugl event handling entry point static PuglStatus puglEventCallback(PuglView* view, const PuglEvent* event); diff --git a/dgl/src/pugl-upstream b/dgl/src/pugl-upstream index 9691a681..7bb0bd67 160000 --- a/dgl/src/pugl-upstream +++ b/dgl/src/pugl-upstream @@ -1 +1 @@ -Subproject commit 9691a6810283ffd5a99b1cc974fc638e80f94979 +Subproject commit 7bb0bd672489ac0d0851dfd1b4980b33b7a9f48d