diff options
| author | Tinja Paavoseppä <tinja.paavoseppa@qt.io> | 2023-12-08 11:24:43 +0200 |
|---|---|---|
| committer | Tinja Paavoseppä <tinja.paavoseppa@qt.io> | 2023-12-08 15:53:37 +0200 |
| commit | 2bc7d38bd63843c4598ed501e3adbf0e39162c61 (patch) | |
| tree | d3d9ffb035add93e032661095e2ec399b8da3526 /src | |
| parent | 6ff88f97a6d24d1098583421161f8f903f9dafde (diff) | |
Android: Make QtWindow wrap the QtLayout instead of inherit it
The layout is a ViewGroup, and should be created in the Android UI
thread, while for ease of use on C++ side we should be able to
construct the Java object in the platform window constructor to
avoid later calls not having a valid object reference. Trying to
make a blocking call to Android thread from Qt thread can lead to
dead locks, so move only the creation of the layout itself into
Android thread, making the QtWindow a wrapper for it, which we can
immediately return to C++/Qt thread. Most of the calls made to
QtWindow are anyway already passed to the Android UI thread.
As a drive by, add a missing QtNative.runAction() to
bringChildToFront().
Change-Id: Ib2495ddda8267384656557cbe40be5da869f82c3
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'src')
3 files changed, 52 insertions, 39 deletions
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 b7d1f207daf..8f6114a7c2f 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java @@ -386,11 +386,11 @@ class QtActivityDelegate } } - window.setLayoutParams(new ViewGroup.LayoutParams( + window.getLayout().setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - m_layout.addView(window, m_topLevelWindows.size()); + m_layout.addView(window.getLayout(), m_topLevelWindows.size()); m_topLevelWindows.put(window.getId(), window); if (!m_splashScreenSticky) hideSplashScreen(); @@ -406,9 +406,9 @@ class QtActivityDelegate if (m_topLevelWindows.isEmpty()) { // Keep last frame in stack until it is replaced to get correct // shutdown transition - m_dummyView = window; + m_dummyView = window.getLayout(); } else { - m_layout.removeView(window); + m_layout.removeView(window.getLayout()); } } }); @@ -420,7 +420,7 @@ class QtActivityDelegate QtNative.runAction(() -> { QtWindow window = m_topLevelWindows.get(id); if (window != null) { - m_layout.moveChild(window, m_topLevelWindows.size() - 1); + m_layout.moveChild(window.getLayout(), m_topLevelWindows.size() - 1); } }); } @@ -431,7 +431,7 @@ class QtActivityDelegate QtNative.runAction(() -> { QtWindow window = m_topLevelWindows.get(id); if (window != null) - m_layout.moveChild(window, 0); + m_layout.moveChild(window.getLayout(), 0); }); } 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 757b00d93f8..79e7b96cb9b 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtWindow.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtWindow.java @@ -11,33 +11,46 @@ import android.view.ViewGroup; import java.util.HashMap; -public class QtWindow extends QtLayout implements QtSurface.SurfaceChangedCallback { +public class QtWindow implements QtSurface.SurfaceChangedCallback { private final static String TAG = "QtWindow"; + private QtLayout m_layout; private QtSurface m_surface; private View m_nativeView; private HashMap<Integer, QtWindow> m_childWindows = new HashMap<Integer, QtWindow>(); private QtWindow m_parentWindow; + private int m_id; private static native void setSurface(int windowId, Surface surface); public QtWindow(Context context, QtWindow parentWindow) { - super(context); - setId(View.generateViewId()); - - setParent(parentWindow); + m_id = View.generateViewId(); + QtNative.runAction(() -> { + m_layout = new QtLayout(context); + setParent(parentWindow); + }); } void setVisible(boolean visible) { QtNative.runAction(() -> { if (visible) - setVisibility(View.VISIBLE); + m_layout.setVisibility(View.VISIBLE); else - setVisibility(View.INVISIBLE); + m_layout.setVisibility(View.INVISIBLE); }); } + public int getId() + { + return m_id; + } + + public QtLayout getLayout() + { + return m_layout; + } + @Override public void onSurfaceChanged(Surface surface) { @@ -58,15 +71,15 @@ public class QtWindow extends QtLayout implements QtSurface.SurfaceChangedCallba @Override public void run() { if (m_surface != null) - removeView(m_surface); + m_layout.removeView(m_surface); - setLayoutParams(new QtLayout.LayoutParams(w, h, x, y)); + m_layout.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y)); // TODO currently setting child windows to onTop, since their surfaces // now get created earlier than the parents -> they are behind the parent window // without this, and SurfaceView z-ordering is limited boolean tempOnTop = onTop || (m_parentWindow != null); - QtSurface surface = new QtSurface(getContext(), QtWindow.this, + QtSurface surface = new QtSurface(m_layout.getContext(), QtWindow.this, QtWindow.this.getId(), tempOnTop, imageDepth); surface.setLayoutParams(new QtLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, @@ -74,7 +87,7 @@ public class QtWindow extends QtLayout implements QtSurface.SurfaceChangedCallba // The QtSurface of this window will be added as the first of the stack. // All other views are stacked based on the order they are created. - addView(surface, 0); + m_layout.addView(surface, 0); m_surface = surface; } }); @@ -86,7 +99,7 @@ public class QtWindow extends QtLayout implements QtSurface.SurfaceChangedCallba @Override public void run() { if (m_surface != null) { - removeView(m_surface); + m_layout.removeView(m_surface); m_surface = null; } } @@ -98,7 +111,7 @@ public class QtWindow extends QtLayout implements QtSurface.SurfaceChangedCallba QtNative.runAction(new Runnable() { @Override public void run() { - QtWindow.this.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y)); + m_layout.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y)); } }); } @@ -109,7 +122,7 @@ public class QtWindow extends QtLayout implements QtSurface.SurfaceChangedCallba @Override public void run() { m_childWindows.put(window.getId(), window); - addView(window, getChildCount()); + m_layout.addView(window.getLayout(), m_layout.getChildCount()); } }); } @@ -120,7 +133,7 @@ public class QtWindow extends QtLayout implements QtSurface.SurfaceChangedCallba @Override public void run() { if (m_childWindows.containsKey(id)) - removeView(m_childWindows.remove(id)); + m_layout.removeView(m_childWindows.remove(id).getLayout()); } }); } @@ -132,33 +145,35 @@ public class QtWindow extends QtLayout implements QtSurface.SurfaceChangedCallba @Override public void run() { if (m_nativeView != null) - removeView(m_nativeView); + m_layout.removeView(m_nativeView); m_nativeView = view; - QtWindow.this.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y)); + m_layout.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y)); m_nativeView.setLayoutParams(new QtLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - addView(m_nativeView); + m_layout.addView(m_nativeView); } }); } public void bringChildToFront(int id) { - View view = m_childWindows.get(id); - if (view != null) { - if (getChildCount() > 0) - moveChild(view, getChildCount() - 1); - } + QtNative.runAction(()-> { + QtWindow window = m_childWindows.get(id); + if (window != null) { + if (m_layout.getChildCount() > 0) + m_layout.moveChild(window.getLayout(), m_layout.getChildCount() - 1); + } + }); } public void bringChildToBack(int id) { QtNative.runAction(new Runnable() { @Override public void run() { - View view = m_childWindows.get(id); - if (view != null) { - moveChild(view, 0); + QtWindow window = m_childWindows.get(id); + if (window != null) { + m_layout.moveChild(window.getLayout(), 0); } } }); @@ -170,7 +185,7 @@ public class QtWindow extends QtLayout implements QtSurface.SurfaceChangedCallba @Override public void run() { if (m_nativeView != null) { - removeView(m_nativeView); + m_layout.removeView(m_nativeView); m_nativeView = null; } } diff --git a/src/plugins/platforms/android/qandroidplatformwindow.cpp b/src/plugins/platforms/android/qandroidplatformwindow.cpp index 9a633e97afe..84a4eab3892 100644 --- a/src/plugins/platforms/android/qandroidplatformwindow.cpp +++ b/src/plugins/platforms/android/qandroidplatformwindow.cpp @@ -51,12 +51,10 @@ QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window) if (parent()) m_nativeParentQtWindow = static_cast<QAndroidPlatformWindow*>(parent())->nativeWindow(); - QNativeInterface::QAndroidApplication::runOnAndroidMainThread([this]() { - m_nativeQtWindow = QJniObject::construct<QtJniTypes::QtWindow>( - QNativeInterface::QAndroidApplication::context(), - m_nativeParentQtWindow); - m_nativeViewId = m_nativeQtWindow.callMethod<jint>("getId"); - }).waitForFinished(); + m_nativeQtWindow = QJniObject::construct<QtJniTypes::QtWindow>( + QNativeInterface::QAndroidApplication::context(), + m_nativeParentQtWindow); + m_nativeViewId = m_nativeQtWindow.callMethod<jint>("getId"); if (window->isTopLevel()) platformScreen()->addWindow(this); |
