Rebased ref, commits from common ancestor: commit 6368723bd902e9cb46ecf2da822be71492a0ca7c Author: Michael Meeks <michael.me...@collabora.com> AuthorDate: Thu Jul 25 19:02:47 2019 +0100 Commit: Michael Meeks <michael.me...@collabora.com> CommitDate: Sat Jul 27 08:46:43 2019 -0400
clipboard: repair unit test so they run in the lok mode. SwTransferable::AddSupportedFormats needs the kit to be active. Change-Id: Id84210eb2e526785f35dfae609d861c310885314 diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx index 7ad2f1e45817..39be487931f3 100644 --- a/desktop/qa/desktop_lib/test_desktop_lib.cxx +++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx @@ -2635,6 +2635,9 @@ void DesktopLOKTest::testShowHideDialog() void DesktopLOKTest::testComplexSelection() { + // needed for SwTransferable to cope with the selection. + comphelper::LibreOfficeKit::setActive(); + // Start with a blank text file and add contents. LibLODocument_Impl* pDocument = loadDoc("blank_text.odt"); static const OString aText("hello world"); diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 37f7899be01f..6e2ca6d37a07 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -878,7 +878,6 @@ ITiledRenderable* getTiledRenderable(LibreOfficeKitDocument* pThis) * we also need to ensure that this works for the first view which * has no clear 'createView' called for it (unfortunately). */ - rtl::Reference<LOKClipboard> forceSetClipboardForCurrentView(LibreOfficeKitDocument *pThis) { ITiledRenderable* pDoc = getTiledRenderable(pThis); commit 3171f6712ef926d6ba0eedd93d535a1ddef2cd94 Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk> AuthorDate: Mon Jul 22 19:00:23 2019 -0400 Commit: Michael Meeks <michael.me...@collabora.com> CommitDate: Sat Jul 27 08:46:42 2019 -0400 clipboard: log before erasing Change-Id: I6d59cdd31c62bbc7db81ccb8985745f68d19cd28 diff --git a/desktop/source/lib/lokclipboard.cxx b/desktop/source/lib/lokclipboard.cxx index 7eefd09370d1..f44f4e9fed81 100644 --- a/desktop/source/lib/lokclipboard.cxx +++ b/desktop/source/lib/lokclipboard.cxx @@ -51,8 +51,8 @@ void LOKClipboardFactory::releaseClipboardForView(int nViewId) auto it = gClipboards.get()->find(nViewId); if (it != gClipboards.get()->end()) { + SAL_INFO("lok", "Releasing clip: " << it->second.get() << " for destroyed " << nViewId); gClipboards.get()->erase(it); - SAL_INFO("lok", "Released clip: " << it->second.get() << " for destroyed " << nViewId); } } } commit a7ca968aaf45750d72bcd3245d3267c065b1f525 Author: Michael Meeks <michael.me...@collabora.com> AuthorDate: Tue Jul 23 09:49:11 2019 +0100 Commit: Michael Meeks <michael.me...@collabora.com> CommitDate: Sat Jul 27 08:46:41 2019 -0400 clipboard: check for null. Change-Id: I07060035a9744642c98d4a0946695408dc0f6b42 diff --git a/desktop/source/lib/lokclipboard.cxx b/desktop/source/lib/lokclipboard.cxx index 3285965c846f..7eefd09370d1 100644 --- a/desktop/source/lib/lokclipboard.cxx +++ b/desktop/source/lib/lokclipboard.cxx @@ -37,7 +37,6 @@ rtl::Reference<LOKClipboard> LOKClipboardFactory::getClipboardForCurView() return xClip; } -/// FIXME: should really copy and stash its content for a bit. void LOKClipboardFactory::releaseClipboardForView(int nViewId) { osl::MutexGuard aGuard(gMutex); @@ -47,7 +46,7 @@ void LOKClipboardFactory::releaseClipboardForView(int nViewId) gClipboards.get()->clear(); SAL_INFO("lok", "Released all clipboards on doc destroy\n"); } - else + else if (gClipboards.get()) { auto it = gClipboards.get()->find(nViewId); if (it != gClipboards.get()->end()) commit 8c58c0f34a105fdde33e74f9e933d0b962ca70a5 Author: Michael Meeks <michael.me...@collabora.com> AuthorDate: Mon Jul 22 09:48:46 2019 +0100 Commit: Michael Meeks <michael.me...@collabora.com> CommitDate: Sat Jul 27 08:46:40 2019 -0400 lok: share more of the clipboard mime-type handling code. Change-Id: I98fc9fa0fd1b5afa00c33b642d2d504eab0b62ba diff --git a/desktop/source/lib/lokclipboard.cxx b/desktop/source/lib/lokclipboard.cxx index 17a9c5c54e4f..3285965c846f 100644 --- a/desktop/source/lib/lokclipboard.cxx +++ b/desktop/source/lib/lokclipboard.cxx @@ -189,20 +189,7 @@ LOKTransferable::LOKTransferable(const size_t nInCount, const char** pInMimeType m_aFlavors = css::uno::Sequence<css::datatransfer::DataFlavor>(nInCount); for (size_t i = 0; i < nInCount; ++i) { - OUString aMimeType = OUString::fromUtf8(pInMimeTypes[i]); - - // cf. sot/source/base/exchange.cxx for these two exceptional types. - if (aMimeType.startsWith("text/plain")) - { - aMimeType = "text/plain;charset=utf-16"; - m_aFlavors[i].DataType = cppu::UnoType<OUString>::get(); - } - else if (aMimeType == "application/x-libreoffice-tsvc") - m_aFlavors[i].DataType = cppu::UnoType<OUString>::get(); - else - m_aFlavors[i].DataType = cppu::UnoType<uno::Sequence<sal_Int8>>::get(); - m_aFlavors[i].MimeType = aMimeType; - m_aFlavors[i].HumanPresentableName = aMimeType; + initFlavourFromMime(m_aFlavors[i], OUString::fromUtf8(pInMimeTypes[i])); uno::Any aContent; if (m_aFlavors[i].DataType == cppu::UnoType<OUString>::get()) commit d2a4d9d570924f668de9798123ee2c2982b6a292 Author: Michael Meeks <michael.me...@collabora.com> AuthorDate: Sat Jul 20 11:22:09 2019 +0100 Commit: Michael Meeks <michael.me...@collabora.com> CommitDate: Sat Jul 27 08:46:39 2019 -0400 clipboard: encourage paste to show up by having some dummy content. Having an empty system clipboard is a hyper-unusual state, but this is quite common for new lok instances. If we populate some dummy state we can hide that. Allows context-menu paste into new documents. Change-Id: Ia180dd370c180d2d666cc57330db6c1385578a36 diff --git a/desktop/source/lib/lokclipboard.cxx b/desktop/source/lib/lokclipboard.cxx index f53202903761..17a9c5c54e4f 100644 --- a/desktop/source/lib/lokclipboard.cxx +++ b/desktop/source/lib/lokclipboard.cxx @@ -69,6 +69,9 @@ LOKClipboard::LOKClipboard() : cppu::WeakComponentImplHelper<css::datatransfer::clipboard::XSystemClipboard, css::lang::XServiceInfo>(m_aMutex) { + // Encourage 'paste' menu items to always show up. + uno::Reference<datatransfer::XTransferable> xTransferable(new LOKTransferable()); + setContents(xTransferable, uno::Reference<datatransfer::clipboard::XClipboardOwner>()); } Sequence<OUString> LOKClipboard::getSupportedServiceNames_static() @@ -150,6 +153,18 @@ LOKTransferable::LOKTransferable(const OUString& sMimeType, aContent <<= aSequence; m_aContent.push_back(aContent); } + +/// Use to ensure we have some dummy content on the clipboard to allow a 1st 'paste' +LOKTransferable::LOKTransferable() +{ + m_aContent.reserve(1); + m_aFlavors = css::uno::Sequence<css::datatransfer::DataFlavor>(1); + initFlavourFromMime(m_aFlavors[0], "text/plain"); + uno::Any aContent; + aContent <<= OUString(); + m_aContent.push_back(aContent); +} + // cf. sot/source/base/exchange.cxx for these two exceptional types. void LOKTransferable::initFlavourFromMime(css::datatransfer::DataFlavor& rFlavor, OUString aMimeType) diff --git a/desktop/source/lib/lokclipboard.hxx b/desktop/source/lib/lokclipboard.hxx index 1ade5c0a3e0b..3b8f9d8ee7c9 100644 --- a/desktop/source/lib/lokclipboard.hxx +++ b/desktop/source/lib/lokclipboard.hxx @@ -77,6 +77,7 @@ class LOKTransferable : public cppu::WeakImplHelper<css::datatransfer::XTransfer void initFlavourFromMime(css::datatransfer::DataFlavor& rFlavor, OUString sMimeType); public: + LOKTransferable(); LOKTransferable(const size_t nInCount, const char** pInMimeTypes, const size_t* pInSizes, const char** pInStreams); LOKTransferable(const OUString& sMimeType, const css::uno::Sequence<sal_Int8>& aSequence); diff --git a/vcl/source/treelist/transfer.cxx b/vcl/source/treelist/transfer.cxx index 10782592f5a2..5e41bde0378d 100644 --- a/vcl/source/treelist/transfer.cxx +++ b/vcl/source/treelist/transfer.cxx @@ -392,7 +392,7 @@ sal_Bool SAL_CALL TransferableHelper::isComplex() { // By default everything is complex, until proven otherwise // in the respective document type transferable handler. - return sal_True; + return true; } Sequence< DataFlavor > SAL_CALL TransferableHelper::getTransferDataFlavors() commit e5432fbf5a209ccb4c61b797e2798cec89c60909 Author: Michael Meeks <michael.me...@collabora.com> AuthorDate: Fri Jun 28 18:36:15 2019 +0100 Commit: Michael Meeks <michael.me...@collabora.com> CommitDate: Sat Jul 27 08:46:38 2019 -0400 Try harder to generate HTML from text. Change-Id: I5b4778cceefc652274a72b779cd6c060a50bf06c diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index a0d8b9436d52..37f7899be01f 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -3429,6 +3429,54 @@ static OUString getGenerator() static bool getFromTransferrable( const css::uno::Reference<css::datatransfer::XTransferable> &xTransferable, + const OString &aInMimeType, OString &aRet); + +static bool encodeImageAsHTML( + const css::uno::Reference<css::datatransfer::XTransferable> &xTransferable, + const OString &aMimeType, OString &aRet) +{ + if (!getFromTransferrable(xTransferable, aMimeType, aRet)) + return false; + + // Encode in base64. + auto aSeq = Sequence<sal_Int8>(reinterpret_cast<const sal_Int8*>(aRet.getStr()), + aRet.getLength()); + OUStringBuffer aBase64Data; + comphelper::Base64::encode(aBase64Data, aSeq); + + // Embed in HTML. + aRet = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n" + "<html><head>" + "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\"/><meta " + "name=\"generator\" content=\"" + + getGenerator().toUtf8() + + "\"/>" + "</head><body><img src=\"data:" + aMimeType + ";base64," + + aBase64Data.makeStringAndClear().toUtf8() + "\"/></body></html>"; + + return true; +} + +static bool encodeTextAsHTML( + const css::uno::Reference<css::datatransfer::XTransferable> &xTransferable, + const OString &aMimeType, OString &aRet) +{ + if (!getFromTransferrable(xTransferable, aMimeType, aRet)) + return false; + + // Embed in HTML - FIXME: needs some escaping. + aRet = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n" + "<html><head>" + "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\"/><meta " + "name=\"generator\" content=\"" + + getGenerator().toUtf8() + + "\"/></head><body><pre>" + aRet + "</pre></body></html>"; + + return true; +} + +static bool getFromTransferrable( + const css::uno::Reference<css::datatransfer::XTransferable> &xTransferable, const OString &aInMimeType, OString &aRet) { OString aMimeType(aInMimeType); @@ -3454,28 +3502,15 @@ static bool getFromTransferrable( if (!xTransferable->isDataFlavorSupported(aFlavor)) { - // If html is not supported, might be a graphic-selection, which supports png. - if (aInMimeType == "text/html" && getFromTransferrable(xTransferable, "image/png", aRet)) + // Try harder for HTML it is our copy/paste meta-file format + if (aInMimeType == "text/html") { - // Encode in base64. - auto aSeq = Sequence<sal_Int8>(reinterpret_cast<const sal_Int8*>(aRet.getStr()), - aRet.getLength()); - OUStringBuffer aBase64Data; - comphelper::Base64::encode(aBase64Data, aSeq); - - // Embed in HTML. - static const OString aHeader - = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">" - "<html><head>" - "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\"/><meta " - "name=\"generator\" content=\"" - + getGenerator().toUtf8() - + "\"/>" - "</head><body><img src=\"data:image/png;charset=utf-8;base64,"; - - aRet = aHeader + aBase64Data.makeStringAndClear().toUtf8() + "\"/></body></html>"; - - return true; + // Desperate measures - convert text to HTML instead. + if (encodeTextAsHTML(xTransferable, "text/plain;charset=utf-8", aRet)) + return true; + // If html is not supported, might be a graphic-selection, + if (encodeImageAsHTML(xTransferable, "image/png", aRet)) + return true; } SetLastExceptionMsg("Flavor " + aFlavor.MimeType + " is not supported"); @@ -3593,7 +3628,7 @@ static int doc_getSelectionType(LibreOfficeKitDocument* pThis) if (!bSuccess) return LOK_SELTYPE_NONE; - if (aRet.getLength() > 1000) // About 2 paragraphs. + if (aRet.getLength() > 10000) return LOK_SELTYPE_COMPLEX; return aRet.getLength() ? LOK_SELTYPE_TEXT : LOK_SELTYPE_NONE; commit cdc350d253405ff85fbe1f5d1bb6a54f95319ff5 Author: Michael Meeks <michael.me...@collabora.com> AuthorDate: Sat Jul 20 11:15:05 2019 +0100 Commit: Michael Meeks <michael.me...@collabora.com> CommitDate: Sat Jul 27 08:46:37 2019 -0400 lok: minimal implementation of isComplex for calc for now. Change-Id: Ic4141d30a0ff48a9ec5ecc8e6119d9d779c4a0fc diff --git a/sc/source/ui/app/seltrans.cxx b/sc/source/ui/app/seltrans.cxx index 79a0437f6061..3a1c2128d560 100644 --- a/sc/source/ui/app/seltrans.cxx +++ b/sc/source/ui/app/seltrans.cxx @@ -413,4 +413,16 @@ void ScSelectionTransferObj::ObjectReleased() TransferableHelper::ObjectReleased(); } +sal_Bool SAL_CALL ScSelectionTransferObj::isComplex() +{ + switch (eMode) + { + case SC_SELTRANS_CELL: + case SC_SELTRANS_CELLS: + return false; + default: + return true; + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/app/transobj.cxx b/sc/source/ui/app/transobj.cxx index c78e8ae9e859..dfa3d47cf8e9 100644 --- a/sc/source/ui/app/transobj.cxx +++ b/sc/source/ui/app/transobj.cxx @@ -234,6 +234,42 @@ void ScTransferObj::AddSupportedFormats() } } +static ScRange lcl_reduceBlock(ScDocumentUniquePtr &pDoc, ScRange aReducedBlock, bool bIncludeVisual = false) +{ + if ((aReducedBlock.aEnd.Col() == MAXCOL || aReducedBlock.aEnd.Row() == MAXROW) && + aReducedBlock.aStart.Tab() == aReducedBlock.aEnd.Tab()) + { + // Shrink the block here so we don't waste time creating huge + // output when whole columns or rows are selected. + + SCCOL nPrintAreaEndCol = 0; + SCROW nPrintAreaEndRow = 0; + if (bIncludeVisual) + pDoc->GetPrintArea( aReducedBlock.aStart.Tab(), nPrintAreaEndCol, nPrintAreaEndRow, true ); + + // Shrink the area to allow pasting to external applications. + // Shrink to real data area for HTML, RTF and RICHTEXT, but include + // all objects and top-left area for BITMAP and PNG. + SCCOL nStartCol = aReducedBlock.aStart.Col(); + SCROW nStartRow = aReducedBlock.aStart.Row(); + SCCOL nEndCol = aReducedBlock.aEnd.Col(); + SCROW nEndRow = aReducedBlock.aEnd.Row(); + bool bShrunk = false; + pDoc->ShrinkToUsedDataArea( bShrunk, aReducedBlock.aStart.Tab(), nStartCol, nStartRow, nEndCol, nEndRow, + false, bIncludeVisual /*bStickyTopRow*/, bIncludeVisual /*bStickyLeftCol*/, + bIncludeVisual /*bConsiderCellNotes*/, bIncludeVisual /*bConsiderCellDrawObjects*/); + + if ( nPrintAreaEndRow > nEndRow ) + nEndRow = nPrintAreaEndRow; + + if ( nPrintAreaEndCol > nEndCol ) + nEndCol = nPrintAreaEndCol; + + aReducedBlock = ScRange(nStartCol, nStartRow, aReducedBlock.aStart.Tab(), nEndCol, nEndRow, aReducedBlock.aEnd.Tab()); + } + return aReducedBlock; +} + bool ScTransferObj::GetData( const datatransfer::DataFlavor& rFlavor, const OUString& /*rDestDoc*/ ) { SotClipboardFormatId nFormat = SotExchange::GetFormat( rFlavor ); @@ -250,39 +286,11 @@ bool ScTransferObj::GetData( const datatransfer::DataFlavor& rFlavor, const OUSt || nFormat == SotClipboardFormatId::BITMAP || nFormat == SotClipboardFormatId::PNG; - if (bReduceBlockFormat && (m_aBlock.aEnd.Col() == MAXCOL || m_aBlock.aEnd.Row() == MAXROW) && - m_aBlock.aStart.Tab() == m_aBlock.aEnd.Tab()) - { - // Shrink the block here so we don't waste time creating huge - // output when whole columns or rows are selected. - - SCCOL nPrintAreaEndCol = 0; - SCROW nPrintAreaEndRow = 0; - const bool bIncludeVisual = (nFormat == SotClipboardFormatId::BITMAP || - nFormat == SotClipboardFormatId::PNG); - if (bIncludeVisual) - m_pDoc->GetPrintArea( m_aBlock.aStart.Tab(), nPrintAreaEndCol, nPrintAreaEndRow, true ); - - // Shrink the area to allow pasting to external applications. - // Shrink to real data area for HTML, RTF and RICHTEXT, but include - // all objects and top-left area for BITMAP and PNG. - SCCOL nStartCol = aReducedBlock.aStart.Col(); - SCROW nStartRow = aReducedBlock.aStart.Row(); - SCCOL nEndCol = aReducedBlock.aEnd.Col(); - SCROW nEndRow = aReducedBlock.aEnd.Row(); - bool bShrunk = false; - m_pDoc->ShrinkToUsedDataArea( bShrunk, aReducedBlock.aStart.Tab(), nStartCol, nStartRow, nEndCol, nEndRow, - false, bIncludeVisual /*bStickyTopRow*/, bIncludeVisual /*bStickyLeftCol*/, - bIncludeVisual /*bConsiderCellNotes*/, bIncludeVisual /*bConsiderCellDrawObjects*/); - - if ( nPrintAreaEndRow > nEndRow ) - nEndRow = nPrintAreaEndRow; - - if ( nPrintAreaEndCol > nEndCol ) - nEndCol = nPrintAreaEndCol; - - aReducedBlock = ScRange(nStartCol, nStartRow, aReducedBlock.aStart.Tab(), nEndCol, nEndRow, aReducedBlock.aEnd.Tab()); - } + const bool bIncludeVisual = (nFormat == SotClipboardFormatId::BITMAP || + nFormat == SotClipboardFormatId::PNG); + + if (bReduceBlockFormat) + aReducedBlock = lcl_reduceBlock(m_pDoc, m_aBlock, bIncludeVisual); if ( nFormat == SotClipboardFormatId::LINKSRCDESCRIPTOR || nFormat == SotClipboardFormatId::OBJECTDESCRIPTOR ) { @@ -535,6 +543,15 @@ bool ScTransferObj::WriteObject( tools::SvRef<SotStorageStream>& rxOStm, void* p return bRet; } +sal_Bool SAL_CALL ScTransferObj::isComplex() +{ + ScRange aReduced = lcl_reduceBlock(m_pDoc, m_aBlock); + size_t nCells = (aReduced.aEnd.Col() - aReduced.aStart.Col() + 1) * + (aReduced.aEnd.Row() - aReduced.aStart.Row() + 1) * + (aReduced.aEnd.Tab() - aReduced.aStart.Tab() + 1); + return nCells > 1000; +} + void ScTransferObj::DragFinished( sal_Int8 nDropAction ) { if ( nDropAction == DND_ACTION_MOVE && !m_bDragWasInternal && !(m_nDragSourceFlags & ScDragSrc::Navigator) ) diff --git a/sc/source/ui/inc/seltrans.hxx b/sc/source/ui/inc/seltrans.hxx index af73f0adf896..83adb2c11eb2 100644 --- a/sc/source/ui/inc/seltrans.hxx +++ b/sc/source/ui/inc/seltrans.hxx @@ -67,6 +67,7 @@ public: virtual void AddSupportedFormats() override; virtual bool GetData( const css::datatransfer::DataFlavor& rFlavor, const OUString& rDestDoc ) override; virtual void ObjectReleased() override; + virtual sal_Bool SAL_CALL isComplex() override; }; #endif diff --git a/sc/source/ui/inc/transobj.hxx b/sc/source/ui/inc/transobj.hxx index 5b7f405fb55e..1ebfd1a4e892 100644 --- a/sc/source/ui/inc/transobj.hxx +++ b/sc/source/ui/inc/transobj.hxx @@ -76,6 +76,7 @@ public: virtual bool WriteObject( tools::SvRef<SotStorageStream>& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId, const css::datatransfer::DataFlavor& rFlavor ) override; virtual void DragFinished( sal_Int8 nDropAction ) override; + virtual sal_Bool SAL_CALL isComplex() override; ScDocument* GetDocument() const { return m_pDoc.get(); } // owned by ScTransferObj const ScRange& GetRange() const { return m_aBlock; } diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx b/sw/source/uibase/dochdl/swdtflvr.cxx index 798b3dd23e3a..f4b8bf904532 100644 --- a/sw/source/uibase/dochdl/swdtflvr.cxx +++ b/sw/source/uibase/dochdl/swdtflvr.cxx @@ -419,7 +419,7 @@ namespace } } -sal_Bool SwTransferable::isComplex() +sal_Bool SAL_CALL SwTransferable::isComplex() { // Copy into a new Doc so we don't mess with the existing one. //FIXME: We *should* be able to avoid this and improve the performance. diff --git a/sw/source/uibase/inc/swdtflvr.hxx b/sw/source/uibase/inc/swdtflvr.hxx index 0b15b8f15acf..c19bc8efc075 100644 --- a/sw/source/uibase/inc/swdtflvr.hxx +++ b/sw/source/uibase/inc/swdtflvr.hxx @@ -151,7 +151,7 @@ protected: const css::datatransfer::DataFlavor& rFlavor ) override; virtual void DragFinished( sal_Int8 nDropAction ) override; virtual void ObjectReleased() override; - virtual sal_Bool isComplex() override; + virtual sal_Bool SAL_CALL isComplex() override; using TransferableHelper::StartDrag; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits