vcl/ios/clipboard.cxx |   77 +++++++++++++++++++++++++++++++++++++++++++++++++-
 vcl/ios/clipboard.hxx |   15 +++++++++
 2 files changed, 91 insertions(+), 1 deletion(-)

New commits:
commit 4e5040dc44024f8313ca51627b6871675865cdf6
Author:     Patrick Luby <guibmac...@gmail.com>
AuthorDate: Sat Apr 13 19:46:48 2024 -0400
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Mon May 13 12:05:05 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 <guibomac...@gmail.com>
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Andras Timar <andras.ti...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167570
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

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: */
  • core.git: vcl/ios Patrick Luby (via logerrit)

Reply via email to