summaryrefslogtreecommitdiff
path: root/vcl/ios/clipboard.cxx
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2019-05-24 01:51:00 +0300
committerTor Lillqvist <tml@collabora.com>2019-05-28 12:39:09 +0300
commitb8c1f54d67c5ae90a868f9b33747c43b97c23351 (patch)
tree37ea8331c239d83d7c919a36a5262e6634ee7dbf /vcl/ios/clipboard.cxx
parent1c7a2eff17f09feaa2709eaab60855f8e1aa7469 (diff)
tdf#124752: Add system clipboard interface for iOS
Based on the corresponding macOS code. Work in progress. The image support ifdeffed out still (because it uses some macOS specific APIs for which I couldn't right away find the equivalent iOS ones). I made it much simpler than the macOS code. I dropped the keeping of a local in-process clipboard completely. Firstly, as far as I see, the iOS clipboard API (UIPasteboard etc) does not even offer the possibility to separately offer some formats and actually provide the data on request. Secondly, we must be prepared anyway that the system can kill an iOS app at any stage while the user is using some other app, so we need to make sure everything that is copied goes onto the system clipboard right away anyway. I had to disable the copying of HTML to the clipboard as that lead to a mysterious assertion failure. See comment in DataFlavorMapper::openOfficeToSystemFlavor(). But RTF seems to work well, too. I assume RTF is what gets used for cross-application copy/paste (and cross-device, even, through Apple's Universal Clipboard thing, where you can copy/paste between your Macs and iOS devices on the same network). I am not sure how relevant the various application/x-openoffice-foo formats are. Change-Id: I174495e33d86fc3990996c229243c05d6cbfcda7
Diffstat (limited to 'vcl/ios/clipboard.cxx')
-rw-r--r--vcl/ios/clipboard.cxx185
1 files changed, 185 insertions, 0 deletions
diff --git a/vcl/ios/clipboard.cxx b/vcl/ios/clipboard.cxx
new file mode 100644
index 000000000000..b60cda1bef4d
--- /dev/null
+++ b/vcl/ios/clipboard.cxx
@@ -0,0 +1,185 @@
+/* -*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ios/iosinst.hxx"
+
+#include "clipboard.hxx"
+
+#include "DataFlavorMapping.hxx"
+#include "iOSTransferable.hxx"
+#include <com/sun/star/datatransfer/MimeContentTypeFactory.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <comphelper/processfactory.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+iOSClipboard::iOSClipboard()
+ : WeakComponentImplHelper<XSystemClipboard, XServiceInfo>(m_aMutex)
+{
+ auto xContext = comphelper::getProcessComponentContext();
+
+ mrXMimeCntFactory = css::datatransfer::MimeContentTypeFactory::create(xContext);
+
+ mpDataFlavorMapper.reset(new DataFlavorMapper());
+
+ mPasteboard = [UIPasteboard generalPasteboard];
+ assert(mPasteboard != nil);
+}
+
+iOSClipboard::~iOSClipboard() {}
+
+css::uno::Reference<css::datatransfer::XTransferable> SAL_CALL iOSClipboard::getContents()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ return css::uno::Reference<css::datatransfer::XTransferable>(
+ new iOSTransferable(mrXMimeCntFactory, mpDataFlavorMapper, mPasteboard));
+}
+
+void SAL_CALL iOSClipboard::setContents(
+ const css::uno::Reference<css::datatransfer::XTransferable>& xTransferable,
+ const css::uno::Reference<css::datatransfer::clipboard::XClipboardOwner>& /*xClipboardOwner*/)
+{
+ NSArray* types = xTransferable.is() ? mpDataFlavorMapper->flavorSequenceToTypesArray(
+ xTransferable->getTransferDataFlavors())
+ : [NSArray array];
+
+ osl::ClearableMutexGuard aGuard(m_aMutex);
+
+ NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithCapacity:1];
+ NSArray* array = @[ dict ];
+
+ for (sal_uInt32 i = 0; i < [types count]; ++i)
+ {
+ DataProviderPtr_t dp = mpDataFlavorMapper->getDataProvider(types[i], xTransferable);
+
+ if (dp.get() != nullptr)
+ {
+ NSData* pBoardData = (NSData*)dp->getSystemData();
+ dict[types[i]] = pBoardData;
+ }
+ }
+ [mPasteboard setItems:array options:@{}];
+
+ // We don't keep a copy of the clipboard contents around in-process, so fire the lost clipboard
+ // ownership event right away.
+ // fireLostClipboardOwnershipEvent(xClipboardOwner, xTransferable);
+
+ // fireClipboardChangedEvent(xTransferable);
+}
+
+OUString SAL_CALL iOSClipboard::getName() { return OUString(); }
+
+sal_Int8 SAL_CALL iOSClipboard::getRenderingCapabilities() { return 0; }
+
+void SAL_CALL iOSClipboard::addClipboardListener(
+ const css::uno::Reference<css::datatransfer::clipboard::XClipboardListener>& listener)
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ if (!listener.is())
+ throw css::lang::IllegalArgumentException(
+ "empty reference", static_cast<css::datatransfer::clipboard::XClipboardEx*>(this), 1);
+
+ mClipboardListeners.push_back(listener);
+}
+
+void SAL_CALL iOSClipboard::removeClipboardListener(
+ const css::uno::Reference<css::datatransfer::clipboard::XClipboardListener>& listener)
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ if (!listener.is())
+ throw css::lang::IllegalArgumentException(
+ "empty reference", static_cast<css::datatransfer::clipboard::XClipboardEx*>(this), 1);
+
+ mClipboardListeners.remove(listener);
+}
+
+void iOSClipboard::fireClipboardChangedEvent(
+ css::uno::Reference<css::datatransfer::XTransferable> xNewContents)
+{
+ osl::ClearableMutexGuard aGuard(m_aMutex);
+
+ std::list<css::uno::Reference<css::datatransfer::clipboard::XClipboardListener>> listeners(
+ mClipboardListeners);
+ css::datatransfer::clipboard::ClipboardEvent aEvent;
+
+ if (!listeners.empty())
+ {
+ aEvent = css::datatransfer::clipboard::ClipboardEvent(static_cast<OWeakObject*>(this),
+ xNewContents);
+ }
+
+ aGuard.clear();
+
+ while (!listeners.empty())
+ {
+ if (listeners.front().is())
+ {
+ try
+ {
+ listeners.front()->changedContents(aEvent);
+ }
+ catch (const css::uno::RuntimeException&)
+ {
+ }
+ }
+ listeners.pop_front();
+ }
+}
+
+void iOSClipboard::fireLostClipboardOwnershipEvent(
+ css::uno::Reference<css::datatransfer::clipboard::XClipboardOwner> const& oldOwner,
+ css::uno::Reference<css::datatransfer::XTransferable> const& oldContent)
+{
+ assert(oldOwner.is());
+
+ try
+ {
+ oldOwner->lostOwnership(static_cast<css::datatransfer::clipboard::XClipboardEx*>(this),
+ oldContent);
+ }
+ catch (const css::uno::RuntimeException&)
+ {
+ }
+}
+
+OUString SAL_CALL iOSClipboard::getImplementationName()
+{
+ return OUString("com.sun.star.datatransfer.clipboard.iOSClipboard");
+}
+
+sal_Bool SAL_CALL iOSClipboard::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL iOSClipboard::getSupportedServiceNames()
+{
+ return { OUString("com.sun.star.datatransfer.clipboard.SystemClipboard") };
+}
+
+css::uno::Reference<css::uno::XInterface>
+IosSalInstance::CreateClipboard(const css::uno::Sequence<css::uno::Any>&)
+{
+ return css::uno::Reference<css::uno::XInterface>(
+ static_cast<cppu::OWeakObject*>(new iOSClipboard()));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */