summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/android/jar/CMakeLists.txt1
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtClipboardManager.java228
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java2
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtNative.java173
-rw-r--r--src/plugins/platforms/android/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/android/androidjniclipboard.cpp96
-rw-r--r--src/plugins/platforms/android/androidjniclipboard.h27
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp5
-rw-r--r--src/plugins/platforms/android/qandroidplatformclipboard.cpp84
-rw-r--r--src/plugins/platforms/android/qandroidplatformclipboard.h16
10 files changed, 329 insertions, 306 deletions
diff --git a/src/android/jar/CMakeLists.txt b/src/android/jar/CMakeLists.txt
index e8caf69818..b45b17c483 100644
--- a/src/android/jar/CMakeLists.txt
+++ b/src/android/jar/CMakeLists.txt
@@ -28,6 +28,7 @@ set(java_sources
src/org/qtproject/qt/android/extras/QtAndroidServiceConnection.java
src/org/qtproject/qt/android/extras/QtNative.java
src/org/qtproject/qt/android/QtConstants.java
+ src/org/qtproject/qt/android/QtClipboardManager.java
)
qt_internal_add_jar(Qt${QtBase_VERSION_MAJOR}Android
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtClipboardManager.java b/src/android/jar/src/org/qtproject/qt/android/QtClipboardManager.java
new file mode 100644
index 0000000000..1737a6134a
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt/android/QtClipboardManager.java
@@ -0,0 +1,228 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+package org.qtproject.qt.android;
+
+import android.content.ClipData;
+import android.content.ClipDescription;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Objects;
+import java.util.concurrent.Semaphore;
+
+public class QtClipboardManager
+{
+ public static native void onClipboardDataChanged(long nativePointer);
+
+ private final static String TAG = "QtClipboardManager";
+ private ClipboardManager m_clipboardManager = null;
+ private boolean m_usePrimaryClip = false;
+ private final long m_nativePointer;
+
+ public QtClipboardManager(Context context, long nativePointer)
+ {
+ m_nativePointer = nativePointer;
+ registerClipboardManager(context);
+ }
+
+ private void registerClipboardManager(Context context)
+ {
+ if (context != null) {
+ final Semaphore semaphore = new Semaphore(0);
+ QtNative.runAction(new Runnable() {
+ @Override
+ public void run() {
+ m_clipboardManager =
+ (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
+ if (m_clipboardManager != null) {
+ m_clipboardManager.addPrimaryClipChangedListener(
+ new ClipboardManager.OnPrimaryClipChangedListener() {
+ public void onPrimaryClipChanged() {
+ onClipboardDataChanged(m_nativePointer);
+ }
+ });
+ }
+ semaphore.release();
+ }
+ });
+ try {
+ semaphore.acquire();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void clearClipData()
+ {
+ if (m_clipboardManager != null) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ m_clipboardManager.clearPrimaryClip();
+ } else {
+ String[] mimeTypes = { ClipDescription.MIMETYPE_UNKNOWN };
+ ClipData data = new ClipData("", mimeTypes, new ClipData.Item(new Intent()));
+ m_clipboardManager.setPrimaryClip(data);
+ }
+ }
+ m_usePrimaryClip = false;
+ }
+ public void setClipboardText(Context context, String text)
+ {
+ if (m_clipboardManager != null) {
+ ClipData clipData = ClipData.newPlainText("text/plain", text);
+ updatePrimaryClip(clipData, context);
+ }
+ }
+
+ public static boolean hasClipboardText(Context context)
+ {
+ ClipboardManager clipboardManager =
+ (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
+
+ if (clipboardManager == null)
+ return false;
+
+ ClipDescription description = clipboardManager.getPrimaryClipDescription();
+ // getPrimaryClipDescription can fail if the app does not have input focus
+ if (description == null)
+ return false;
+
+ for (int i = 0; i < description.getMimeTypeCount(); ++i) {
+ String itemMimeType = description.getMimeType(i);
+ if (itemMimeType.matches("text/(.*)"))
+ return true;
+ }
+ return false;
+ }
+
+ public boolean hasClipboardText()
+ {
+ return hasClipboardMimeType("text/(.*)");
+ }
+
+ public String getClipboardText()
+ {
+ try {
+ if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
+ ClipData primaryClip = m_clipboardManager.getPrimaryClip();
+ if (primaryClip != null) {
+ for (int i = 0; i < primaryClip.getItemCount(); ++i)
+ if (primaryClip.getItemAt(i).getText() != null)
+ return primaryClip.getItemAt(i).getText().toString();
+ }
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to get clipboard data", e);
+ }
+ return "";
+ }
+
+ private void updatePrimaryClip(ClipData clipData, Context context)
+ {
+ try {
+ if (m_usePrimaryClip) {
+ ClipData clip = m_clipboardManager.getPrimaryClip();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ Objects.requireNonNull(clip).addItem(context.getContentResolver(),
+ clipData.getItemAt(0));
+ } else {
+ Objects.requireNonNull(clip).addItem(clipData.getItemAt(0));
+ }
+ m_clipboardManager.setPrimaryClip(clip);
+ } else {
+ m_clipboardManager.setPrimaryClip(clipData);
+ m_usePrimaryClip = true;
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to set clipboard data", e);
+ }
+ }
+
+ public void setClipboardHtml(Context context, String text, String html)
+ {
+ if (m_clipboardManager != null) {
+ ClipData clipData = ClipData.newHtmlText("text/html", text, html);
+ updatePrimaryClip(clipData, context);
+ }
+ }
+
+ private boolean hasClipboardMimeType(String mimeType)
+ {
+ if (m_clipboardManager == null)
+ return false;
+
+ ClipDescription description = m_clipboardManager.getPrimaryClipDescription();
+ // getPrimaryClipDescription can fail if the app does not have input focus
+ if (description == null)
+ return false;
+
+ for (int i = 0; i < description.getMimeTypeCount(); ++i) {
+ String itemMimeType = description.getMimeType(i);
+ if (itemMimeType.matches(mimeType))
+ return true;
+ }
+ return false;
+ }
+
+ public boolean hasClipboardHtml()
+ {
+ return hasClipboardMimeType("text/html");
+ }
+
+ public String getClipboardHtml()
+ {
+ try {
+ if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
+ ClipData primaryClip = m_clipboardManager.getPrimaryClip();
+ if (primaryClip != null) {
+ for (int i = 0; i < primaryClip.getItemCount(); ++i)
+ if (primaryClip.getItemAt(i).getHtmlText() != null)
+ return primaryClip.getItemAt(i).getHtmlText();
+ }
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to get clipboard data", e);
+ }
+ return "";
+ }
+
+ public void setClipboardUri(Context context, String uriString)
+ {
+ if (m_clipboardManager != null) {
+ ClipData clipData = ClipData.newUri(context.getContentResolver(), "text/uri-list",
+ Uri.parse(uriString));
+ updatePrimaryClip(clipData, context);
+ }
+ }
+
+ public boolean hasClipboardUri()
+ {
+ return hasClipboardMimeType("text/uri-list");
+ }
+
+ private String[] getClipboardUris()
+ {
+ ArrayList<String> uris = new ArrayList<>();
+ try {
+ if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
+ ClipData primaryClip = m_clipboardManager.getPrimaryClip();
+ if (primaryClip != null) {
+ for (int i = 0; i < primaryClip.getItemCount(); ++i)
+ if (primaryClip.getItemAt(i).getUri() != null)
+ uris.add(primaryClip.getItemAt(i).getUri().toString());
+ }
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to get clipboard data", e);
+ }
+ String[] strings = new String[uris.size()];
+ strings = uris.toArray(strings);
+ return strings;
+ }
+}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java
index 98b75d08b4..ebdfd5339c 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java
@@ -537,7 +537,7 @@ public class QtInputDelegate {
break;
}
- if (!QtNative.hasClipboardText())
+ if (!QtClipboardManager.hasClipboardText(activity))
editButtons &= ~EditContextView.PASTE_BUTTON;
if ((mode & CursorHandleShowEdit) == CursorHandleShowEdit && editButtons != 0) {
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtNative.java b/src/android/jar/src/org/qtproject/qt/android/QtNative.java
index f5df382b00..5f0bd1cd59 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtNative.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtNative.java
@@ -26,9 +26,6 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.system.Os;
-import android.content.ClipboardManager;
-import android.content.ClipData;
-import android.content.ClipDescription;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.view.ContextMenu;
@@ -79,9 +76,7 @@ public class QtNative
private static double m_displayMetricsScaledDensity = 1.0;
private static double m_displayMetricsDensity = 1.0;
private static final int m_moveThreshold = 0;
- private static ClipboardManager m_clipboardManager = null;
private static Method m_checkSelfPermissionMethod = null;
- private static boolean m_usePrimaryClip = false;
public static QtThread m_qtThread = new QtThread();
@@ -525,171 +520,7 @@ public class QtNative
m_activityDelegate.notifyQtAndroidPluginRunning(running);
}
- private static void registerClipboardManager()
- {
- if (m_service == null || m_activity != null) { // Avoid freezing if only service
- final Semaphore semaphore = new Semaphore(0);
- runAction(new Runnable() {
- @Override
- public void run() {
- if (m_activity != null)
- m_clipboardManager = (android.content.ClipboardManager) m_activity.getSystemService(Context.CLIPBOARD_SERVICE);
- if (m_clipboardManager != null) {
- m_clipboardManager.addPrimaryClipChangedListener(new ClipboardManager.OnPrimaryClipChangedListener() {
- public void onPrimaryClipChanged() {
- onClipboardDataChanged();
- }
- });
- }
- semaphore.release();
- }
- });
- try {
- semaphore.acquire();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
-
- private static void clearClipData()
- {
- if (m_clipboardManager != null) {
- if (Build.VERSION.SDK_INT >= 28) {
- m_clipboardManager.clearPrimaryClip();
- } else {
- String[] mimeTypes = { ClipDescription.MIMETYPE_UNKNOWN };
- ClipData data = new ClipData("", mimeTypes, new ClipData.Item(new Intent()));
- m_clipboardManager.setPrimaryClip(data);
- }
- }
- m_usePrimaryClip = false;
- }
- private static void setClipboardText(String text)
- {
- if (m_clipboardManager != null) {
- ClipData clipData = ClipData.newPlainText("text/plain", text);
- updatePrimaryClip(clipData);
- }
- }
-
- public static boolean hasClipboardText()
- {
- return hasClipboardMimeType("text/(.*)");
- }
-
- private static String getClipboardText()
- {
- try {
- if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
- ClipData primaryClip = m_clipboardManager.getPrimaryClip();
- for (int i = 0; i < primaryClip.getItemCount(); ++i)
- if (primaryClip.getItemAt(i).getText() != null)
- return primaryClip.getItemAt(i).getText().toString();
- }
- } catch (Exception e) {
- Log.e(QtTAG, "Failed to get clipboard data", e);
- }
- return "";
- }
-
- private static void updatePrimaryClip(ClipData clipData)
- {
- try {
- if (m_usePrimaryClip) {
- ClipData clip = m_clipboardManager.getPrimaryClip();
- if (Build.VERSION.SDK_INT >= 26) {
- Objects.requireNonNull(clip).addItem(m_activity.getContentResolver(), clipData.getItemAt(0));
- } else {
- Objects.requireNonNull(clip).addItem(clipData.getItemAt(0));
- }
- m_clipboardManager.setPrimaryClip(clip);
- } else {
- m_clipboardManager.setPrimaryClip(clipData);
- m_usePrimaryClip = true;
- }
- } catch (Exception e) {
- Log.e(QtTAG, "Failed to set clipboard data", e);
- }
- }
-
- private static void setClipboardHtml(String text, String html)
- {
- if (m_clipboardManager != null) {
- ClipData clipData = ClipData.newHtmlText("text/html", text, html);
- updatePrimaryClip(clipData);
- }
- }
- private static boolean hasClipboardMimeType(String mimeType)
- {
- if (m_clipboardManager == null)
- return false;
-
- ClipDescription description = m_clipboardManager.getPrimaryClipDescription();
- // getPrimaryClipDescription can fail if the app does not have input focus
- if (description == null)
- return false;
-
- for (int i = 0; i < description.getMimeTypeCount(); ++i) {
- String itemMimeType = description.getMimeType(i);
- if (itemMimeType.matches(mimeType))
- return true;
- }
- return false;
- }
-
- public static boolean hasClipboardHtml()
- {
- return hasClipboardMimeType("text/html");
- }
-
- private static String getClipboardHtml()
- {
- try {
- if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
- ClipData primaryClip = m_clipboardManager.getPrimaryClip();
- for (int i = 0; i < primaryClip.getItemCount(); ++i)
- if (primaryClip.getItemAt(i).getHtmlText() != null)
- return primaryClip.getItemAt(i).getHtmlText().toString();
- }
- } catch (Exception e) {
- Log.e(QtTAG, "Failed to get clipboard data", e);
- }
- return "";
- }
-
- private static void setClipboardUri(String uriString)
- {
- if (m_clipboardManager != null) {
- ClipData clipData = ClipData.newUri(m_activity.getContentResolver(), "text/uri-list",
- Uri.parse(uriString));
- updatePrimaryClip(clipData);
- }
- }
-
- public static boolean hasClipboardUri()
- {
- return hasClipboardMimeType("text/uri-list");
- }
-
- private static String[] getClipboardUris()
- {
- ArrayList<String> uris = new ArrayList<String>();
- try {
- if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
- ClipData primaryClip = m_clipboardManager.getPrimaryClip();
- for (int i = 0; i < primaryClip.getItemCount(); ++i)
- if (primaryClip.getItemAt(i).getUri() != null)
- uris.add(primaryClip.getItemAt(i).getUri().toString());
- }
- } catch (Exception e) {
- Log.e(QtTAG, "Failed to get clipboard data", e);
- }
- String[] strings = new String[uris.size()];
- strings = uris.toArray(strings);
- return strings;
- }
private static void openContextMenu(final int x, final int y, final int w, final int h)
{
@@ -909,10 +740,6 @@ public class QtNative
public static native void onContextMenuClosed(Menu menu);
// menu methods
- // clipboard methods
- public static native void onClipboardDataChanged();
- // clipboard methods
-
// activity methods
public static native void onActivityResult(int requestCode, int resultCode, Intent data);
public static native void onNewIntent(Intent data);
diff --git a/src/plugins/platforms/android/CMakeLists.txt b/src/plugins/platforms/android/CMakeLists.txt
index 0b24e52d9a..40def7ba77 100644
--- a/src/plugins/platforms/android/CMakeLists.txt
+++ b/src/plugins/platforms/android/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (C) 2022 The Qt Company Ltd.
+# Copyright (C) 2023 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
@@ -14,7 +14,6 @@ qt_internal_add_plugin(QAndroidIntegrationPlugin
androidcontentfileengine.cpp androidcontentfileengine.h
androiddeadlockprotector.h
androidjniaccessibility.cpp androidjniaccessibility.h
- androidjniclipboard.cpp androidjniclipboard.h
androidjniinput.cpp androidjniinput.h
androidjnimain.cpp androidjnimain.h
androidjnimenu.cpp androidjnimenu.h
diff --git a/src/plugins/platforms/android/androidjniclipboard.cpp b/src/plugins/platforms/android/androidjniclipboard.cpp
deleted file mode 100644
index d510f43049..0000000000
--- a/src/plugins/platforms/android/androidjniclipboard.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-
-#include "androidjniclipboard.h"
-#include <QtCore/QUrl>
-#include <QtCore/QJniObject>
-#include <QtCore/QJniEnvironment>
-
-QT_BEGIN_NAMESPACE
-
-using namespace QtAndroid;
-namespace QtAndroidClipboard
-{
- QAndroidPlatformClipboard *m_manager = nullptr;
-
- static JNINativeMethod methods[] = {
- {"onClipboardDataChanged", "()V", (void *)onClipboardDataChanged}
- };
-
- void setClipboardManager(QAndroidPlatformClipboard *manager)
- {
- m_manager = manager;
- QJniObject::callStaticMethod<void>(applicationClass(), "registerClipboardManager");
- jclass appClass = QtAndroid::applicationClass();
- QJniEnvironment env;
- if (env->RegisterNatives(appClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) {
- __android_log_print(ANDROID_LOG_FATAL,"Qt", "RegisterNatives failed");
- return;
- }
- }
- void clearClipboardData()
- {
- QJniObject::callStaticMethod<void>(applicationClass(), "clearClipData");
- }
- void setClipboardMimeData(QMimeData *data)
- {
- clearClipboardData();
- if (data->hasUrls()) {
- QList<QUrl> urls = data->urls();
- for (const auto &u : std::as_const(urls)) {
- QJniObject::callStaticMethod<void>(applicationClass(),
- "setClipboardUri",
- "(Ljava/lang/String;)V",
- QJniObject::fromString(u.toEncoded()).object());
- }
- } else if (data->hasHtml()) { // html can contain text
- QJniObject::callStaticMethod<void>(applicationClass(),
- "setClipboardHtml",
- "(Ljava/lang/String;Ljava/lang/String;)V",
- QJniObject::fromString(data->text()).object(),
- QJniObject::fromString(data->html()).object());
- } else if (data->hasText()) { // hasText must be the last (the order matter here)
- QJniObject::callStaticMethod<void>(applicationClass(),
- "setClipboardText", "(Ljava/lang/String;)V",
- QJniObject::fromString(data->text()).object());
- }
- }
-
- QMimeData *getClipboardMimeData()
- {
- QMimeData *data = new QMimeData;
- if (QJniObject::callStaticMethod<jboolean>(applicationClass(), "hasClipboardText")) {
- data->setText(QJniObject::callStaticObjectMethod(applicationClass(),
- "getClipboardText",
- "()Ljava/lang/String;").toString());
- }
- if (QJniObject::callStaticMethod<jboolean>(applicationClass(), "hasClipboardHtml")) {
- data->setHtml(QJniObject::callStaticObjectMethod(applicationClass(),
- "getClipboardHtml",
- "()Ljava/lang/String;").toString());
- }
- if (QJniObject::callStaticMethod<jboolean>(applicationClass(), "hasClipboardUri")) {
- QJniObject uris = QJniObject::callStaticObjectMethod(applicationClass(),
- "getClipboardUris",
- "()[Ljava/lang/String;");
- if (uris.isValid()) {
- QList<QUrl> urls;
- QJniEnvironment env;
- jobjectArray juris = uris.object<jobjectArray>();
- const jint nUris = env->GetArrayLength(juris);
- urls.reserve(static_cast<int>(nUris));
- for (int i = 0; i < nUris; ++i)
- urls << QUrl(QJniObject(env->GetObjectArrayElement(juris, i)).toString());
- data->setUrls(urls);
- }
- }
- return data;
- }
-
- void onClipboardDataChanged(JNIEnv */*env*/, jobject /*thiz*/)
- {
- m_manager->emitChanged(QClipboard::Clipboard);
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/androidjniclipboard.h b/src/plugins/platforms/android/androidjniclipboard.h
deleted file mode 100644
index 24feeef9b3..0000000000
--- a/src/plugins/platforms/android/androidjniclipboard.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-
-#ifndef ANDROIDJNICLIPBOARD_H
-#define ANDROIDJNICLIPBOARD_H
-
-#include <QString>
-#include "qandroidplatformclipboard.h"
-#include "androidjnimain.h"
-
-QT_BEGIN_NAMESPACE
-
-class QAndroidPlatformClipboard;
-namespace QtAndroidClipboard
-{
- // Clipboard support
- void setClipboardManager(QAndroidPlatformClipboard *manager);
- void setClipboardMimeData(QMimeData *data);
- QMimeData *getClipboardMimeData();
- void clearClipboardData();
- void onClipboardDataChanged(JNIEnv */*env*/, jobject /*thiz*/);
- // Clipboard support
-}
-
-QT_END_NAMESPACE
-
-#endif // ANDROIDJNICLIPBOARD_H
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index 6b906bfe8c..ebed64d48d 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -10,7 +10,6 @@
#include "androidcontentfileengine.h"
#include "androiddeadlockprotector.h"
#include "androidjniaccessibility.h"
-#include "androidjniclipboard.h"
#include "androidjniinput.h"
#include "androidjnimain.h"
#include "androidjnimenu.h"
@@ -18,6 +17,7 @@
#include "qandroideventdispatcher.h"
#include "qandroidplatformdialoghelpers.h"
#include "qandroidplatformintegration.h"
+#include "qandroidplatformclipboard.h"
#include <android/api-level.h>
#include <android/asset_manager_jni.h>
@@ -927,7 +927,8 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/)
|| !QtAndroidInput::registerNatives()
|| !QtAndroidMenu::registerNatives(env)
|| !QtAndroidAccessibility::registerNatives(env)
- || !QtAndroidDialogHelpers::registerNatives(env)) {
+ || !QtAndroidDialogHelpers::registerNatives(env)
+ || !QAndroidPlatformClipboard::registerNatives()) {
__android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed");
return -1;
}
diff --git a/src/plugins/platforms/android/qandroidplatformclipboard.cpp b/src/plugins/platforms/android/qandroidplatformclipboard.cpp
index 39a508a1b3..bc199e32fb 100644
--- a/src/plugins/platforms/android/qandroidplatformclipboard.cpp
+++ b/src/plugins/platforms/android/qandroidplatformclipboard.cpp
@@ -1,15 +1,34 @@
+// Copyright (C) 2023 The Qt Company Ltd.
// Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qandroidplatformclipboard.h"
-#include "androidjniclipboard.h"
+
+#include <QtCore/QUrl>
+#include <QtCore/QJniEnvironment>
+#include <QtCore/QJniObject>
+#include <QtCore/private/qjnihelpers_p.h>
+
#ifndef QT_NO_CLIPBOARD
+using namespace QtJniTypes;
+
QT_BEGIN_NAMESPACE
+void QAndroidPlatformClipboard::onClipboardDataChanged(JNIEnv *env, jobject obj, jlong nativePointer)
+{
+ Q_UNUSED(env)
+ Q_UNUSED(obj)
+
+ auto *clipboardManager = reinterpret_cast<QAndroidPlatformClipboard *>(nativePointer);
+ if (clipboardManager)
+ clipboardManager->emitChanged(QClipboard::Clipboard);
+}
+
QAndroidPlatformClipboard::QAndroidPlatformClipboard()
{
- QtAndroidClipboard::setClipboardManager(this);
+ m_clipboardManager = QtClipboardManager::construct(QtAndroidPrivate::context(),
+ reinterpret_cast<long>(this));
}
QAndroidPlatformClipboard::~QAndroidPlatformClipboard()
@@ -18,24 +37,66 @@ QAndroidPlatformClipboard::~QAndroidPlatformClipboard()
delete data;
}
+QMimeData *QAndroidPlatformClipboard::getClipboardMimeData()
+{
+ QMimeData *data = new QMimeData;
+ if (m_clipboardManager.callMethod<jboolean>("hasClipboardText")) {
+ data->setText(m_clipboardManager.callMethod<QString>("getClipboardText"));
+ }
+ if (m_clipboardManager.callMethod<jboolean>("hasClipboardHtml")) {
+ data->setHtml(m_clipboardManager.callMethod<QString>("getClipboardHtml"));
+ }
+ if (m_clipboardManager.callMethod<jboolean>("hasClipboardUri")) {
+ auto uris = m_clipboardManager.callMethod<QString[]>("getClipboardUris");
+ if (uris.isValid()) {
+ QList<QUrl> urls;
+ for (const QString &uri : uris)
+ urls << QUrl(uri);
+ data->setUrls(urls);
+ }
+ }
+ return data;
+}
+
QMimeData *QAndroidPlatformClipboard::mimeData(QClipboard::Mode mode)
{
Q_UNUSED(mode);
Q_ASSERT(supportsMode(mode));
if (data)
data->deleteLater();
- data = QtAndroidClipboard::getClipboardMimeData();
+ data = getClipboardMimeData();
return data;
}
+void QAndroidPlatformClipboard::clearClipboardData()
+{
+ m_clipboardManager.callMethod<void>("clearClipData");
+}
+
+void QAndroidPlatformClipboard::setClipboardMimeData(QMimeData *data)
+{
+ clearClipboardData();
+ auto context = QtAndroidPrivate::context();
+ if (data->hasUrls()) {
+ QList<QUrl> urls = data->urls();
+ for (const auto &u : std::as_const(urls))
+ m_clipboardManager.callMethod<void>("setClipboardUri", context, u.toEncoded());
+ } else if (data->hasHtml()) { // html can contain text
+ m_clipboardManager.callMethod<void>("setClipboardHtml",
+ context, data->text(), data->html());
+ } else if (data->hasText()) { // hasText must be the last (the order matter here)
+ m_clipboardManager.callMethod<void>("setClipboardText", context, data->text());
+ }
+}
+
void QAndroidPlatformClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
{
if (!data) {
- QtAndroidClipboard::clearClipboardData();
+ clearClipboardData();
return;
}
if (data && supportsMode(mode))
- QtAndroidClipboard::setClipboardMimeData(data);
+ setClipboardMimeData(data);
if (data != 0)
data->deleteLater();
}
@@ -45,6 +106,19 @@ bool QAndroidPlatformClipboard::supportsMode(QClipboard::Mode mode) const
return QClipboard::Clipboard == mode;
}
+bool QAndroidPlatformClipboard::registerNatives()
+{
+ QJniEnvironment env;
+ bool success = env.registerNativeMethods(Traits<QtClipboardManager>::className(),
+ { Q_JNI_NATIVE_SCOPED_METHOD(onClipboardDataChanged, QAndroidPlatformClipboard) });
+ if (!success) {
+ qCritical() << "QtClipboardManager: registerNativeMethods() failed";
+ return false;
+ }
+
+ return true;
+}
+
QT_END_NAMESPACE
#endif // QT_NO_CLIPBOARD
diff --git a/src/plugins/platforms/android/qandroidplatformclipboard.h b/src/plugins/platforms/android/qandroidplatformclipboard.h
index 1778ca5b28..e3467b83ee 100644
--- a/src/plugins/platforms/android/qandroidplatformclipboard.h
+++ b/src/plugins/platforms/android/qandroidplatformclipboard.h
@@ -1,3 +1,4 @@
+// Copyright (C) 2023 The Qt Company Ltd.
// Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
@@ -6,8 +7,12 @@
#include <qpa/qplatformclipboard.h>
#include <QMimeData>
+#include <QtCore/qjnitypes.h>
#ifndef QT_NO_CLIPBOARD
+
+Q_DECLARE_JNI_CLASS(QtClipboardManager, "org/qtproject/qt/android/QtClipboardManager");
+
QT_BEGIN_NAMESPACE
class QAndroidPlatformClipboard : public QPlatformClipboard
@@ -18,8 +23,19 @@ public:
QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) override;
void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard) override;
bool supportsMode(QClipboard::Mode mode) const override;
+
+ static bool registerNatives();
+
private:
+ QMimeData *getClipboardMimeData();
+ void setClipboardMimeData(QMimeData *data);
+ void clearClipboardData();
+
+ static void onClipboardDataChanged(JNIEnv *env, jobject obj, jlong nativePointer);
+ Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(onClipboardDataChanged)
+
QMimeData *data = nullptr;
+ QtJniTypes::QtClipboardManager m_clipboardManager;
};
QT_END_NAMESPACE