vcl/ios/clipboard.cxx | 77 +++++++++++++++++++++++++++++++++++++++++++++++++- vcl/ios/clipboard.hxx | 15 +++++++++ 2 files changed, 91 insertions(+), 1 deletion(-)
New commits: commit b16637b716479fcbd50acb47673df7e6d2fbdb61 Author: Patrick Luby <[email protected]> AuthorDate: Sat Apr 13 19:46:48 2024 -0400 Commit: Andras Timar <[email protected]> CommitDate: Mon Apr 15 07:20:46 2024 +0200 cool#5839 fire a clipboard changed event in the iOS app A clipboard changed event needs to be fired whenever the native general pasteboard changes. Otherwise, if the clipboard is empty when a document is opened, the Paste and Paste Special menu items and toolbar buttons will be disabled and will never be enabled even after something has been copied to the general pasteboard. Change-Id: I8a70a2ac4de55593a886233d144dc18c3c57178e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166073 Reviewed-by: Patrick Luby <[email protected]> Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Andras Timar <[email protected]> diff --git a/vcl/ios/clipboard.cxx b/vcl/ios/clipboard.cxx index 59209504da31..109f744e87c8 100644 --- a/vcl/ios/clipboard.cxx +++ b/vcl/ios/clipboard.cxx @@ -29,6 +29,56 @@ #include <comphelper/processfactory.hxx> #include <cppuhelper/supportsservice.hxx> +@implementation PasteboardChangedEventListener + +- (PasteboardChangedEventListener*)initWithiOSClipboard:(iOSClipboard*)pcb +{ + self = [super init]; + + if (self) + { + // Just to be safe, set clipboard to a nullptr to ignore any + // synchronous callbacks that might occur when adding the observer + piOSClipboard = nullptr; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(pasteboardChanged:) + name:UIPasteboardChangedNotification + object:[UIPasteboard generalPasteboard]]; + + // According to following, no UIPasteboardChangedNotification + // notifications are received when an app is not active. So, post the + // notification so that the LibreOffice vcl/ios code can handle any + // clipboard changes: + // https://stackoverflow.com/questions/4240087/receiving-uipasteboard-generalpasteboard-notification-while-in-the-background + // Note: UIApplicationDidBecomeActiveNotification is never sent when + // running in Mac Catalyst so listen for UISceneDidActivateNotification + // instead. + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(pasteboardChanged:) + name:UISceneDidActivateNotification + object:nil]; + + piOSClipboard = pcb; + } + + return self; +} + +- (void)pasteboardChanged:(NSNotification*)aNotification +{ + if (piOSClipboard) + piOSClipboard->contentsChanged(); +} + +- (void)disposing +{ + piOSClipboard = nullptr; + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +@end + iOSClipboard::iOSClipboard() : WeakComponentImplHelper<XSystemClipboard, XServiceInfo>(m_aMutex) { @@ -37,9 +87,17 @@ iOSClipboard::iOSClipboard() mrXMimeCntFactory = css::datatransfer::MimeContentTypeFactory::create(xContext); mpDataFlavorMapper.reset(new DataFlavorMapper()); + + mnPasteboardChangeCount = 0; + mpPasteboardChangedEventListener = + [[PasteboardChangedEventListener alloc] initWithiOSClipboard:this]; } -iOSClipboard::~iOSClipboard() {} +iOSClipboard::~iOSClipboard() +{ + [mpPasteboardChangedEventListener disposing]; + [mpPasteboardChangedEventListener release]; +} css::uno::Reference<css::datatransfer::XTransferable> SAL_CALL iOSClipboard::getContents() { @@ -173,6 +231,23 @@ css::uno::Sequence<OUString> SAL_CALL iOSClipboard::getSupportedServiceNames() return { OUString("com.sun.star.datatransfer.clipboard.SystemClipboard") }; } +void iOSClipboard::contentsChanged() +{ + NSInteger nPasteboardChangeCount = [[UIPasteboard generalPasteboard] changeCount]; + if (mnPasteboardChangeCount != nPasteboardChangeCount) + { + // cool#5839 fire a clipboard changed event in the iOS app + // A clipboard changed event needs to be fired whenever the + // native general pasteboard changes. Otherwise, if the clipboard + // is empty when a document is opened, the Paste and Paste Special + // menu items and toolbar buttons will be disabled and will never + // be enabled even after something has been copied to the general + // pasteboard. + mnPasteboardChangeCount = nPasteboardChangeCount; + fireClipboardChangedEvent(getContents()); + } +} + css::uno::Reference<css::uno::XInterface> IosSalInstance::CreateClipboard(const css::uno::Sequence<css::uno::Any>&) { diff --git a/vcl/ios/clipboard.hxx b/vcl/ios/clipboard.hxx index 086840912650..e1133f0ba0bf 100644 --- a/vcl/ios/clipboard.hxx +++ b/vcl/ios/clipboard.hxx @@ -41,6 +41,17 @@ #import <UIKit/UIKit.h> #include <postmac.h> +class iOSClipboard; + +@interface PasteboardChangedEventListener : NSObject +{ + iOSClipboard* piOSClipboard; +} +- (PasteboardChangedEventListener*)initWithiOSClipboard:(iOSClipboard*)pcb; +- (void)pasteboardChanged:(NSNotification*)aNotification; +- (void)disposing; +@end + class iOSClipboard : public ::cppu::BaseMutex, public ::cppu::WeakComponentImplHelper<css::datatransfer::clipboard::XSystemClipboard, @@ -86,6 +97,8 @@ public: css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; + void contentsChanged(); + private: /* Notify the current clipboard owner that he is no longer the clipboard owner. */ void fireLostClipboardOwnershipEvent( @@ -102,6 +115,8 @@ private: mClipboardListeners; css::uno::Reference<css::datatransfer::clipboard::XClipboardOwner> mXClipboardOwner; std::shared_ptr<DataFlavorMapper> mpDataFlavorMapper; + NSInteger mnPasteboardChangeCount; + PasteboardChangedEventListener* mpPasteboardChangedEventListener; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
