summaryrefslogtreecommitdiffstats
path: root/src/android/jar/src/org/qtproject/qt/android
diff options
context:
space:
mode:
Diffstat (limited to 'src/android/jar/src/org/qtproject/qt/android')
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/BackendRegister.java9
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java2
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtAccessibilityInterface.java14
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java42
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java150
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java105
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtEditText.java4
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java63
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegateFactory.java37
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtEmbeddedLoader.java2
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtEmbeddedViewInterfaceFactory.java34
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java9
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java261
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtInputInterface.java21
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtLayoutInterface.java8
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtMenuInterface.java11
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtNative.java97
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtRootLayout.java39
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtServiceEmbeddedDelegate.java10
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtSurface.java2
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtSurfaceInterface.java3
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtTextureView.java5
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtView.java52
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtWindow.java25
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtWindowInterface.java11
25 files changed, 535 insertions, 481 deletions
diff --git a/src/android/jar/src/org/qtproject/qt/android/BackendRegister.java b/src/android/jar/src/org/qtproject/qt/android/BackendRegister.java
new file mode 100644
index 0000000000..b66a593ec6
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt/android/BackendRegister.java
@@ -0,0 +1,9 @@
+// Copyright (C) 2024 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;
+
+class BackendRegister
+{
+ static native void registerBackend(Class interfaceType, Object interfaceObject);
+ static native void unregisterBackend(Class interfaceType);
+}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java
index d23c87e792..8558e42c3b 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java
@@ -61,6 +61,8 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
}
// TODO do we want to have one QtAccessibilityDelegate for the whole app (QtRootLayout) or
// e.g. one per window?
+ // FIXME make QtAccessibilityDelegate window based or verify current way works
+ // also for child windows: QTBUG-120685
public QtAccessibilityDelegate(QtLayout layout)
{
m_layout = layout;
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityInterface.java b/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityInterface.java
new file mode 100644
index 0000000000..690b1ae248
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityInterface.java
@@ -0,0 +1,14 @@
+// Copyright (C) 2024 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;
+
+@UsedFromNativeCode
+interface QtAccessibilityInterface {
+ default void initializeAccessibility() { }
+ default void notifyLocationChange(int viewId) { }
+ default void notifyObjectHide(int viewId, int parentId) { }
+ default void notifyObjectFocus(int viewId) { }
+ default void notifyScrolledEvent(int viewId) { }
+ default void notifyValueChanged(int viewId, String value) { }
+ default void notifyObjectShow(int parentId) { }
+}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java
index 3cb6ba220e..dccaf45a05 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java
@@ -19,7 +19,7 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
-public class QtActivityBase extends Activity
+public class QtActivityBase extends Activity implements QtNative.AppStateDetailsListener
{
private String m_applicationParams = "";
private boolean m_isCustomThemeSet = false;
@@ -63,25 +63,19 @@ public class QtActivityBase extends Activity
m_applicationParams += params;
}
- private void handleActivityRestart() {
- if (QtNative.getStateDetails().isStarted) {
- boolean updated = m_delegate.updateActivityAfterRestart(this);
- if (!updated) {
- // could not update the activity so restart the application
- Intent intent = Intent.makeRestartActivityTask(getComponentName());
- startActivity(intent);
- QtNative.quitApp();
- Runtime.getRuntime().exit(0);
- }
- }
- }
-
@Override
public void setTheme(int resId) {
super.setTheme(resId);
m_isCustomThemeSet = true;
}
+ private void restartApplication() {
+ Intent intent = Intent.makeRestartActivityTask(getComponentName());
+ startActivity(intent);
+ QtNative.quitApp();
+ Runtime.getRuntime().exit(0);
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState)
{
@@ -94,9 +88,17 @@ public class QtActivityBase extends Activity
android.R.style.Theme_Holo_Light);
}
+ if (QtNative.getStateDetails().isStarted) {
+ // We don't yet have a reliable way to keep the app
+ // running properly in case of an Activity only restart,
+ // so for now restart the whole app.
+ restartApplication();
+ }
+
m_delegate = new QtActivityDelegate(this);
- handleActivityRestart();
+ QtNative.registerAppStateListener(this);
+
addReferrer(getIntent());
QtActivityLoader loader = new QtActivityLoader(this);
@@ -108,6 +110,14 @@ public class QtActivityBase extends Activity
}
@Override
+ public void onAppStateDetailsChanged(QtNative.ApplicationStateDetails details) {
+ if (details.isStarted)
+ m_delegate.registerBackends();
+ else
+ m_delegate.unregisterBackends();
+ }
+
+ @Override
protected void onStart()
{
super.onStart();
@@ -153,6 +163,7 @@ public class QtActivityBase extends Activity
{
super.onDestroy();
if (!m_retainNonConfigurationInstance) {
+ QtNative.unregisterAppStateListener(this);
QtNative.terminateQt();
QtNative.setActivity(null);
QtNative.getQtThread().exit();
@@ -295,6 +306,7 @@ public class QtActivityBase extends Activity
@Override
protected void onNewIntent(Intent intent)
{
+ addReferrer(intent);
QtNative.onNewIntent(intent);
}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java
index 1e1a36be3c..d78c059094 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java
@@ -9,7 +9,6 @@ import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
-import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.Rect;
@@ -26,24 +25,24 @@ import android.view.Menu;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowInsetsController;
import android.widget.ImageView;
import android.widget.PopupMenu;
import java.util.HashMap;
class QtActivityDelegate extends QtActivityDelegateBase
+ implements QtWindowInterface, QtAccessibilityInterface, QtMenuInterface, QtLayoutInterface
{
private static final String QtTAG = "QtActivityDelegate";
private QtRootLayout m_layout = null;
private ImageView m_splashScreen = null;
private boolean m_splashScreenSticky = false;
+ private boolean m_backendsRegistered = false;
private View m_dummyView = null;
- private HashMap<Integer, View> m_nativeViews = new HashMap<Integer, View>();
-
+ private final HashMap<Integer, View> m_nativeViews = new HashMap<>();
+ private QtAccessibilityDelegate m_accessibilityDelegate = null;
QtActivityDelegate(Activity activity)
{
@@ -53,17 +52,43 @@ class QtActivityDelegate extends QtActivityDelegateBase
setActivityBackgroundDrawable();
}
+ void registerBackends()
+ {
+ if (!m_backendsRegistered) {
+ m_backendsRegistered = true;
+ BackendRegister.registerBackend(QtWindowInterface.class,
+ (QtWindowInterface)QtActivityDelegate.this);
+ BackendRegister.registerBackend(QtAccessibilityInterface.class,
+ (QtAccessibilityInterface)QtActivityDelegate.this);
+ BackendRegister.registerBackend(QtMenuInterface.class,
+ (QtMenuInterface)QtActivityDelegate.this);
+ BackendRegister.registerBackend(QtLayoutInterface.class,
+ (QtLayoutInterface)QtActivityDelegate.this);
+ BackendRegister.registerBackend(QtInputInterface.class,
+ (QtInputInterface)m_inputDelegate);
+ }
+ }
+
+ void unregisterBackends()
+ {
+ if (m_backendsRegistered) {
+ m_backendsRegistered = false;
+ BackendRegister.unregisterBackend(QtWindowInterface.class);
+ BackendRegister.unregisterBackend(QtAccessibilityInterface.class);
+ BackendRegister.unregisterBackend(QtMenuInterface.class);
+ BackendRegister.unregisterBackend(QtLayoutInterface.class);
+ BackendRegister.unregisterBackend(QtInputInterface.class);
+ }
+ }
- @UsedFromNativeCode
@Override
- QtLayout getQtLayout()
+ public QtLayout getQtLayout()
{
return m_layout;
}
- @UsedFromNativeCode
@Override
- void setSystemUiVisibility(int systemUiVisibility)
+ public void setSystemUiVisibility(int systemUiVisibility)
{
QtNative.runAction(() -> {
m_displayManager.setSystemUiVisibility(systemUiVisibility);
@@ -73,21 +98,6 @@ class QtActivityDelegate extends QtActivityDelegateBase
}
@Override
- public boolean updateActivityAfterRestart(Activity activity) {
- boolean updated = super.updateActivityAfterRestart(activity);
- // TODO verify whether this is even needed, the last I checked the initMembers
- // recreates the layout anyway
- // update the new activity content view to old layout
- ViewGroup layoutParent = (ViewGroup)m_layout.getParent();
- if (layoutParent != null)
- layoutParent.removeView(m_layout);
-
- m_activity.setContentView(m_layout);
-
- return updated;
- }
-
- @Override
void startNativeApplicationImpl(String appParams, String mainLib)
{
m_layout.getViewTreeObserver().addOnGlobalLayoutListener(
@@ -212,7 +222,55 @@ class QtActivityDelegate extends QtActivityDelegateBase
});
}
- @UsedFromNativeCode
+ @Override
+ public void notifyLocationChange(int viewId)
+ {
+ if (m_accessibilityDelegate == null)
+ return;
+ m_accessibilityDelegate.notifyLocationChange(viewId);
+ }
+
+ @Override
+ public void notifyObjectHide(int viewId, int parentId)
+ {
+ if (m_accessibilityDelegate == null)
+ return;
+ m_accessibilityDelegate.notifyObjectHide(viewId, parentId);
+ }
+
+ @Override
+ public void notifyObjectShow(int parentId)
+ {
+ if (m_accessibilityDelegate == null)
+ return;
+ m_accessibilityDelegate.notifyObjectShow(parentId);
+ }
+
+ @Override
+ public void notifyObjectFocus(int viewId)
+ {
+ if (m_accessibilityDelegate == null)
+ return;
+ m_accessibilityDelegate.notifyObjectFocus(viewId);
+ }
+
+ @Override
+ public void notifyValueChanged(int viewId, String value)
+ {
+ if (m_accessibilityDelegate == null)
+ return;
+ m_accessibilityDelegate.notifyValueChanged(viewId, value);
+ }
+
+ @Override
+ public void notifyScrolledEvent(int viewId)
+ {
+ if (m_accessibilityDelegate == null)
+ return;
+ m_accessibilityDelegate.notifyScrolledEvent(viewId);
+ }
+
+ @Override
public void initializeAccessibility()
{
QtNative.runAction(() -> {
@@ -224,27 +282,25 @@ class QtActivityDelegate extends QtActivityDelegateBase
});
}
- @UsedFromNativeCode
+ // QtMenuInterface implementation begin
+ @Override
public void resetOptionsMenu()
{
QtNative.runAction(() -> m_activity.invalidateOptionsMenu());
}
- @UsedFromNativeCode
+ @Override
public void openOptionsMenu()
{
QtNative.runAction(() -> m_activity.openOptionsMenu());
}
- private boolean m_contextMenuVisible = false;
-
- public void onCreatePopupMenu(Menu menu)
+ @Override
+ public void closeContextMenu()
{
- QtNative.fillContextMenu(menu);
- m_contextMenuVisible = true;
+ QtNative.runAction(() -> m_activity.closeContextMenu());
}
- @UsedFromNativeCode
@Override
public void openContextMenu(final int x, final int y, final int w, final int h)
{
@@ -264,11 +320,14 @@ class QtActivityDelegate extends QtActivityDelegateBase
popup.show();
}, 100);
}
+ // QtMenuInterface implementation end
- @UsedFromNativeCode
- public void closeContextMenu()
+ private boolean m_contextMenuVisible = false;
+
+ public void onCreatePopupMenu(Menu menu)
{
- QtNative.runAction(() -> m_activity.closeContextMenu());
+ QtNative.fillContextMenu(menu);
+ m_contextMenuVisible = true;
}
@Override
@@ -310,7 +369,7 @@ class QtActivityDelegate extends QtActivityDelegateBase
@UsedFromNativeCode
@Override
- void removeTopLevelWindow(final int id)
+ public void removeTopLevelWindow(final int id)
{
QtNative.runAction(()-> {
if (m_topLevelWindows.containsKey(id)) {
@@ -328,7 +387,7 @@ class QtActivityDelegate extends QtActivityDelegateBase
@UsedFromNativeCode
@Override
- void bringChildToFront(final int id)
+ public void bringChildToFront(final int id)
{
QtNative.runAction(() -> {
QtWindow window = m_topLevelWindows.get(id);
@@ -339,7 +398,7 @@ class QtActivityDelegate extends QtActivityDelegateBase
@UsedFromNativeCode
@Override
- void bringChildToBack(int id)
+ public void bringChildToBack(int id)
{
QtNative.runAction(() -> {
QtWindow window = m_topLevelWindows.get(id);
@@ -348,16 +407,6 @@ class QtActivityDelegate extends QtActivityDelegateBase
});
}
- @Override
- QtAccessibilityDelegate createAccessibilityDelegate()
- {
- if (m_layout != null)
- return new QtAccessibilityDelegate(m_layout);
-
- Log.w(QtTAG, "Null layout, failed to initialize accessibility delegate.");
- return null;
- }
-
private void setActivityBackgroundDrawable()
{
TypedValue attr = new TypedValue();
@@ -408,7 +457,8 @@ class QtActivityDelegate extends QtActivityDelegateBase
QtNative.runAction(() -> {
if (m_nativeViews.containsKey(id)) {
View view = m_nativeViews.get(id);
- view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
+ if (view != null)
+ view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
} else {
Log.e(QtTAG, "View " + id + " not found!");
}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java
index 6fd539d8dd..84a5961b8a 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java
@@ -37,7 +37,6 @@ abstract class QtActivityDelegateBase
{
protected Activity m_activity;
protected HashMap<Integer, QtWindow> m_topLevelWindows;
- protected QtAccessibilityDelegate m_accessibilityDelegate = null;
protected QtDisplayManager m_displayManager = null;
protected QtInputDelegate m_inputDelegate = null;
@@ -46,20 +45,12 @@ abstract class QtActivityDelegateBase
// Subclass must implement these
abstract void startNativeApplicationImpl(String appParams, String mainLib);
- abstract QtAccessibilityDelegate createAccessibilityDelegate();
- abstract QtLayout getQtLayout();
// With these we are okay with default implementation doing nothing
void setUpLayout() {}
void setUpSplashScreen(int orientation) {}
void hideSplashScreen(final int duration) {}
- void openContextMenu(final int x, final int y, final int w, final int h) {}
void setActionBarVisibility(boolean visible) {}
- void addTopLevelWindow(final QtWindow window) {}
- void removeTopLevelWindow(final int id) {}
- void bringChildToFront(final int id) {}
- void bringChildToBack(int id) {}
- void setSystemUiVisibility(int systemUiVisibility) {}
QtActivityDelegateBase(Activity activity)
{
@@ -72,7 +63,6 @@ abstract class QtActivityDelegateBase
return m_displayManager;
}
- @UsedFromNativeCode
QtInputDelegate getInputDelegate() {
return m_inputDelegate;
}
@@ -87,21 +77,6 @@ abstract class QtActivityDelegateBase
return m_contextMenuVisible;
}
- public boolean updateActivityAfterRestart(Activity activity) {
- try {
- // set new activity
- m_activity = activity;
- QtNative.setActivity(m_activity);
-
- // force c++ native activity object to update
- return QtNative.updateNativeActivity();
- } catch (Exception e) {
- Log.w(QtNative.QtTAG, "Failed to update the activity.");
- e.printStackTrace();
- return false;
- }
- }
-
public void startNativeApplication(String appParams, String mainLib)
{
if (m_membersInitialized)
@@ -158,62 +133,6 @@ abstract class QtActivityDelegateBase
hideSplashScreen(0);
}
- @UsedFromNativeCode
- public void notifyLocationChange(int viewId)
- {
- if (m_accessibilityDelegate == null)
- return;
- m_accessibilityDelegate.notifyLocationChange(viewId);
- }
-
- @UsedFromNativeCode
- public void notifyObjectHide(int viewId, int parentId)
- {
- if (m_accessibilityDelegate == null)
- return;
- m_accessibilityDelegate.notifyObjectHide(viewId, parentId);
- }
-
- @UsedFromNativeCode
- public void notifyObjectShow(int parentId)
- {
- if (m_accessibilityDelegate == null)
- return;
- m_accessibilityDelegate.notifyObjectShow(parentId);
- }
-
- @UsedFromNativeCode
- public void notifyObjectFocus(int viewId)
- {
- if (m_accessibilityDelegate == null)
- return;
- m_accessibilityDelegate.notifyObjectFocus(viewId);
- }
-
- @UsedFromNativeCode
- public void notifyValueChanged(int viewId, String value)
- {
- if (m_accessibilityDelegate == null)
- return;
- m_accessibilityDelegate.notifyValueChanged(viewId, value);
- }
-
- @UsedFromNativeCode
- public void notifyScrolledEvent(int viewId)
- {
- if (m_accessibilityDelegate == null)
- return;
- m_accessibilityDelegate.notifyScrolledEvent(viewId);
- }
-
- @UsedFromNativeCode
- public void initializeAccessibility()
- {
- QtNative.runAction(() -> {
- m_accessibilityDelegate = createAccessibilityDelegate();
- });
- }
-
void handleUiModeChange(int uiMode)
{
// QTBUG-108365
@@ -240,28 +159,4 @@ abstract class QtActivityDelegateBase
break;
}
}
-
- @UsedFromNativeCode
- public void resetOptionsMenu()
- {
- QtNative.runAction(() -> m_activity.invalidateOptionsMenu());
- }
-
- @UsedFromNativeCode
- public void openOptionsMenu()
- {
- QtNative.runAction(() -> m_activity.openOptionsMenu());
- }
-
- public void onCreatePopupMenu(Menu menu)
- {
- QtNative.fillContextMenu(menu);
- m_contextMenuVisible = true;
- }
-
- @UsedFromNativeCode
- public void closeContextMenu()
- {
- QtNative.runAction(() -> m_activity.closeContextMenu());
- }
}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtEditText.java b/src/android/jar/src/org/qtproject/qt/android/QtEditText.java
index 4524887242..71b44a81e5 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtEditText.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtEditText.java
@@ -61,7 +61,7 @@ class QtEditText extends View
{
if (m_imeOptions == imeOptions)
return;
- m_imeOptions = m_imeOptions;
+ m_imeOptions = imeOptions;
m_optionsChanged = true;
}
@@ -78,7 +78,7 @@ class QtEditText extends View
{
if (m_inputType == inputType)
return;
- m_inputType = m_inputType;
+ m_inputType = inputType;
m_optionsChanged = true;
}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java
index ff694777d5..5298ac02bd 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java
@@ -15,19 +15,24 @@ import android.os.Handler;
import android.os.Looper;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.PopupMenu;
import java.util.ArrayList;
import java.util.HashMap;
class QtEmbeddedDelegate extends QtActivityDelegateBase
- implements QtNative.AppStateDetailsListener, QtEmbeddedViewInterface
+ implements QtNative.AppStateDetailsListener, QtEmbeddedViewInterface, QtWindowInterface,
+ QtMenuInterface, QtLayoutInterface
{
+ private static final String QtTAG = "QtEmbeddedDelegate";
// TODO simplistic implementation with one QtView, expand to support multiple views QTBUG-117649
private QtView m_view;
private QtNative.ApplicationStateDetails m_stateDetails;
private boolean m_windowLoaded = false;
+ private boolean m_backendsRegistered = false;
public QtEmbeddedDelegate(Activity context) {
super(context);
@@ -76,7 +81,7 @@ class QtEmbeddedDelegate extends QtActivityDelegateBase
if (m_activity == activity && m_stateDetails.isStarted) {
m_activity.getApplication().unregisterActivityLifecycleCallbacks(this);
QtNative.unregisterAppStateListener(QtEmbeddedDelegate.this);
- QtEmbeddedDelegateFactory.remove(m_activity);
+ QtEmbeddedViewInterfaceFactory.remove(m_activity);
QtNative.terminateQt();
QtNative.setActivity(null);
QtNative.getQtThread().exit();
@@ -89,6 +94,17 @@ class QtEmbeddedDelegate extends QtActivityDelegateBase
public void onAppStateDetailsChanged(QtNative.ApplicationStateDetails details) {
synchronized (this) {
m_stateDetails = details;
+ if (details.isStarted && !m_backendsRegistered) {
+ m_backendsRegistered = true;
+ BackendRegister.registerBackend(QtWindowInterface.class, (QtWindowInterface)this);
+ BackendRegister.registerBackend(QtMenuInterface.class, (QtMenuInterface)this);
+ BackendRegister.registerBackend(QtLayoutInterface.class, (QtLayoutInterface)this);
+ } else if (!details.isStarted && m_backendsRegistered) {
+ m_backendsRegistered = false;
+ BackendRegister.unregisterBackend(QtWindowInterface.class);
+ BackendRegister.unregisterBackend(QtMenuInterface.class);
+ BackendRegister.unregisterBackend(QtLayoutInterface.class);
+ }
}
}
@@ -115,16 +131,7 @@ class QtEmbeddedDelegate extends QtActivityDelegateBase
}
@Override
- QtAccessibilityDelegate createAccessibilityDelegate()
- {
- // FIXME make QtAccessibilityDelegate window based or verify current way works
- // also for child windows: QTBUG-120685
- return null;
- }
-
- @UsedFromNativeCode
- @Override
- QtLayout getQtLayout()
+ public QtLayout getQtLayout()
{
// TODO verify if returning m_view here works, this is used by the androidjniinput
// when e.g. showing a keyboard, so depends on getting the keyboard focus working
@@ -175,4 +182,36 @@ class QtEmbeddedDelegate extends QtActivityDelegateBase
m_windowLoaded = true;
}
}
+
+ // QtMenuInterface implementation begin
+ @Override
+ public void resetOptionsMenu() { QtNative.runAction(() -> m_activity.invalidateOptionsMenu()); }
+
+ @Override
+ public void openOptionsMenu() { QtNative.runAction(() -> m_activity.openOptionsMenu()); }
+
+ @Override
+ public void closeContextMenu() { QtNative.runAction(() -> m_activity.closeContextMenu()); }
+
+ @Override
+ public void openContextMenu(final int x, final int y, final int w, final int h)
+ {
+ QtLayout layout = getQtLayout();
+ layout.postDelayed(() -> {
+ final QtEditText focusedEditText = m_inputDelegate.getCurrentQtEditText();
+ if (focusedEditText == null) {
+ Log.w(QtTAG, "No focused view when trying to open context menu");
+ return;
+ }
+ layout.setLayoutParams(focusedEditText, new QtLayout.LayoutParams(w, h, x, y), false);
+ PopupMenu popup = new PopupMenu(m_activity, focusedEditText);
+ QtNative.fillContextMenu(popup.getMenu());
+ popup.setOnMenuItemClickListener(menuItem ->
+ m_activity.onContextItemSelected(menuItem));
+ popup.setOnDismissListener(popupMenu ->
+ m_activity.onContextMenuClosed(popupMenu.getMenu()));
+ popup.show();
+ }, 100);
+ }
+ // QtMenuInterface implementation end
}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegateFactory.java b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegateFactory.java
deleted file mode 100644
index 8cf89e5bc3..0000000000
--- a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegateFactory.java
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (C) 2024 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.app.Activity;
-import android.app.Application;
-import android.os.Bundle;
-
-import java.util.HashMap;
-
-class QtEmbeddedDelegateFactory {
- private static final HashMap<Activity, QtEmbeddedDelegate> m_delegates = new HashMap<>();
- private static final Object m_delegateLock = new Object();
-
- @UsedFromNativeCode
- public static QtActivityDelegateBase getActivityDelegate(Activity activity) {
- synchronized (m_delegateLock) {
- return m_delegates.get(activity);
- }
- }
-
- public static QtEmbeddedDelegate create(Activity activity) {
- synchronized (m_delegateLock) {
- if (!m_delegates.containsKey(activity))
- m_delegates.put(activity, new QtEmbeddedDelegate(activity));
-
- return m_delegates.get(activity);
- }
- }
-
- public static void remove(Activity activity) {
- synchronized (m_delegateLock) {
- m_delegates.remove(activity);
- }
- }
-}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedLoader.java b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedLoader.java
index 0c6c4b49f0..69ecced7ff 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedLoader.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedLoader.java
@@ -48,6 +48,6 @@ class QtEmbeddedLoader extends QtLoader {
protected void finish() {
// Called when loading fails - clear the delegate to make sure we don't hold reference
// to the embedding Context
- QtEmbeddedDelegateFactory.remove((Activity)m_context.getBaseContext());
+ QtEmbeddedViewInterfaceFactory.remove((Activity)m_context.getBaseContext());
}
}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedViewInterfaceFactory.java b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedViewInterfaceFactory.java
new file mode 100644
index 0000000000..8a5764e93f
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedViewInterfaceFactory.java
@@ -0,0 +1,34 @@
+// Copyright (C) 2024 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.Context;
+import android.app.Activity;
+import android.app.Service;
+
+import java.util.HashMap;
+
+class QtEmbeddedViewInterfaceFactory {
+ private static final HashMap<Context, QtEmbeddedViewInterface> m_interfaces = new HashMap<>();
+ private static final Object m_interfaceLock = new Object();
+
+ public static QtEmbeddedViewInterface create(Context context) {
+ synchronized (m_interfaceLock) {
+ if (!m_interfaces.containsKey(context)) {
+ if (context instanceof Activity)
+ m_interfaces.put(context, new QtEmbeddedDelegate((Activity)context));
+ else if (context instanceof Service)
+ m_interfaces.put(context, new QtServiceEmbeddedDelegate((Service)context));
+ }
+
+ return m_interfaces.get(context);
+ }
+ }
+
+ public static void remove(Context context) {
+ synchronized (m_interfaceLock) {
+ m_interfaces.remove(context);
+ }
+ }
+}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java b/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java
index 1bfe05e7ac..b95f817d33 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java
@@ -77,6 +77,10 @@ class QtInputConnection extends BaseInputConnection
Log.w(QtTAG, "HideKeyboardRunnable: The activity reference is null");
return;
}
+ if (m_qtInputConnectionListener == null) {
+ Log.w(QtTAG, "HideKeyboardRunnable: QtInputConnectionListener is null");
+ return;
+ }
Rect r = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
@@ -109,7 +113,7 @@ class QtInputConnection extends BaseInputConnection
{
if (closing)
m_view.postDelayed(new HideKeyboardRunnable(), 100);
- else
+ else if (m_qtInputConnectionListener != null)
m_qtInputConnectionListener.onSetClosing(false);
}
@@ -297,7 +301,8 @@ class QtInputConnection extends BaseInputConnection
restartImmInput();
break;
default:
- m_qtInputConnectionListener.onSendKeyEventDefaultCase();
+ if (m_qtInputConnectionListener != null)
+ m_qtInputConnectionListener.onSendKeyEventDefaultCase();
break;
}
}
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 cfa273e410..bf5578285a 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java
@@ -21,7 +21,8 @@ import android.view.inputmethod.InputMethodManager;
import org.qtproject.qt.android.QtInputConnection.QtInputConnectionListener;
/** @noinspection FieldCanBeLocal*/
-class QtInputDelegate implements QtInputConnection.QtInputConnectionListener {
+class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, QtInputInterface
+{
// keyboard methods
public static native void keyDown(int key, int unicode, int modifier, boolean autoRepeat);
@@ -90,6 +91,140 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener {
m_imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
}
+ // QtInputInterface implementation begin
+ @Override
+ public void updateSelection(final int selStart, final int selEnd,
+ final int candidatesStart, final int candidatesEnd)
+ {
+ QtNative.runAction(() -> {
+ if (m_imm == null)
+ return;
+
+ m_imm.updateSelection(m_currentEditText, selStart, selEnd, candidatesStart, candidatesEnd);
+ });
+ }
+
+ @Override
+ public void showSoftwareKeyboard(Activity activity, QtLayout layout,
+ final int x, final int y, final int width, final int height,
+ final int inputHints, final int enterKeyType)
+ {
+ QtNative.runAction(() -> {
+ if (m_imm == null || m_currentEditText == null)
+ return;
+
+ if (updateSoftInputMode(activity, height))
+ return;
+
+ m_currentEditText.setEditTextOptions(enterKeyType, inputHints);
+
+ m_currentEditText.postDelayed(() -> {
+ m_imm.showSoftInput(m_currentEditText, 0, new ResultReceiver(new Handler()) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ switch (resultCode) {
+ case InputMethodManager.RESULT_SHOWN:
+ QtNativeInputConnection.updateCursorPosition();
+ //FALLTHROUGH
+ case InputMethodManager.RESULT_UNCHANGED_SHOWN:
+ setKeyboardVisibility(true, System.nanoTime());
+ if (m_softInputMode == 0) {
+ probeForKeyboardHeight(layout, activity,
+ x, y, width, height, inputHints, enterKeyType);
+ }
+ break;
+ case InputMethodManager.RESULT_HIDDEN:
+ case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
+ setKeyboardVisibility(false, System.nanoTime());
+ break;
+ }
+ }
+ });
+ if (m_currentEditText.m_optionsChanged) {
+ m_imm.restartInput(m_currentEditText);
+ m_currentEditText.m_optionsChanged = false;
+ }
+ }, 15);
+ });
+ }
+
+ @Override
+ public int getSelectHandleWidth()
+ {
+ int width = 0;
+ if (m_leftSelectionHandle != null && m_rightSelectionHandle != null) {
+ width = Math.max(m_leftSelectionHandle.width(), m_rightSelectionHandle.width());
+ } else if (m_cursorHandle != null) {
+ width = m_cursorHandle.width();
+ }
+ return width;
+ }
+
+ /* called from the C++ code when the position of the cursor or selection handles needs to
+ be adjusted.
+ mode is one of QAndroidInputContext::CursorHandleShowMode
+ */
+ @Override
+ public void updateHandles(Activity activity, QtLayout layout, int mode,
+ int editX, int editY, int editButtons,
+ int x1, int y1, int x2, int y2, boolean rtl)
+ {
+ QtNative.runAction(() -> updateHandleImpl(activity, layout, mode, editX, editY, editButtons,
+ x1, y1, x2, y2, rtl));
+ }
+
+ @Override
+ public QtInputConnection.QtInputConnectionListener getInputConnectionListener()
+ {
+ return this;
+ }
+
+ @Override
+ public void resetSoftwareKeyboard()
+ {
+ if (m_imm == null || m_currentEditText == null)
+ return;
+ m_currentEditText.postDelayed(() -> {
+ m_imm.restartInput(m_currentEditText);
+ m_currentEditText.m_optionsChanged = false;
+ }, 5);
+ }
+
+ @Override
+ public void hideSoftwareKeyboard()
+ {
+ m_isKeyboardHidingAnimationOngoing = true;
+ QtNative.runAction(() -> {
+ if (m_imm == null || m_currentEditText == null)
+ return;
+
+ m_imm.hideSoftInputFromWindow(m_currentEditText.getWindowToken(), 0,
+ new ResultReceiver(new Handler()) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ switch (resultCode) {
+ case InputMethodManager.RESULT_SHOWN:
+ case InputMethodManager.RESULT_UNCHANGED_SHOWN:
+ setKeyboardVisibility(true, System.nanoTime());
+ break;
+ case InputMethodManager.RESULT_HIDDEN:
+ case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
+ setKeyboardVisibility(false, System.nanoTime());
+ break;
+ }
+ }
+ });
+ });
+ }
+
+ // Is the keyboard fully visible i.e. visible and no ongoing animation
+ @Override
+ public boolean isSoftwareKeyboardVisible()
+ {
+ return isKeyboardVisible() && !m_isKeyboardHidingAnimationOngoing;
+ }
+ // QtInputInterface implementation end
+
// QtInputConnectionListener methods
@Override
public void onSetClosing(boolean closing) {
@@ -113,13 +248,6 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener {
return m_keyboardIsVisible;
}
- // Is the keyboard fully visible i.e. visible and no ongoing animation
- @UsedFromNativeCode
- public boolean isSoftwareKeyboardVisible()
- {
- return isKeyboardVisible() && !m_isKeyboardHidingAnimationOngoing;
- }
-
void setSoftInputMode(int inputMode)
{
m_softInputMode = inputMode;
@@ -158,65 +286,11 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener {
}
- @UsedFromNativeCode
- public void resetSoftwareKeyboard()
- {
- if (m_imm == null || m_currentEditText == null)
- return;
- m_currentEditText.postDelayed(() -> {
- m_imm.restartInput(m_currentEditText);
- m_currentEditText.m_optionsChanged = false;
- }, 5);
- }
-
void setFocusedView(QtEditText currentEditText)
{
m_currentEditText = currentEditText;
}
- public void showSoftwareKeyboard(Activity activity, QtLayout layout,
- final int x, final int y, final int width, final int height,
- final int inputHints, final int enterKeyType)
- {
- QtNative.runAction(() -> {
- if (m_imm == null || m_currentEditText == null)
- return;
-
- if (updateSoftInputMode(activity, height))
- return;
-
- m_currentEditText.setEditTextOptions(enterKeyType, inputHints);
-
- m_currentEditText.postDelayed(() -> {
- m_imm.showSoftInput(m_currentEditText, 0, new ResultReceiver(new Handler()) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- switch (resultCode) {
- case InputMethodManager.RESULT_SHOWN:
- QtNativeInputConnection.updateCursorPosition();
- //FALLTHROUGH
- case InputMethodManager.RESULT_UNCHANGED_SHOWN:
- setKeyboardVisibility(true, System.nanoTime());
- if (m_softInputMode == 0) {
- probeForKeyboardHeight(layout, activity,
- x, y, width, height, inputHints, enterKeyType);
- }
- break;
- case InputMethodManager.RESULT_HIDDEN:
- case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
- setKeyboardVisibility(false, System.nanoTime());
- break;
- }
- }
- });
- if (m_currentEditText.m_optionsChanged) {
- m_imm.restartInput(m_currentEditText);
- m_currentEditText.m_optionsChanged = false;
- }
- }, 15);
- });
- }
-
private boolean updateSoftInputMode(Activity activity, int height)
{
DisplayMetrics metrics = new DisplayMetrics();
@@ -284,69 +358,6 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener {
}, m_probeKeyboardHeightDelayMs);
}
- public void hideSoftwareKeyboard()
- {
- m_isKeyboardHidingAnimationOngoing = true;
- QtNative.runAction(() -> {
- if (m_imm == null || m_currentEditText == null)
- return;
-
- m_imm.hideSoftInputFromWindow(m_currentEditText.getWindowToken(), 0,
- new ResultReceiver(new Handler()) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- switch (resultCode) {
- case InputMethodManager.RESULT_SHOWN:
- case InputMethodManager.RESULT_UNCHANGED_SHOWN:
- setKeyboardVisibility(true, System.nanoTime());
- break;
- case InputMethodManager.RESULT_HIDDEN:
- case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
- setKeyboardVisibility(false, System.nanoTime());
- break;
- }
- }
- });
- });
- }
-
- @UsedFromNativeCode
- public void updateSelection(final int selStart, final int selEnd,
- final int candidatesStart, final int candidatesEnd)
- {
- QtNative.runAction(() -> {
- if (m_imm == null)
- return;
-
- m_imm.updateSelection(m_currentEditText, selStart, selEnd, candidatesStart, candidatesEnd);
- });
- }
-
- @UsedFromNativeCode
- public int getSelectHandleWidth()
- {
- int width = 0;
- if (m_leftSelectionHandle != null && m_rightSelectionHandle != null) {
- width = Math.max(m_leftSelectionHandle.width(), m_rightSelectionHandle.width());
- } else if (m_cursorHandle != null) {
- width = m_cursorHandle.width();
- }
- return width;
- }
-
- /* called from the C++ code when the position of the cursor or selection handles needs to
- be adjusted.
- mode is one of QAndroidInputContext::CursorHandleShowMode
- */
- @UsedFromNativeCode
- public void updateHandles(Activity activity, QtLayout layout, int mode,
- int editX, int editY, int editButtons,
- int x1, int y1, int x2, int y2, boolean rtl)
- {
- QtNative.runAction(() -> updateHandleImpl(activity, layout, mode, editX, editY, editButtons,
- x1, y1, x2, y2, rtl));
- }
-
private void updateHandleImpl(Activity activity, QtLayout layout, int mode,
int editX, int editY, int editButtons,
int x1, int y1, int x2, int y2, boolean rtl)
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtInputInterface.java b/src/android/jar/src/org/qtproject/qt/android/QtInputInterface.java
new file mode 100644
index 0000000000..1dc4d5fd7f
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt/android/QtInputInterface.java
@@ -0,0 +1,21 @@
+// Copyright (C) 2024 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.app.Activity;
+
+@UsedFromNativeCode
+interface QtInputInterface {
+ void updateSelection(final int selStart, final int selEnd, final int candidatesStart,
+ final int candidatesEnd);
+ void showSoftwareKeyboard(Activity activity, QtLayout layout, final int x, final int y,
+ final int width, final int height, final int inputHints,
+ final int enterKeyType);
+ void resetSoftwareKeyboard();
+ void hideSoftwareKeyboard();
+ boolean isSoftwareKeyboardVisible();
+ int getSelectHandleWidth();
+ void updateHandles(Activity activity, QtLayout layout, int mode, int editX, int editY,
+ int editButtons, int x1, int y1, int x2, int y2, boolean rtl);
+ QtInputConnection.QtInputConnectionListener getInputConnectionListener();
+}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtLayoutInterface.java b/src/android/jar/src/org/qtproject/qt/android/QtLayoutInterface.java
new file mode 100644
index 0000000000..8444266893
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt/android/QtLayoutInterface.java
@@ -0,0 +1,8 @@
+// Copyright (C) 2024 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;
+
+@UsedFromNativeCode
+interface QtLayoutInterface {
+ QtLayout getQtLayout();
+}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtMenuInterface.java b/src/android/jar/src/org/qtproject/qt/android/QtMenuInterface.java
new file mode 100644
index 0000000000..556b9a57b9
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt/android/QtMenuInterface.java
@@ -0,0 +1,11 @@
+// Copyright (C) 2024 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;
+
+@UsedFromNativeCode
+interface QtMenuInterface {
+ void resetOptionsMenu();
+ void openOptionsMenu();
+ void closeContextMenu();
+ void openContextMenu(final int x, final int y, final int w, final int h);
+}
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 b2a2887ad5..17e1386efb 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtNative.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtNative.java
@@ -30,15 +30,16 @@ import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
-class QtNative
+// ### Qt7: make private and find new API for onNewIntent()
+public class QtNative
{
private static WeakReference<Activity> m_activity = null;
private static WeakReference<Service> m_service = null;
- public static final Object m_mainActivityMutex = new Object(); // mutex used to synchronize runnable operations
+ private static final Object m_mainActivityMutex = new Object(); // mutex used to synchronize runnable operations
private static final ApplicationStateDetails m_stateDetails = new ApplicationStateDetails();
- public static final String QtTAG = "Qt JAVA";
+ static final String QtTAG = "Qt JAVA";
// a list containing all actions which could not be performed (e.g. the main activity is destroyed, etc.)
private static final ArrayList<Runnable> m_lostActions = new ArrayList<>();
@@ -51,24 +52,24 @@ class QtNative
private static final Object m_appStateListenersLock = new Object();
@UsedFromNativeCode
- public static ClassLoader classLoader()
+ static ClassLoader classLoader()
{
return m_classLoader;
}
- public static void setClassLoader(ClassLoader classLoader)
+ static void setClassLoader(ClassLoader classLoader)
{
m_classLoader = classLoader;
}
- public static void setActivity(Activity qtMainActivity)
+ static void setActivity(Activity qtMainActivity)
{
synchronized (m_mainActivityMutex) {
m_activity = new WeakReference<>(qtMainActivity);
}
}
- public static void setService(Service qtMainService)
+ static void setService(Service qtMainService)
{
synchronized (m_mainActivityMutex) {
m_service = new WeakReference<>(qtMainService);
@@ -76,40 +77,40 @@ class QtNative
}
@UsedFromNativeCode
- public static Activity activity()
+ static Activity activity()
{
synchronized (m_mainActivityMutex) {
return m_activity != null ? m_activity.get() : null;
}
}
- public static boolean isActivityValid()
+ static boolean isActivityValid()
{
return m_activity != null && m_activity.get() != null;
}
@UsedFromNativeCode
- public static Service service()
+ static Service service()
{
synchronized (m_mainActivityMutex) {
return m_service != null ? m_service.get() : null;
}
}
- public static boolean isServiceValid()
+ static boolean isServiceValid()
{
return m_service != null && m_service.get() != null;
}
@UsedFromNativeCode
- public static Context getContext() {
+ static Context getContext() {
if (isActivityValid())
return m_activity.get();
return service();
}
@UsedFromNativeCode
- public static String[] getStringArray(String joinedString)
+ static String[] getStringArray(String joinedString)
{
return joinedString.split(",");
}
@@ -162,7 +163,7 @@ class QtNative
}
@UsedFromNativeCode
- public static boolean openURL(Context context, String url, String mime)
+ static boolean openURL(Context context, String url, String mime)
{
final Uri uri = getUriWithValidPermission(context, url, "r");
if (uri == null) {
@@ -201,39 +202,39 @@ class QtNative
}
// Keep in sync with src/corelib/global/qnamespace.h
- public static class ApplicationState {
+ static class ApplicationState {
static final int ApplicationSuspended = 0x0;
static final int ApplicationHidden = 0x1;
static final int ApplicationInactive = 0x2;
static final int ApplicationActive = 0x4;
}
- public static class ApplicationStateDetails {
+ static class ApplicationStateDetails {
int state = ApplicationState.ApplicationSuspended;
boolean nativePluginIntegrationReady = false;
boolean isStarted = false;
}
- public static ApplicationStateDetails getStateDetails()
+ static ApplicationStateDetails getStateDetails()
{
return m_stateDetails;
}
- public static void setStarted(boolean started)
+ static void setStarted(boolean started)
{
m_stateDetails.isStarted = started;
notifyAppStateDetailsChanged(m_stateDetails);
}
@UsedFromNativeCode
- public static void notifyNativePluginIntegrationReady(boolean ready)
+ static void notifyNativePluginIntegrationReady(boolean ready)
{
m_stateDetails.nativePluginIntegrationReady = ready;
notifyNativePluginIntegrationReadyChanged(ready);
notifyAppStateDetailsChanged(m_stateDetails);
}
- public static void setApplicationState(int state)
+ static void setApplicationState(int state)
{
synchronized (m_mainActivityMutex) {
m_stateDetails.state = state;
@@ -276,12 +277,12 @@ class QtNative
// Post a runnable to Main (UI) Thread if the app is active,
// otherwise, queue it to be posted when the the app is active again
- public static void runAction(Runnable action)
+ static void runAction(Runnable action)
{
runAction(action, true);
}
- public static void runAction(Runnable action, boolean queueWhenInactive)
+ static void runAction(Runnable action, boolean queueWhenInactive)
{
synchronized (m_mainActivityMutex) {
final Looper mainLooper = Looper.getMainLooper();
@@ -328,7 +329,7 @@ class QtNative
runAction(() -> view.setVisibility(visible ? View.VISIBLE : View.GONE));
}
- public static void startApplication(String params, String mainLib)
+ static void startApplication(String params, String mainLib)
{
synchronized (m_mainActivityMutex) {
m_qtThread.run(() -> {
@@ -343,7 +344,7 @@ class QtNative
}
}
- public static void quitApp()
+ static void quitApp()
{
runAction(() -> {
quitQtAndroidPlugin();
@@ -357,7 +358,7 @@ class QtNative
}
@UsedFromNativeCode
- public static int checkSelfPermission(String permission)
+ static int checkSelfPermission(String permission)
{
synchronized (m_mainActivityMutex) {
Context context = getContext();
@@ -419,47 +420,43 @@ class QtNative
}
// application methods
- public static native boolean startQtAndroidPlugin(String params);
- public static native void startQtApplication();
- public static native void waitForServiceSetup();
- public static native void quitQtCoreApplication();
- public static native void quitQtAndroidPlugin();
- public static native void terminateQt();
- public static native boolean updateNativeActivity();
+ static native boolean startQtAndroidPlugin(String params);
+ static native void startQtApplication();
+ static native void waitForServiceSetup();
+ static native void quitQtCoreApplication();
+ static native void quitQtAndroidPlugin();
+ static native void terminateQt();
+ static native boolean updateNativeActivity();
// application methods
- // surface methods
- public static native void setSurface(int id, Object surface);
- // surface methods
-
// window methods
- public static native void updateWindow();
+ static native void updateWindow();
// window methods
// application methods
- public static native void updateApplicationState(int state);
+ static native void updateApplicationState(int state);
// menu methods
- public static native boolean onPrepareOptionsMenu(Menu menu);
- public static native boolean onOptionsItemSelected(int itemId, boolean checked);
- public static native void onOptionsMenuClosed(Menu menu);
-
- public static native void onCreateContextMenu(ContextMenu menu);
- public static native void fillContextMenu(Menu menu);
- public static native boolean onContextItemSelected(int itemId, boolean checked);
- public static native void onContextMenuClosed(Menu menu);
+ static native boolean onPrepareOptionsMenu(Menu menu);
+ static native boolean onOptionsItemSelected(int itemId, boolean checked);
+ static native void onOptionsMenuClosed(Menu menu);
+
+ static native void onCreateContextMenu(ContextMenu menu);
+ static native void fillContextMenu(Menu menu);
+ static native boolean onContextItemSelected(int itemId, boolean checked);
+ static native void onContextMenuClosed(Menu menu);
// menu methods
// activity methods
- public static native void onActivityResult(int requestCode, int resultCode, Intent data);
+ static native void onActivityResult(int requestCode, int resultCode, Intent data);
public static native void onNewIntent(Intent data);
- public static native void runPendingCppRunnables();
+ static native void runPendingCppRunnables();
- public static native void sendRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults);
+ static native void sendRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults);
// activity methods
// service methods
- public static native IBinder onBind(Intent intent);
+ static native IBinder onBind(Intent intent);
// service methods
}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtRootLayout.java b/src/android/jar/src/org/qtproject/qt/android/QtRootLayout.java
index 3dae587a71..b8743d5ce0 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtRootLayout.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtRootLayout.java
@@ -16,11 +16,8 @@ import android.view.Surface;
A layout which corresponds to one Activity, i.e. is the root layout where the top level window
and handles orientation changes.
*/
-public class QtRootLayout extends QtLayout
+class QtRootLayout extends QtLayout
{
- private int m_activityDisplayRotation = -1;
- private int m_ownDisplayRotation = -1;
- private int m_nativeOrientation = -1;
private int m_previousRotation = -1;
public QtRootLayout(Context context)
@@ -28,21 +25,6 @@ public class QtRootLayout extends QtLayout
super(context);
}
- public void setActivityDisplayRotation(int rotation)
- {
- m_activityDisplayRotation = rotation;
- }
-
- public void setNativeOrientation(int orientation)
- {
- m_nativeOrientation = orientation;
- }
-
- public int displayRotation()
- {
- return m_ownDisplayRotation;
- }
-
@Override
protected void onSizeChanged (int w, int h, int oldw, int oldh)
{
@@ -50,25 +32,6 @@ public class QtRootLayout extends QtLayout
if (activity == null)
return;
- DisplayMetrics realMetrics = new DisplayMetrics();
- Display display = (Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
- ? activity.getWindowManager().getDefaultDisplay()
- : activity.getDisplay();
-
- if (display == null)
- return;
-
- display.getRealMetrics(realMetrics);
- if ((realMetrics.widthPixels > realMetrics.heightPixels) != (w > h)) {
- // This is an intermediate state during display rotation.
- // The new size is still reported for old orientation, while
- // realMetrics contain sizes for new orientation. Setting
- // such parameters will produce inconsistent results, so
- // we just skip them.
- // We will have another onSizeChanged() with normal values
- // a bit later.
- return;
- }
QtDisplayManager.setApplicationDisplayMetrics(activity, w, h);
QtDisplayManager.handleOrientationChanges(activity);
}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtServiceEmbeddedDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtServiceEmbeddedDelegate.java
index 29f1d1790f..d8af626ca0 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtServiceEmbeddedDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtServiceEmbeddedDelegate.java
@@ -28,13 +28,8 @@ class QtServiceEmbeddedDelegate implements QtEmbeddedViewInterface, QtNative.App
m_service = service;
QtNative.registerAppStateListener(this);
QtNative.setService(service);
- }
-
- @UsedFromNativeCode
- QtInputDelegate getInputDelegate()
- {
- // TODO Implement text input (QTBUG-122552)
- return null;
+ // QTBUG-122920 TODO Implement accessibility for service UIs
+ // QTBUG-122552 TODO Implement text input
}
@Override
@@ -107,6 +102,7 @@ class QtServiceEmbeddedDelegate implements QtEmbeddedViewInterface, QtNative.App
{
QtNative.setApplicationState(ApplicationSuspended);
QtNative.unregisterAppStateListener(QtServiceEmbeddedDelegate.this);
+ QtEmbeddedViewInterfaceFactory.remove(m_service);
QtNative.terminateQt();
QtNative.setService(null);
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtSurface.java b/src/android/jar/src/org/qtproject/qt/android/QtSurface.java
index 3165de4811..e20974eeac 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtSurface.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtSurface.java
@@ -14,7 +14,7 @@ import android.view.SurfaceView;
@SuppressLint("ViewConstructor")
class QtSurface extends SurfaceView implements SurfaceHolder.Callback
{
- private QtSurfaceInterface m_surfaceCallback;
+ private final QtSurfaceInterface m_surfaceCallback;
public QtSurface(Context context, QtSurfaceInterface surfaceCallback, boolean onTop, int imageDepth)
{
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtSurfaceInterface.java b/src/android/jar/src/org/qtproject/qt/android/QtSurfaceInterface.java
index 8df442f730..5850f2e3a1 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtSurfaceInterface.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtSurfaceInterface.java
@@ -6,8 +6,7 @@ package org.qtproject.qt.android;
import android.view.Surface;
-
-public interface QtSurfaceInterface
+interface QtSurfaceInterface
{
void onSurfaceChanged(Surface surface);
}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtTextureView.java b/src/android/jar/src/org/qtproject/qt/android/QtTextureView.java
index 828838a9f0..95370f3e4b 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtTextureView.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtTextureView.java
@@ -5,15 +5,14 @@
package org.qtproject.qt.android;
import android.content.Context;
-import android.graphics.PixelFormat;
import android.graphics.SurfaceTexture;
import android.util.Log;
import android.view.Surface;
import android.view.TextureView;
-public class QtTextureView extends TextureView implements TextureView.SurfaceTextureListener
+class QtTextureView extends TextureView implements TextureView.SurfaceTextureListener
{
- private QtSurfaceInterface m_surfaceCallback;
+ private final QtSurfaceInterface m_surfaceCallback;
private boolean m_staysOnTop;
private Surface m_surface;
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtView.java b/src/android/jar/src/org/qtproject/qt/android/QtView.java
index ddf70b3b5b..b4fa0382ed 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtView.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtView.java
@@ -44,24 +44,15 @@ abstract class QtView extends ViewGroup {
private static native void resizeWindow(long windowReference,
int x, int y, int width, int height);
- /**
- * Create QtView for embedding a QWindow. Instantiating a QtView will load the Qt libraries
- * if they have not already been loaded, including the app library specified by appName, and
- * starting the said Qt app.
- * @param context the hosting Context
- * @param appLibName the name of the Qt app library to load and start. This corresponds to the
- target name set in Qt app's CMakeLists.txt
- **/
- public QtView(Context context, String appLibName) throws InvalidParameterException {
+ /**
+ * Create a QtView for embedding a QWindow without loading the Qt libraries or starting
+ * the Qt app.
+ * @param context the hosting Context
+ **/
+ public QtView(Context context) {
super(context);
- if (appLibName == null || appLibName.isEmpty()) {
- throw new InvalidParameterException("QtView: argument 'appLibName' may not be empty "+
- "or null");
- }
- QtEmbeddedLoader loader = new QtEmbeddedLoader(context);
- m_viewInterface = QtEmbeddedDelegateFactory.create((Activity)context);
- loader.setMainLibraryName(appLibName);
+ m_viewInterface = QtEmbeddedViewInterfaceFactory.create(context);
addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
@@ -78,10 +69,22 @@ abstract class QtView extends ViewGroup {
}
}
});
- loader.loadQtLibraries();
- // Start Native Qt application
- m_viewInterface.startQtApplication(loader.getApplicationParameters(),
- loader.getMainLibraryPath());
+ }
+ /**
+ * Create a QtView for embedding a QWindow, and load the Qt libraries if they have not already
+ * been loaded, including the app library specified by appName, and starting the said Qt app.
+ * @param context the hosting Context
+ * @param appLibName the name of the Qt app library to load and start. This corresponds to the
+ target name set in Qt app's CMakeLists.txt
+ **/
+ public QtView(Context context, String appLibName) throws InvalidParameterException {
+ this(context);
+ if (appLibName == null || appLibName.isEmpty()) {
+ throw new InvalidParameterException("QtView: argument 'appLibName' may not be empty "+
+ "or null");
+ }
+
+ loadQtLibraries(appLibName);
}
@Override
@@ -139,6 +142,15 @@ abstract class QtView extends ViewGroup {
m_windowListener = listener;
}
+ void loadQtLibraries(String appLibName) {
+ QtEmbeddedLoader loader = new QtEmbeddedLoader(getContext());
+ loader.setMainLibraryName(appLibName);
+ loader.loadQtLibraries();
+ // Start Native Qt application
+ m_viewInterface.startQtApplication(loader.getApplicationParameters(),
+ loader.getMainLibraryPath());
+ }
+
void setWindowReference(long windowReference) {
m_windowReference = windowReference;
}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtWindow.java b/src/android/jar/src/org/qtproject/qt/android/QtWindow.java
index d72e69d32a..2a9daa5d02 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtWindow.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtWindow.java
@@ -6,7 +6,6 @@ package org.qtproject.qt.android;
import android.content.Context;
import android.view.GestureDetector;
import android.view.MotionEvent;
-import android.util.Log;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
@@ -14,11 +13,9 @@ import android.view.ViewGroup;
import java.util.HashMap;
class QtWindow extends QtLayout implements QtSurfaceInterface {
- private final static String TAG = "QtWindow";
-
private View m_surfaceContainer;
private View m_nativeView;
- private HashMap<Integer, QtWindow> m_childWindows = new HashMap<Integer, QtWindow>();
+ private final HashMap<Integer, QtWindow> m_childWindows = new HashMap<>();
private QtWindow m_parentWindow;
private GestureDetector m_gestureDetector;
private final QtEditText m_editText;
@@ -26,11 +23,12 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
private static native void setSurface(int windowId, Surface surface);
static native void windowFocusChanged(boolean hasFocus, int id);
- public QtWindow(Context context, QtWindow parentWindow, QtInputDelegate delegate)
+ public QtWindow(Context context, QtWindow parentWindow,
+ QtInputConnection.QtInputConnectionListener listener)
{
super(context);
setId(View.generateViewId());
- m_editText = new QtEditText(context, delegate);
+ m_editText = new QtEditText(context, listener);
setParent(parentWindow);
setFocusableInTouchMode(true);
addView(m_editText, new QtLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
@@ -39,6 +37,7 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
QtNative.runAction(() -> {
m_gestureDetector =
new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
+ @Override
public void onLongPress(MotionEvent event) {
QtInputDelegate.longPress(getId(), (int) event.getX(), (int) event.getY());
}
@@ -47,6 +46,7 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
});
}
+ @UsedFromNativeCode
void setVisible(boolean visible) {
QtNative.runAction(() -> {
if (visible)
@@ -85,12 +85,14 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
return QtInputDelegate.sendGenericMotionEvent(event, getId());
}
+ @UsedFromNativeCode
public void removeWindow()
{
if (m_parentWindow != null)
m_parentWindow.removeChildWindow(getId());
}
+ @UsedFromNativeCode
public void createSurface(final boolean onTop,
final int x, final int y, final int w, final int h,
final int imageDepth, final boolean isOpaque,
@@ -116,6 +118,7 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
});
}
+ @UsedFromNativeCode
public void destroySurface()
{
QtNative.runAction(()-> {
@@ -126,6 +129,7 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
}, false);
}
+ @UsedFromNativeCode
public void setGeometry(final int x, final int y, final int w, final int h)
{
QtNative.runAction(()-> {
@@ -150,6 +154,7 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
});
}
+ @UsedFromNativeCode
public void setNativeView(final View view,
final int x, final int y, final int w, final int h)
{
@@ -165,6 +170,7 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
});
}
+ @UsedFromNativeCode
public void bringChildToFront(int id)
{
QtNative.runAction(()-> {
@@ -176,6 +182,7 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
});
}
+ @UsedFromNativeCode
public void bringChildToBack(int id) {
QtNative.runAction(()-> {
View view = m_childWindows.get(id);
@@ -185,6 +192,7 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
});
}
+ @UsedFromNativeCode
public void removeNativeView()
{
QtNative.runAction(()-> {
@@ -207,9 +215,4 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
if (m_parentWindow != null)
m_parentWindow.addChildWindow(this);
}
-
- QtWindow parent()
- {
- return m_parentWindow;
- }
}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtWindowInterface.java b/src/android/jar/src/org/qtproject/qt/android/QtWindowInterface.java
new file mode 100644
index 0000000000..1fb312786f
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt/android/QtWindowInterface.java
@@ -0,0 +1,11 @@
+// Copyright (C) 2024 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;
+@UsedFromNativeCode
+interface QtWindowInterface {
+ default void addTopLevelWindow(final QtWindow window) { }
+ default void removeTopLevelWindow(final int id) { }
+ default void bringChildToFront(final int id) { }
+ default void bringChildToBack(int id) { }
+ default void setSystemUiVisibility(int systemUiVisibility) { }
+}