Android: Add support for multiple QtViews in same Context

This patch makes it possible to have multiple QtViews
in an Android app, provided they are in the same Context.

Task-number: QTBUG-127422
Task-number: QTBUG-124116
Change-Id: I3d5bef3f789f23c8495c3b7209bbd3e430d439ac
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
(cherry picked from commit 0af53d3e87464a0638e4fdb8b68287912281a2a6)
This commit is contained in:
Tinja Paavoseppä 2024-06-06 09:28:33 +03:00 committed by Petri Virkkunen
parent a228a3e7b6
commit 46dbb74249
4 changed files with 41 additions and 44 deletions

View File

@ -20,23 +20,20 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.PopupMenu;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
class QtEmbeddedDelegate extends QtActivityDelegateBase
implements QtNative.AppStateDetailsListener, QtEmbeddedViewInterface, QtWindowInterface,
QtMenuInterface
{
private static final String QtTAG = "QtEmbeddedDelegate";
// TODO simplistic implementation with one QtView, expand to support multiple views QTBUG-117649
private QtView m_view;
private final HashSet<QtView> m_views = new HashSet<>();
private QtNative.ApplicationStateDetails m_stateDetails;
private boolean m_windowLoaded = false;
private boolean m_backendsRegistered = false;
QtEmbeddedDelegate(Activity context) {
super(context);
m_stateDetails = QtNative.getStateDetails();
QtNative.registerAppStateListener(this);
@ -111,7 +108,6 @@ class QtEmbeddedDelegate extends QtActivityDelegateBase
@Override
public void onNativePluginIntegrationReadyChanged(boolean ready)
{
synchronized (this) {
if (ready) {
QtNative.runAction(() -> {
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
@ -119,8 +115,6 @@ class QtEmbeddedDelegate extends QtActivityDelegateBase
metrics.heightPixels);
});
createRootWindow();
}
}
}
@ -138,26 +132,26 @@ class QtEmbeddedDelegate extends QtActivityDelegateBase
}
@Override
public void queueLoadWindow()
public void addView(QtView view)
{
synchronized (this) {
if (m_stateDetails.nativePluginIntegrationReady)
createRootWindow();
if (m_views.add(view)) {
QtNative.runAction(() -> { createRootWindow(view); });
}
}
@Override
public void setView(QtView view)
public void removeView(QtView view)
{
m_view = view;
m_views.remove(view.getId());
}
// QtEmbeddedViewInterface implementation end
private void createRootWindow() {
if (m_view != null && !m_windowLoaded) {
QtView.createRootWindow(m_view, m_view.getLeft(), m_view.getTop(), m_view.getWidth(),
m_view.getHeight());
m_windowLoaded = true;
// This gets called from Android thread
private void createRootWindow(QtView view) {
// No use in creating a QQuickView for a View that has been removed
if (m_views.contains(view)) {
QtView.createRootWindow(view, view.getLeft(), view.getTop(), view.getWidth(),
view.getHeight());
}
}
@ -174,12 +168,12 @@ class QtEmbeddedDelegate extends QtActivityDelegateBase
@Override
public void openContextMenu(final int x, final int y, final int w, final int h)
{
m_view.postDelayed(() -> {
final QtEditText focusedEditText = m_inputDelegate.getCurrentQtEditText();
if (focusedEditText == null) {
Log.w(QtTAG, "No focused view when trying to open context menu");
return;
}
focusedEditText.postDelayed(() -> {
PopupMenu popup = new PopupMenu(m_activity, focusedEditText);
QtNative.fillContextMenu(popup.getMenu());
popup.setOnMenuItemClickListener(menuItem ->

View File

@ -10,6 +10,6 @@ package org.qtproject.qt.android;
**/
interface QtEmbeddedViewInterface {
void startQtApplication(String appParams, String mainLib);
void setView(QtView view);
void queueLoadWindow();
void addView(QtView view);
void removeView(QtView view);
};

View File

@ -71,20 +71,22 @@ class QtServiceEmbeddedDelegate implements QtEmbeddedViewInterface, QtNative.App
}
@Override
public void setView(QtView view)
public void addView(QtView view)
{
m_view = view;
// If the embedded view is destroyed, do cleanup:
if (view == null)
cleanup();
QtNative.runAction(() -> {
createRootWindow();
});
}
@Override
public void queueLoadWindow()
public void removeView(QtView view)
{
synchronized (this) {
if (QtNative.getStateDetails().nativePluginIntegrationReady)
createRootWindow();
if (m_view == view) {
m_view = null;
m_windowLoaded = false;
// If the embedded view is destroyed, do cleanup:
cleanup();
}
}
// QtEmbeddedViewInterface implementation end

View File

@ -70,6 +70,8 @@ abstract class QtView extends ViewGroup {
}
}
});
if (getId() == -1)
setId(View.generateViewId());
}
/**
* Create a QtView for embedding a QWindow, and load the Qt libraries if they have not already
@ -90,15 +92,14 @@ abstract class QtView extends ViewGroup {
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
m_viewInterface.setView(this);
m_viewInterface.queueLoadWindow();
m_viewInterface.addView(this);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
destroyWindow();
m_viewInterface.setView(null);
m_viewInterface.removeView(this);
}
@Override