From 2ead533d2383083925537832b473e3264811d454 Mon Sep 17 00:00:00 2001 From: Henry Castro Date: Thu, 18 Apr 2019 18:10:13 -0400 Subject: lok: allow paste content to popup dialog Change-Id: I1893d52df505bc43428c37a624ca05c569ba1bc0 Reviewed-on: https://gerrit.libreoffice.org/70958 Tested-by: Jenkins Reviewed-by: Henry Castro --- desktop/qa/desktop_lib/test_desktop_lib.cxx | 51 ++++++++++++++++++++++ desktop/source/lib/init.cxx | 37 +++++++++++++++- desktop/source/lib/lokclipboard.cxx | 10 ++++- desktop/source/lib/lokclipboard.hxx | 3 +- include/LibreOfficeKit/LibreOfficeKit.h | 2 +- include/LibreOfficeKit/LibreOfficeKit.hxx | 4 +- include/LibreOfficeKit/LibreOfficeKitEnums.h | 3 +- .../LibreOfficeLight/LOKit/Document.swift | 8 ++-- .../qa/gtktiledviewer/gtv-application-window.cxx | 2 +- libreofficekit/qa/tilebench/tilebench.cxx | 2 +- 10 files changed, 107 insertions(+), 15 deletions(-) diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx index a08d476a8bac..e18cda94bb7d 100644 --- a/desktop/qa/desktop_lib/test_desktop_lib.cxx +++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx @@ -22,7 +22,11 @@ #include +#include #include +#include +#include +#include #include #include #include @@ -130,6 +134,7 @@ public: void testInsertCertificate_PEM_DOCX(); void testSignDocument_PEM_PDF(); void testTextSelectionHandles(); + void testDialogPaste(); void testABI(); CPPUNIT_TEST_SUITE(DesktopLOKTest); @@ -180,6 +185,7 @@ public: CPPUNIT_TEST(testInsertCertificate_PEM_DOCX); CPPUNIT_TEST(testSignDocument_PEM_PDF); CPPUNIT_TEST(testTextSelectionHandles); + CPPUNIT_TEST(testDialogPaste); CPPUNIT_TEST(testABI); CPPUNIT_TEST_SUITE_END(); @@ -207,6 +213,23 @@ public: }; +static Control* GetFocusControl(vcl::Window const * pParent) +{ + sal_uInt16 nChildren = pParent->GetChildCount(); + for (sal_uInt16 nChild = 0; nChild < nChildren; ++nChild) + { + vcl::Window* pChild = pParent->GetChild( nChild ); + Control* pCtrl = dynamic_cast(pChild); + if (pCtrl && pCtrl->HasControlFocus()) + return pCtrl; + + Control* pSubCtrl = GetFocusControl( pChild ); + if (pSubCtrl) + return pSubCtrl; + } + return nullptr; +} + LibLODocument_Impl* DesktopLOKTest::loadDoc(const char* pName, LibreOfficeKitDocumentType eType) { OUString aFileURL; @@ -2616,6 +2639,34 @@ void DesktopLOKTest::testTextSelectionHandles() comphelper::LibreOfficeKit::setActive(false); } +void DesktopLOKTest::testDialogPaste() +{ + comphelper::LibreOfficeKit::setActive(); + LibLODocument_Impl* pDocument = loadDoc("blank_text.odt"); + pDocument->pClass->postUnoCommand(pDocument, ".uno:HyperlinkDialog", nullptr, false); + Scheduler::ProcessEventsToIdle(); + + SfxViewShell* pViewShell = SfxViewShell::Current(); + pViewShell->GetViewFrame()->GetBindings().Update(); + + VclPtr pWindow(Application::GetActiveTopWindow()); + CPPUNIT_ASSERT(pWindow); + + pDocument->pClass->postWindow(pDocument, pWindow->GetLOKWindowId(), LOK_WINDOW_PASTE, + "{ \"MimeType\" : { \"type\" : \"string\", \"value\" : \"text/plain;charset=utf-8\" }, \"Data\" : { \"type\" : \"[]byte\", \"value\" : \"www.softwarelibre.org.bo\" } }"); + Scheduler::ProcessEventsToIdle(); + + Control* pCtrlFocused = GetFocusControl(pWindow.get()); + CPPUNIT_ASSERT(pCtrlFocused); + ComboBox* pCtrlURL = dynamic_cast(pCtrlFocused); + CPPUNIT_ASSERT(pCtrlURL); + CPPUNIT_ASSERT_EQUAL(OUString("www.softwarelibre.org.bo"), pCtrlURL->GetText()); + + static_cast(pWindow.get())->Close(); + Scheduler::ProcessEventsToIdle(); + comphelper::LibreOfficeKit::setActive(false); +} + namespace { constexpr size_t classOffset(int i) diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index c4a36e9e182e..937331376024 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -358,6 +358,15 @@ std::vector desktop::jsonToPropertyValuesVector(const char aValue.Value <<= static_cast(OString(rValue.c_str()).toInt32()); else if (rType == "unsigned short") aValue.Value <<= static_cast(OString(rValue.c_str()).toUInt32()); + else if (rType == "[]byte") + { + aNodeValue = rPair.second.get_child("value", aNodeNull); + if (aNodeValue != aNodeNull && aNodeValue.size() == 0) + { + uno::Sequence< sal_Int8 > aSeqByte(reinterpret_cast(rValue.c_str()), rValue.size()); + aValue.Value <<= aSeqByte; + } + } else if (rType == "[]any") { aNodeValue = rPair.second.get_child("value", aNodeNull); @@ -806,7 +815,7 @@ static void doc_paintWindowDPI(LibreOfficeKitDocument* pThis, unsigned nLOKWindo const int nWidth, const int nHeight, const double fDPIScale); -static void doc_postWindow(LibreOfficeKitDocument* pThis, unsigned nLOKWindowId, int nAction); +static void doc_postWindow(LibreOfficeKitDocument* pThis, unsigned nLOKWindowId, int nAction, const char* pData); static char* doc_getPartInfo(LibreOfficeKitDocument* pThis, int nPart); @@ -4146,7 +4155,7 @@ static void doc_paintWindowDPI(LibreOfficeKitDocument* /*pThis*/, unsigned nLOKW #endif } -static void doc_postWindow(LibreOfficeKitDocument* /*pThis*/, unsigned nLOKWindowId, int nAction) +static void doc_postWindow(LibreOfficeKitDocument* /*pThis*/, unsigned nLOKWindowId, int nAction, const char* pData) { comphelper::ProfileZone aZone("doc_postWindow"); @@ -4168,6 +4177,30 @@ static void doc_postWindow(LibreOfficeKitDocument* /*pThis*/, unsigned nLOKWindo else if (FloatingWindow* pFloatWin = dynamic_cast(pWindow.get())) pFloatWin->EndPopupMode(FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll); } + else if (nAction == LOK_WINDOW_PASTE) + { + OUString aMimeType; + css::uno::Sequence aData; + std::vector aArgs(jsonToPropertyValuesVector(pData)); + { + aArgs.size() == 2 && + aArgs[0].Name == "MimeType" && (aArgs[0].Value >>= aMimeType) && + aArgs[1].Name == "Data" && (aArgs[1].Value >>= aData); + } + + if (!aMimeType.isEmpty() && aData.getLength() > 0) + { + uno::Reference xTransferable(new LOKTransferable(aMimeType, aData)); + uno::Reference xClipboard(new LOKClipboard); + xClipboard->setContents(xTransferable, uno::Reference()); + pWindow->SetClipboard(xClipboard); + + KeyEvent aEvent(0, KEY_PASTE, 0); + Application::PostKeyEvent(VclEventId::WindowKeyInput, pWindow, &aEvent); + } + else + gImpl->maLastExceptionMsg = "Window command 'paste': wrong parameters."; + } } // CERTIFICATE AND DOCUMENT SIGNING diff --git a/desktop/source/lib/lokclipboard.cxx b/desktop/source/lib/lokclipboard.cxx index 091bd47d35db..b02dc3ca172b 100644 --- a/desktop/source/lib/lokclipboard.cxx +++ b/desktop/source/lib/lokclipboard.cxx @@ -29,11 +29,17 @@ OUString SAL_CALL LOKClipboard::getName() } LOKTransferable::LOKTransferable(const char* pMimeType, const char* pData, std::size_t nSize) - : m_aMimeType(pMimeType), + : m_aMimeType(OUString::fromUtf8(pMimeType)), m_aSequence(reinterpret_cast(pData), nSize) { } +LOKTransferable::LOKTransferable(const OUString& sMimeType, const css::uno::Sequence& aSequence) + : m_aMimeType(sMimeType), + m_aSequence(aSequence) +{ +} + uno::Any SAL_CALL LOKTransferable::getTransferData(const datatransfer::DataFlavor& rFlavor) { uno::Any aRet; @@ -51,7 +57,7 @@ std::vector LOKTransferable::getTransferDataFlavorsAsV { std::vector aRet; datatransfer::DataFlavor aFlavor; - aFlavor.MimeType = OUString::fromUtf8(m_aMimeType.getStr()); + aFlavor.MimeType = m_aMimeType; aFlavor.DataType = cppu::UnoType< uno::Sequence >::get(); sal_Int32 nIndex(0); diff --git a/desktop/source/lib/lokclipboard.hxx b/desktop/source/lib/lokclipboard.hxx index 11c676500043..ae83eb6dd2e6 100644 --- a/desktop/source/lib/lokclipboard.hxx +++ b/desktop/source/lib/lokclipboard.hxx @@ -32,7 +32,7 @@ public: /// Represents the contents of LOKClipboard. class LOKTransferable : public cppu::WeakImplHelper { - OString m_aMimeType; + OUString m_aMimeType; css::uno::Sequence m_aSequence; /// Provides a list of flavors, used by getTransferDataFlavors() and isDataFlavorSupported(). @@ -40,6 +40,7 @@ class LOKTransferable : public cppu::WeakImplHelper& aSequence); css::uno::Any SAL_CALL getTransferData(const css::datatransfer::DataFlavor& rFlavor) override; diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h index 62bd3c429fa1..e4e96483c354 100644 --- a/include/LibreOfficeKit/LibreOfficeKit.h +++ b/include/LibreOfficeKit/LibreOfficeKit.h @@ -294,7 +294,7 @@ struct _LibreOfficeKitDocumentClass const int width, const int height); /// @see lok::Document::postWindow(). - void (*postWindow) (LibreOfficeKitDocument* pThis, unsigned nWindowId, int nAction); + void (*postWindow) (LibreOfficeKitDocument* pThis, unsigned nWindowId, int nAction, const char* pData); /// @see lok::Document::postWindowKeyEvent(). void (*postWindowKeyEvent) (LibreOfficeKitDocument* pThis, diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx index 7027298a1481..47983e68fa27 100644 --- a/include/LibreOfficeKit/LibreOfficeKit.hxx +++ b/include/LibreOfficeKit/LibreOfficeKit.hxx @@ -188,9 +188,9 @@ public: * * @param nWindowid */ - void postWindow(unsigned nWindowId, int nAction) + void postWindow(unsigned nWindowId, int nAction, const char* pData) { - return mpDoc->pClass->postWindow(mpDoc, nWindowId, nAction); + return mpDoc->pClass->postWindow(mpDoc, nWindowId, nAction, pData); } /** diff --git a/include/LibreOfficeKit/LibreOfficeKitEnums.h b/include/LibreOfficeKit/LibreOfficeKitEnums.h index ef24828988f7..33d235af827b 100644 --- a/include/LibreOfficeKit/LibreOfficeKitEnums.h +++ b/include/LibreOfficeKit/LibreOfficeKitEnums.h @@ -42,7 +42,8 @@ LibreOfficeKitTileMode; typedef enum { - LOK_WINDOW_CLOSE + LOK_WINDOW_CLOSE, + LOK_WINDOW_PASTE } LibreOfficeKitWindowAction; diff --git a/ios/LibreOfficeLight/LibreOfficeLight/LOKit/Document.swift b/ios/LibreOfficeLight/LibreOfficeLight/LOKit/Document.swift index 2a1ad97b3005..48cafe44632b 100644 --- a/ios/LibreOfficeLight/LibreOfficeLight/LOKit/Document.swift +++ b/ios/LibreOfficeLight/LibreOfficeLight/LOKit/Document.swift @@ -170,9 +170,9 @@ open class Document * * @param nWindowid */ - public func postWindow( nWindowId: UInt32, nAction: Int32) + public func postWindow( nWindowId: UInt32, nAction: Int32, data: String) { - return docClass.postWindow(pDoc, nWindowId, nAction); + return docClass.postWindow(pDoc, nWindowId, nAction, data); } /** @@ -536,13 +536,13 @@ open class Document { docClass.setViewLanguage(pDoc, id, language); } - + public func invokeHandlers() { // The app seems to work even without this? Or maybe I // just didn't test hard enough? // temporaryHackToInvokeCallbackHandlers(pDoc) - + } } diff --git a/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx b/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx index 5d6ecb01728d..1de1aa94568d 100644 --- a/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx +++ b/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx @@ -431,7 +431,7 @@ gtv_application_window_unregister_child_window(GtvApplicationWindow* window, Gtk LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview)); guint dialogId = 0; g_object_get(G_OBJECT(pChildWin), "dialogid", &dialogId, nullptr); - pDocument->pClass->postWindow(pDocument, dialogId, LOK_WINDOW_CLOSE); + pDocument->pClass->postWindow(pDocument, dialogId, LOK_WINDOW_CLOSE, nullptr); } } diff --git a/libreofficekit/qa/tilebench/tilebench.cxx b/libreofficekit/qa/tilebench/tilebench.cxx index 61d337f6c518..d0fc87283d35 100644 --- a/libreofficekit/qa/tilebench/tilebench.cxx +++ b/libreofficekit/qa/tilebench/tilebench.cxx @@ -286,7 +286,7 @@ static void testDialog( Document *pDocument, const char *uno_cmd ) } aTimes.emplace_back("post close dialog"); - pDocument->postWindow(nDialogId, LOK_WINDOW_CLOSE); + pDocument->postWindow(nDialogId, LOK_WINDOW_CLOSE, nullptr); aTimes.emplace_back(); pDocument->destroyView(view); -- cgit