[Libreoffice-commits] online.git: android/lib loleaflet/src

Michael Meeks (via logerrit) logerrit at kemper.freedesktop.org
Thu Dec 19 00:19:33 UTC 2019


 android/lib/src/main/cpp/androidapp.cpp                              |   42 +++
 android/lib/src/main/java/org/libreoffice/androidlib/LOActivity.java |  124 ++++++----
 loleaflet/src/control/Control.JSDialogBuilder.js                     |    2 
 loleaflet/src/map/Map.js                                             |    2 
 4 files changed, 126 insertions(+), 44 deletions(-)

New commits:
commit 76114dd957e8f121969dd206213b3a31a4de7afc
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Wed Dec 18 17:10:04 2019 +0000
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Thu Dec 19 01:19:08 2019 +0100

    android: improved native copy/paste.
    
    don't do copy/paste in the JS if we can avoid it.
    support text & html for cut / copy and share code.
    inject our own origin cookie to allow local short-circuiting.
    
    Change-Id: I3187104e9602e86b50cf52d45a9277db44ca8b3b
    Reviewed-on: https://gerrit.libreoffice.org/85455
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Jan Holesovsky <kendy at collabora.com>

diff --git a/android/lib/src/main/cpp/androidapp.cpp b/android/lib/src/main/cpp/androidapp.cpp
index d964d3579..577df5a90 100644
--- a/android/lib/src/main/cpp/androidapp.cpp
+++ b/android/lib/src/main/cpp/androidapp.cpp
@@ -333,11 +333,47 @@ Java_org_libreoffice_androidlib_LOActivity_saveAs(JNIEnv *env, jobject instance,
     env->ReleaseStringUTFChars(format_, format);
 }
 
+static jstring tojstringAndFree(JNIEnv *env, char *str)
+{
+    if (!str)
+        return env->NewStringUTF("");
+    jstring ret = env->NewStringUTF(str);
+    free(str);
+    return ret;
+}
+
 extern "C"
-JNIEXPORT jstring JNICALL
-Java_org_libreoffice_androidlib_LOActivity_getTextSelection(JNIEnv *env, jobject instance) {
+JNIEXPORT jobjectArray JNICALL
+Java_org_libreoffice_androidlib_LOActivity_getClipboardContent(JNIEnv *env, jobject instance)
+{
+    const char *mimeTypes[] = { "text/plain;charset=utf-8", "text/html", nullptr };
+    size_t outCount = 0;
+    char  **outMimeTypes = nullptr;
+    size_t *outSizes = nullptr;
+    char  **outStreams = nullptr;
+
+    jobjectArray values = (jobjectArray)env->NewObjectArray(2,env->FindClass("java/lang/String"),env->NewStringUTF(""));
+
+    if (getLOKDocument()->getClipboard(mimeTypes,
+                                       &outCount, &outMimeTypes,
+                                       &outSizes, &outStreams))
+    {
+        if (outCount != 2)
+            LOG_DBG("clipboard fetch produced wrong results");
+        else
+        {
+            env->SetObjectArrayElement(values,0,tojstringAndFree(env, outStreams[0]));
+            env->SetObjectArrayElement(values,1,tojstringAndFree(env, outStreams[1]));
+            free (outMimeTypes[0]);
+            free (outMimeTypes[1]);
+            free (outMimeTypes);
+            free (outStreams);
+        }
+    }
+    else
+        LOG_DBG("failed to fetch mime-types");
 
-    return env->NewStringUTF(getLOKDocument()->getTextSelection("text/plain;charset=utf-8"));
+    return values;
 }
 
 extern "C"
diff --git a/android/lib/src/main/java/org/libreoffice/androidlib/LOActivity.java b/android/lib/src/main/java/org/libreoffice/androidlib/LOActivity.java
index e1efc01f9..713032122 100644
--- a/android/lib/src/main/java/org/libreoffice/androidlib/LOActivity.java
+++ b/android/lib/src/main/java/org/libreoffice/androidlib/LOActivity.java
@@ -78,6 +78,9 @@ public class LOActivity extends AppCompatActivity {
 
     private int providerId;
 
+    /// Unique number identifying this app + document.
+    private long loadDocumentMillis = 0;
+
     @Nullable
     private URI documentUri;
 
@@ -478,6 +481,8 @@ public class LOActivity extends AppCompatActivity {
         mWebView.loadUrl(finalUrlToLoad);
 
         documentLoaded = true;
+
+        loadDocumentMillis = android.os.SystemClock.uptimeMillis();
     }
 
     static {
@@ -564,46 +569,13 @@ public class LOActivity extends AppCompatActivity {
             case "uno":
                 switch (messageAndParam[1]) {
                     case ".uno:Paste":
-                        clipData = clipboardManager.getPrimaryClip();
-                        if (clipData != null) {
-                            if (clipData.getDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {
-                                final ClipData.Item clipItem = clipData.getItemAt(0);
-                                nativeHandler.post(new Runnable() {
-                                    @Override
-                                    public void run() {
-                                        LOActivity.this.paste("text/plain;charset=utf-16", clipItem.getText().toString());
-                                    }
-                                });
-                            }
-                            return false;
-                        }
+                        return performPaste();
+                    case ".uno:Copy":
+                    case ".uno:Cut":
+                        populateClipboard();
                         break;
-                    case ".uno:Copy": {
-                        nativeHandler.post(new Runnable() {
-                            @Override
-                            public void run() {
-                                String tempSelectedText = LOActivity.this.getTextSelection();
-                                if (!tempSelectedText.equals("")) {
-                                    clipData = ClipData.newPlainText(ClipDescription.MIMETYPE_TEXT_PLAIN, tempSelectedText);
-                                    clipboardManager.setPrimaryClip(clipData);
-                                }
-                            }
-                        });
+                    default:
                         break;
-                    }
-                    case ".uno:Cut": {
-                        nativeHandler.post(new Runnable() {
-                            @Override
-                            public void run() {
-                                String tempSelectedText = LOActivity.this.getTextSelection();
-                                if (!tempSelectedText.equals("")) {
-                                    clipData = ClipData.newPlainText(ClipDescription.MIMETYPE_TEXT_PLAIN, tempSelectedText);
-                                    clipboardManager.setPrimaryClip(clipData);
-                                }
-                            }
-                        });
-                        break;
-                    }
                 }
                 break;
             case "DIM_SCREEN": {
@@ -671,9 +643,83 @@ public class LOActivity extends AppCompatActivity {
 
     public native void saveAs(String fileUri, String format);
 
-    public native String getTextSelection();
+    public native String[] getClipboardContent();
 
     public native void paste(String mimeType, String data);
+
+    /// Returns a magic that specifies this application - and this document.
+    private final String getClipboardMagic() {
+        return "lool-clip-magic-4a22437e49a8-" + Long.toString(loadDocumentMillis);
+    }
+
+    /// Needs to be executed after the .uno:Copy / Paste has executed
+    public final void populateClipboard()
+    {
+        /// FIXME: in theory we can do better with URIs to temporary files and so on...
+        nativeHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    // text[0], html[1]
+                    String[] clipStrings = LOActivity.this.getClipboardContent();
+                    if (clipStrings.length < 2 ||
+                        (clipStrings[0].length() == 0 && clipStrings[1].length() == 0))
+                        Log.e(TAG, "no clipboard to copy");
+                    else
+                    {
+                        String text = clipStrings[0];
+                        String html = clipStrings[1];
+
+                        int idx = html.indexOf("<meta name=\"generator\" content=\"");
+                        if (idx < 0)
+                            idx = html.indexOf("<meta http-equiv=\"content-type\" content=\"text/html;");
+                        if (idx >= 0) { // inject our magic
+                            StringBuffer newHtml = new StringBuffer(html);
+                            newHtml.insert(idx, "<meta name=\"origin\" content=\"" + getClipboardMagic() + "\"/>\n");
+                            html = newHtml.toString();
+                        }
+
+                        if (text == null || text.length() == 0)
+                            Log.i(TAG, "set text to clipoard with: text '" + text + "' and html '" + html + "'");
+                        clipData = ClipData.newHtmlText(ClipDescription.MIMETYPE_TEXT_HTML, text, html);
+                        clipboardManager.setPrimaryClip(clipData);
+                    }
+                }
+            });
+    }
+
+    /// Do the paste, and return true if we should short-circuit the paste locally
+    private final boolean performPaste()
+    {
+        clipData = clipboardManager.getPrimaryClip();
+        ClipDescription clipDesc = clipData != null ? clipData.getDescription() : null;
+        if (clipDesc != null) {
+            if (clipDesc.hasMimeType(ClipDescription.MIMETYPE_TEXT_HTML)) {
+                final String html = clipData.getItemAt(0).getHtmlText();
+                if (html.contains(getClipboardMagic())) {
+                    Log.i(TAG, "clipboard comes from us: short circuit it " + html);
+                    return true;
+                } else {
+                    Log.i(TAG, "foreign html '" + html + "'");
+                    nativeHandler.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            LOActivity.this.paste("text/html", html);
+                        }
+                    });
+                }
+            }
+            else if (clipDesc.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {
+                final ClipData.Item clipItem = clipData.getItemAt(0);
+                nativeHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        LOActivity.this.paste("text/plain;charset=utf-16", clipItem.getText().toString());
+                    }
+                });
+            }
+        }
+        return false;
+    }
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/loleaflet/src/control/Control.JSDialogBuilder.js b/loleaflet/src/control/Control.JSDialogBuilder.js
index 617a8d9d0..9d91807cd 100644
--- a/loleaflet/src/control/Control.JSDialogBuilder.js
+++ b/loleaflet/src/control/Control.JSDialogBuilder.js
@@ -1444,7 +1444,7 @@ L.Control.JSDialogBuilder = L.Control.extend({
 				// before close the wizard then execute the action
 				if (data.executionType === 'action') {
 					builder.map.menubar._executeAction(undefined, data.id);
-				} else if (!builder.map._clip.filterExecCopyPaste(data.command)) {
+				} else if (!builder.map._clip || !builder.map._clip.filterExecCopyPaste(data.command)) {
 					builder.map.sendUnoCommand(data.command)
 				}
 			});
diff --git a/loleaflet/src/map/Map.js b/loleaflet/src/map/Map.js
index 58d9cf849..778013556 100644
--- a/loleaflet/src/map/Map.js
+++ b/loleaflet/src/map/Map.js
@@ -58,7 +58,7 @@ L.Map = L.Evented.extend({
 			this.options.documentContainer = L.DomUtil.get(this.options.documentContainer);
 		}
 
-		if (!window.ThisIsTheiOSApp)
+		if (!window.ThisIsTheiOSApp && !window.ThisIsTheAndroidApp)
 			this._clip = L.clipboard(this);
 		this._initContainer(id);
 		this._initLayout();


More information about the Libreoffice-commits mailing list