Rebased ref, commits from common ancestor: commit a835eb88f466f09808a6a777d3d9f0f3932922c8 Author: Michael Meeks <michael.me...@collabora.com> AuthorDate: Mon Jul 22 09:48:46 2019 +0100 Commit: Michael Meeks <michael.me...@collabora.com> CommitDate: Mon Jul 22 10:23:12 2019 +0100
lok: share more clipboard type 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 8e08a83a5afb3b8a64505b5b3738ce9d38a11e9a Author: Michael Meeks <michael.me...@collabora.com> AuthorDate: Sat Jul 20 11:22:09 2019 +0100 Commit: Michael Meeks <michael.me...@collabora.com> CommitDate: Mon Jul 22 10:23:11 2019 +0100 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 a738cc906ab7fb5557963a9b121358fab1160529 Author: Michael Meeks <michael.me...@collabora.com> AuthorDate: Fri Jun 28 18:36:15 2019 +0100 Commit: Michael Meeks <michael.me...@collabora.com> CommitDate: Mon Jul 22 10:23:10 2019 +0100 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 7562133b52c4..32d1edbed9ef 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -3339,6 +3339,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); @@ -3364,28 +3412,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"); @@ -3503,7 +3538,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 ec6cd857057f9971a133e0964ba9faa34cd6e608 Author: Michael Meeks <michael.me...@collabora.com> AuthorDate: Sat Jul 20 11:15:05 2019 +0100 Commit: Michael Meeks <michael.me...@collabora.com> CommitDate: Mon Jul 22 10:23:09 2019 +0100 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..0ed12820fb3c 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 4873c20b392b..3f1fe21ff54f 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