vcl/unx/gtk3/app/gtk3gtkinst.cxx | 184 ++++++++++++++++++++++++++++++++++----- 1 file changed, 164 insertions(+), 20 deletions(-)
New commits: commit 698120857eecc0afa90bc408a3e0a41eee21f1dd Author: Caolán McNamara <caol...@redhat.com> Date: Thu Jun 18 16:28:52 2015 +0100 gtk3: implement paste from us Change-Id: Iea25d633a833965814a08d87954906e0133f7076 diff --git a/vcl/unx/gtk3/app/gtk3gtkinst.cxx b/vcl/unx/gtk3/app/gtk3gtkinst.cxx index ae5b338..baa558d 100644 --- a/vcl/unx/gtk3/app/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/app/gtk3gtkinst.cxx @@ -203,7 +203,7 @@ public: return aVector; } - virtual css::uno::Sequence< css::datatransfer::DataFlavor > SAL_CALL getTransferDataFlavors() + virtual css::uno::Sequence<css::datatransfer::DataFlavor> SAL_CALL getTransferDataFlavors() throw(css::uno::RuntimeException, std::exception) SAL_OVERRIDE { return comphelper::containerToSequence(getTransferDataFlavorsAsVector()); @@ -222,13 +222,14 @@ public: class VclGtkClipboard : public cppu::WeakComponentImplHelper< datatransfer::clipboard::XSystemClipboard, - XServiceInfo - > + XServiceInfo> { - osl::Mutex m_aMutex; - Reference< css::datatransfer::XTransferable > m_aContents; - Reference< css::datatransfer::clipboard::XClipboardOwner > m_aOwner; - std::list< Reference< css::datatransfer::clipboard::XClipboardListener > > m_aListeners; + osl::Mutex m_aMutex; + Reference<css::datatransfer::XTransferable> m_aContents; + Reference<css::datatransfer::clipboard::XClipboardOwner> m_aOwner; + std::list< Reference<css::datatransfer::clipboard::XClipboardListener> > m_aListeners; + std::vector<GtkTargetEntry> m_aGtkTargets; + std::vector<css::datatransfer::DataFlavor> m_aInfoToFlavor; public: @@ -238,6 +239,7 @@ public: >( m_aMutex ) { } + virtual ~VclGtkClipboard() { } @@ -285,6 +287,11 @@ public: virtual void SAL_CALL removeClipboardListener( const Reference< css::datatransfer::clipboard::XClipboardListener >& listener ) throw(RuntimeException, std::exception) SAL_OVERRIDE; + + void ClipboardGet(GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info); + void ClipboardClear(GtkClipboard *clipboard); +private: + GtkTargetEntry makeGtkTargetEntry(const css::datatransfer::DataFlavor& rFlavor); }; OUString VclGtkClipboard::getImplementationName_static() @@ -322,6 +329,107 @@ Reference< css::datatransfer::XTransferable > VclGtkClipboard::getContents() thr return m_aContents; } +namespace +{ + void ClipboardGetFunc(GtkClipboard *clipboard, GtkSelectionData *selection_data, + guint info, + gpointer user_data_or_owner) + { + VclGtkClipboard* pThis = static_cast<VclGtkClipboard*>(user_data_or_owner); + pThis->ClipboardGet(clipboard, selection_data, info); + } + + void ClipboardClearFunc(GtkClipboard *clipboard, gpointer user_data_or_owner) + { + VclGtkClipboard* pThis = static_cast<VclGtkClipboard*>(user_data_or_owner); + pThis->ClipboardClear(clipboard); + } +} + +void VclGtkClipboard::ClipboardGet(GtkClipboard *clipboard, GtkSelectionData *selection_data, + guint info) +{ + + GdkAtom type(gdk_atom_intern(OUStringToOString(m_aInfoToFlavor[info].MimeType, + RTL_TEXTENCODING_UTF8).getStr(), + false)); + + css::datatransfer::DataFlavor aFlavor(m_aInfoToFlavor[info]); + if (aFlavor.MimeType == "UTF8_STRING" || aFlavor.MimeType == "STRING") + aFlavor.MimeType = "text/plain;charset=utf-8"; + + Sequence<sal_Int8> aData; + Any aValue; + + try + { + aValue = m_aContents->getTransferData(aFlavor); + } + catch(...) + { + } + + if (aValue.getValueTypeClass() == TypeClass_STRING) + { + OUString aString; + aValue >>= aString; + aData = Sequence< sal_Int8 >( reinterpret_cast<sal_Int8 const *>(aString.getStr()), aString.getLength() * sizeof( sal_Unicode ) ); + } + else if (aValue.getValueType() == cppu::UnoType<Sequence< sal_Int8 >>::get()) + { + aValue >>= aData; + } + else if (aFlavor.MimeType == "text/plain;charset=utf-8") + { + //didn't have utf-8, try utf-16 and convert + aFlavor.MimeType = "text/plain;charset=utf-16"; + aFlavor.DataType = cppu::UnoType<OUString>::get(); + try + { + aValue = m_aContents->getTransferData(aFlavor); + } + catch(...) + { + } + OUString aString; + aValue >>= aString; + OString aUTF8String(OUStringToOString(aString, RTL_TEXTENCODING_UTF8)); + gtk_selection_data_set(selection_data, type, 8, + reinterpret_cast<const guchar *>(aUTF8String.getStr()), + aUTF8String.getLength()); + return; + } + + gtk_selection_data_set(selection_data, type, 8, + reinterpret_cast<const guchar *>(aData.getArray()), + aData.getLength()); +} + +void VclGtkClipboard::ClipboardClear(GtkClipboard * /*clipboard*/) +{ + for (auto &a : m_aGtkTargets) + free(a.target); + m_aGtkTargets.clear(); +} + +GtkTargetEntry VclGtkClipboard::makeGtkTargetEntry(const css::datatransfer::DataFlavor& rFlavor) +{ + GtkTargetEntry aEntry; + aEntry.target = + g_strdup(OUStringToOString(rFlavor.MimeType, RTL_TEXTENCODING_UTF8).getStr()); + aEntry.flags = 0; + auto it = std::find_if(m_aInfoToFlavor.begin(), m_aInfoToFlavor.end(), + DataFlavorEq(rFlavor)); + if (it != m_aInfoToFlavor.end()) + aEntry.info = std::distance(m_aInfoToFlavor.begin(), it); + else + { + aEntry.info = m_aInfoToFlavor.size(); + m_aInfoToFlavor.push_back(rFlavor); + } + return aEntry; +} + void VclGtkClipboard::setContents( const Reference< css::datatransfer::XTransferable >& xTrans, const Reference< css::datatransfer::clipboard::XClipboardOwner >& xClipboardOwner ) @@ -337,6 +445,52 @@ void VclGtkClipboard::setContents( datatransfer::clipboard::ClipboardEvent aEv; aEv.Contents = m_aContents; + if (m_aContents.is()) + { + css::uno::Sequence<css::datatransfer::DataFlavor> aFormats = xTrans->getTransferDataFlavors(); + std::vector<GtkTargetEntry> aGtkTargets; + bool bHaveText(false), bHaveUTF8(false); + for (int i = 0; i < aFormats.getLength(); ++i) + { + const css::datatransfer::DataFlavor& rFlavor = aFormats[i]; + + sal_Int32 nIndex(0); + if (rFlavor.MimeType.getToken(0, ';', nIndex) == "text/plain") + { + bHaveText = true; + OUString aToken(rFlavor.MimeType.getToken(0, ';', nIndex)); + if (aToken == "charset=utf-8") + { + bHaveUTF8 = true; + } + } + GtkTargetEntry aEntry(makeGtkTargetEntry(rFlavor)); + aGtkTargets.push_back(aEntry); + } + + if (bHaveText) + { + css::datatransfer::DataFlavor aFlavor; + aFlavor.DataType = cppu::UnoType<Sequence< sal_Int8 >>::get(); + if (!bHaveUTF8) + { + aFlavor.MimeType = "text/plain;charset=utf-8"; + aGtkTargets.push_back(makeGtkTargetEntry(aFlavor)); + } + aFlavor.MimeType = "UTF8_STRING"; + aGtkTargets.push_back(makeGtkTargetEntry(aFlavor)); + aFlavor.MimeType = "STRING"; + aGtkTargets.push_back(makeGtkTargetEntry(aFlavor)); + } + + //if there was a previous gtk_clipboard_set_with_data call then + //ClipboardClearFunc will be called now + GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); + gtk_clipboard_set_with_data(clipboard, aGtkTargets.data(), aGtkTargets.size(), + ClipboardGetFunc, ClipboardClearFunc, this); + m_aGtkTargets = aGtkTargets; + } + aGuard.clear(); if( xOldOwner.is() && xOldOwner != xClipboardOwner ) commit ceb31879c4fc3dd3e62a45318f22c1f69db9974a Author: Caolán McNamara <caol...@redhat.com> Date: Thu Jun 18 14:02:54 2015 +0100 gtk3: little code cleanup Change-Id: I3e0f1fe0376ddcf9e79e6815a13f54007d47b03e diff --git a/vcl/unx/gtk3/app/gtk3gtkinst.cxx b/vcl/unx/gtk3/app/gtk3gtkinst.cxx index 0b5ea9f..ae5b338 100644 --- a/vcl/unx/gtk3/app/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/app/gtk3gtkinst.cxx @@ -98,14 +98,6 @@ class GtkTransferable : public ::cppu::WeakImplHelper1 < private: std::map<OUString, GdkAtom> m_aMimeTypeToAtom; public: - GtkTransferable() - { - } - - virtual ~GtkTransferable() - { - } - /* * XTransferable */ @@ -246,7 +238,9 @@ public: >( m_aMutex ) { } - virtual ~VclGtkClipboard(); + virtual ~VclGtkClipboard() + { + } /* * XServiceInfo @@ -293,10 +287,6 @@ public: throw(RuntimeException, std::exception) SAL_OVERRIDE; }; -VclGtkClipboard::~VclGtkClipboard() -{ -} - OUString VclGtkClipboard::getImplementationName_static() { return OUString( "com.sun.star.datatransfer.VclGtkClipboard" );
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits