summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTinja Paavoseppä <tinja.paavoseppa@qt.io>2023-10-17 11:47:49 +0300
committerSoheil Armin <soheil.armin@qt.io>2023-12-14 00:26:55 +0200
commitcca81a663661ef1fce5f4a9f4c5a5f5fd1381325 (patch)
tree8ed1f948368a96a7084e12670052f65efaf63e77
parentb2e44a2d1d1fa109bb2971177a4fda1210637410 (diff)
Android: Use TextureView when multiple windows present
The SurfaceView class is not the best option for when we have multiple windows, as the created Surface can only either be below the window or on top of it, it is not a part of the view hierarchy. Replace the SurfaceView with TextureView when there are more than one window. This way the surface will be a part of the view hierarchy, and will respect z-ordering. When there is only one window, keep using the SurfaceView approach to limit the effect on existing apps, as well as enable some of the benefits SurfaceView has for e.g. game and multimedia apps, such as HDR ability. Move touch handling from QtSurface to QtWindow, so touches are handled also when using TextureView instead of QtSurface aka SurfaceView. Pick-to: 6.7 Task-number: QTBUG-118142 Change-Id: I37dcaf0fb656cfc1ff2eca0a3bfe7259f607411c Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
-rw-r--r--src/android/jar/CMakeLists.txt2
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtLayout.java43
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtSurface.java49
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtSurfaceInterface.java13
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtTextureView.java52
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtWindow.java71
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.cpp12
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.h6
8 files changed, 177 insertions, 71 deletions
diff --git a/src/android/jar/CMakeLists.txt b/src/android/jar/CMakeLists.txt
index a4463291a9..7c062120f0 100644
--- a/src/android/jar/CMakeLists.txt
+++ b/src/android/jar/CMakeLists.txt
@@ -21,7 +21,9 @@ set(java_sources
src/org/qtproject/qt/android/QtLayout.java
src/org/qtproject/qt/android/QtMessageDialogHelper.java
src/org/qtproject/qt/android/QtNative.java
+ src/org/qtproject/qt/android/QtSurfaceInterface.java
src/org/qtproject/qt/android/QtSurface.java
+ src/org/qtproject/qt/android/QtTextureView.java
src/org/qtproject/qt/android/QtThread.java
src/org/qtproject/qt/android/extras/QtAndroidBinder.java
src/org/qtproject/qt/android/extras/QtAndroidServiceConnection.java
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtLayout.java b/src/android/jar/src/org/qtproject/qt/android/QtLayout.java
index 5f560db7a5..511f733479 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtLayout.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtLayout.java
@@ -10,16 +10,31 @@ import android.os.Build;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Display;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
-class QtLayout extends ViewGroup
-{
+class QtLayout extends ViewGroup {
+
+ interface QtTouchListener {
+ public boolean onTouchEvent(MotionEvent event);
+ public boolean onTrackballEvent(MotionEvent event);
+ public boolean onGenericMotionEvent(MotionEvent event);
+ }
+
+ private QtTouchListener m_touchListener;
+
public QtLayout(Context context)
{
super(context);
}
+ public QtLayout(Context context, QtTouchListener listener)
+ {
+ super(context);
+ m_touchListener = listener;
+ }
+
public QtLayout(Context context, AttributeSet attrs)
{
super(context, attrs);
@@ -31,6 +46,30 @@ class QtLayout extends ViewGroup
}
@Override
+ public boolean onTouchEvent(MotionEvent event)
+ {
+ if (m_touchListener != null) {
+ event.setLocation(event.getX() + getX(), event.getY() + getY());
+ return m_touchListener.onTouchEvent(event);
+ }
+ return false;
+ }
+ @Override
+ public boolean onTrackballEvent(MotionEvent event)
+ {;
+ if (m_touchListener != null)
+ return m_touchListener.onTrackballEvent(event);
+ return false;
+ }
+ @Override
+ public boolean onGenericMotionEvent(MotionEvent event)
+ {
+ if (m_touchListener != null)
+ return m_touchListener.onGenericMotionEvent(event);
+ return false;
+ }
+
+ @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int count = getChildCount();
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 7682d87d96..3165de4811 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtSurface.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtSurface.java
@@ -7,8 +7,6 @@ package org.qtproject.qt.android;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.PixelFormat;
-import android.view.GestureDetector;
-import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
@@ -16,17 +14,9 @@ import android.view.SurfaceView;
@SuppressLint("ViewConstructor")
class QtSurface extends SurfaceView implements SurfaceHolder.Callback
{
- private final GestureDetector m_gestureDetector;
- private Object m_accessibilityDelegate = null;
- private SurfaceChangedCallback m_surfaceCallback;
- private final int m_windowId;
+ private QtSurfaceInterface m_surfaceCallback;
- interface SurfaceChangedCallback {
- void onSurfaceChanged(Surface surface);
- }
-
- public QtSurface(Context context, SurfaceChangedCallback surfaceCallback, int id, boolean onTop,
- int imageDepth)
+ public QtSurface(Context context, QtSurfaceInterface surfaceCallback, boolean onTop, int imageDepth)
{
super(context);
setFocusable(false);
@@ -38,15 +28,6 @@ class QtSurface extends SurfaceView implements SurfaceHolder.Callback
getHolder().setFormat(PixelFormat.RGB_565);
else
getHolder().setFormat(PixelFormat.RGBA_8888);
-
- m_windowId = id;
- m_gestureDetector =
- new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
- public void onLongPress(MotionEvent event) {
- QtInputDelegate.longPress(m_windowId, (int) event.getX(), (int) event.getY());
- }
- });
- m_gestureDetector.setIsLongpressEnabled(true);
}
@Override
@@ -69,30 +50,4 @@ class QtSurface extends SurfaceView implements SurfaceHolder.Callback
if (m_surfaceCallback != null)
m_surfaceCallback.onSurfaceChanged(null);
}
-
- @Override
- public boolean onTouchEvent(MotionEvent event)
- {
- // QTBUG-65927
- // Fix event positions depending on Surface position.
- // In case when Surface is moved, we should also add this move to event position
- event.setLocation(event.getX() + getX(), event.getY() + getY());
-
- QtInputDelegate.sendTouchEvent(event, m_windowId);
- m_gestureDetector.onTouchEvent(event);
- return true;
- }
-
- @Override
- public boolean onTrackballEvent(MotionEvent event)
- {
- QtInputDelegate.sendTrackballEvent(event, m_windowId);
- return true;
- }
-
- @Override
- public boolean onGenericMotionEvent(MotionEvent event)
- {
- return QtInputDelegate.sendGenericMotionEvent(event, m_windowId);
- }
}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtSurfaceInterface.java b/src/android/jar/src/org/qtproject/qt/android/QtSurfaceInterface.java
new file mode 100644
index 0000000000..8df442f730
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt/android/QtSurfaceInterface.java
@@ -0,0 +1,13 @@
+// Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
+// Copyright (C) 2016 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.view.Surface;
+
+
+public 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
new file mode 100644
index 0000000000..828838a9f0
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt/android/QtTextureView.java
@@ -0,0 +1,52 @@
+// Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
+// Copyright (C) 2016 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.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
+{
+ private QtSurfaceInterface m_surfaceCallback;
+ private boolean m_staysOnTop;
+ private Surface m_surface;
+
+ public QtTextureView(Context context, QtSurfaceInterface surfaceCallback, boolean isOpaque)
+ {
+ super(context);
+ setFocusable(false);
+ setFocusableInTouchMode(false);
+ m_surfaceCallback = surfaceCallback;
+ setSurfaceTextureListener(this);
+ setOpaque(isOpaque);
+ setSurfaceTexture(new SurfaceTexture(false));
+ }
+
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
+ m_surface = new Surface(surfaceTexture);
+ m_surfaceCallback.onSurfaceChanged(m_surface);
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) {
+ m_surface = new Surface(surfaceTexture);
+ m_surfaceCallback.onSurfaceChanged(m_surface);
+ }
+
+ @Override
+ public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
+ m_surfaceCallback.onSurfaceChanged(null);
+ return true;
+ }
+
+ @Override
+ public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
+ }
+}
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 79e7b96cb9..44ba257ce2 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtWindow.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtWindow.java
@@ -4,6 +4,8 @@
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;
@@ -11,15 +13,16 @@ import android.view.ViewGroup;
import java.util.HashMap;
-public class QtWindow implements QtSurface.SurfaceChangedCallback {
+public class QtWindow implements QtSurfaceInterface, QtLayout.QtTouchListener {
private final static String TAG = "QtWindow";
+ private View m_surfaceContainer;
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 GestureDetector m_gestureDetector;
private static native void setSurface(int windowId, Surface surface);
@@ -27,8 +30,15 @@ public class QtWindow implements QtSurface.SurfaceChangedCallback {
{
m_id = View.generateViewId();
QtNative.runAction(() -> {
- m_layout = new QtLayout(context);
+ m_layout = new QtLayout(context, this);
setParent(parentWindow);
+ m_gestureDetector =
+ new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
+ public void onLongPress(MotionEvent event) {
+ QtInputDelegate.longPress(getId(), (int) event.getX(), (int) event.getY());
+ }
+ });
+ m_gestureDetector.setIsLongpressEnabled(true);
});
}
@@ -57,6 +67,27 @@ public class QtWindow implements QtSurface.SurfaceChangedCallback {
setSurface(getId(), surface);
}
+ @Override
+ public boolean onTouchEvent(MotionEvent event)
+ {
+ QtInputDelegate.sendTouchEvent(event, getId());
+ m_gestureDetector.onTouchEvent(event);
+ return true;
+ }
+
+ @Override
+ public boolean onTrackballEvent(MotionEvent event)
+ {
+ QtInputDelegate.sendTrackballEvent(event, getId());
+ return true;
+ }
+
+ @Override
+ public boolean onGenericMotionEvent(MotionEvent event)
+ {
+ return QtInputDelegate.sendGenericMotionEvent(event, getId());
+ }
+
public void removeWindow()
{
if (m_parentWindow != null)
@@ -65,30 +96,28 @@ public class QtWindow implements QtSurface.SurfaceChangedCallback {
public void createSurface(final boolean onTop,
final int x, final int y, final int w, final int h,
- final int imageDepth)
+ final int imageDepth, final boolean isOpaque,
+ final int surfaceContainerType) // TODO constant for type
{
QtNative.runAction(new Runnable() {
@Override
public void run() {
- if (m_surface != null)
- m_layout.removeView(m_surface);
+ if (m_surfaceContainer != null)
+ m_layout.removeView(m_surfaceContainer);
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(m_layout.getContext(), QtWindow.this,
- QtWindow.this.getId(), tempOnTop, imageDepth);
- surface.setLayoutParams(new QtLayout.LayoutParams(
+ if (surfaceContainerType == 0) {
+ m_surfaceContainer = new QtSurface(m_layout.getContext(), QtWindow.this,
+ onTop, imageDepth);
+ } else {
+ m_surfaceContainer = new QtTextureView(m_layout.getContext(), QtWindow.this, isOpaque);
+ }
+ m_surfaceContainer.setLayoutParams(new QtLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
-
- // The QtSurface of this window will be added as the first of the stack.
+ // The surface container of this window will be added as the first of the stack.
// All other views are stacked based on the order they are created.
- m_layout.addView(surface, 0);
- m_surface = surface;
+ m_layout.addView(m_surfaceContainer, 0);
}
});
}
@@ -98,9 +127,9 @@ public class QtWindow implements QtSurface.SurfaceChangedCallback {
QtNative.runAction(new Runnable() {
@Override
public void run() {
- if (m_surface != null) {
- m_layout.removeView(m_surface);
- m_surface = null;
+ if (m_surfaceContainer != null) {
+ m_layout.removeView(m_surfaceContainer);
+ m_surfaceContainer = null;
}
}
});
diff --git a/src/plugins/platforms/android/qandroidplatformwindow.cpp b/src/plugins/platforms/android/qandroidplatformwindow.cpp
index 6681f1d20d..0756fb115f 100644
--- a/src/plugins/platforms/android/qandroidplatformwindow.cpp
+++ b/src/plugins/platforms/android/qandroidplatformwindow.cpp
@@ -55,6 +55,14 @@ QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window)
if (window->isTopLevel())
platformScreen()->addWindow(this);
+
+ // TODO should handle case where this changes at runtime -> need to change existing window
+ // into TextureView (or perhaps not, if the parent window would be SurfaceView, as long as
+ // onTop was false it would stay below the children)
+ if (platformScreen()->windows().size() > 1)
+ m_surfaceContainerType = SurfaceContainer::TextureView;
+ else
+ m_surfaceContainerType = SurfaceContainer::SurfaceView;
}
QAndroidPlatformWindow::~QAndroidPlatformWindow()
@@ -236,8 +244,10 @@ void QAndroidPlatformWindow::createSurface()
}
const bool windowStaysOnTop = bool(window()->flags() & Qt::WindowStaysOnTopHint);
+ const bool isOpaque = format().hasAlpha() || (0.0 < window()->opacity() < 1.0);
- m_nativeQtWindow.callMethod<void>("createSurface", windowStaysOnTop, x, y, w, h, 32);
+ m_nativeQtWindow.callMethod<void>("createSurface", windowStaysOnTop, x, y, w, h, 32, isOpaque,
+ m_surfaceContainerType);
m_surfaceCreated = true;
}
diff --git a/src/plugins/platforms/android/qandroidplatformwindow.h b/src/plugins/platforms/android/qandroidplatformwindow.h
index 1c95ca123b..3fc5526c1c 100644
--- a/src/plugins/platforms/android/qandroidplatformwindow.h
+++ b/src/plugins/platforms/android/qandroidplatformwindow.h
@@ -26,6 +26,11 @@ class QAndroidPlatformScreen;
class QAndroidPlatformWindow: public QPlatformWindow
{
public:
+ enum class SurfaceContainer {
+ SurfaceView,
+ TextureView
+ };
+
explicit QAndroidPlatformWindow(QWindow *window);
~QAndroidPlatformWindow();
void lower() override;
@@ -76,6 +81,7 @@ protected:
int m_nativeViewId = -1;
QtJniTypes::QtWindow m_nativeQtWindow;
+ SurfaceContainer m_surfaceContainerType = SurfaceContainer::SurfaceView;
QtJniTypes::QtWindow m_nativeParentQtWindow;
// The Android Surface, accessed from multiple threads, guarded by m_surfaceMutex
QtJniTypes::Surface m_androidSurfaceObject;