summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/android/jar/CMakeLists.txt1
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java22
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java176
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtSurface.java29
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtWindow.java114
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp123
-rw-r--r--src/plugins/platforms/android/androidjnimain.h8
-rw-r--r--src/plugins/platforms/android/qandroidplatformforeignwindow.cpp58
-rw-r--r--src/plugins/platforms/android/qandroidplatformforeignwindow.h10
-rw-r--r--src/plugins/platforms/android/qandroidplatformopenglwindow.cpp8
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.cpp51
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.h5
-rw-r--r--src/plugins/platforms/android/qandroidplatformvulkanwindow.cpp4
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.cpp132
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.h22
15 files changed, 383 insertions, 380 deletions
diff --git a/src/android/jar/CMakeLists.txt b/src/android/jar/CMakeLists.txt
index 87f1e030d19..82460b553c7 100644
--- a/src/android/jar/CMakeLists.txt
+++ b/src/android/jar/CMakeLists.txt
@@ -29,6 +29,7 @@ set(java_sources
src/org/qtproject/qt/android/QtClipboardManager.java
src/org/qtproject/qt/android/QtDisplayManager.java
src/org/qtproject/qt/android/UsedFromNativeCode.java
+ src/org/qtproject/qt/android/QtWindow.java
)
qt_internal_add_jar(Qt${QtBase_VERSION_MAJOR}Android
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 82b8976144e..9eaefed2a7c 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java
@@ -36,9 +36,7 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
private View m_view = null;
private final AccessibilityManager m_manager;
- private final QtActivityDelegate m_activityDelegate;
- private final Activity m_activity;
- private final ViewGroup m_layout;
+ private final QtLayout m_layout;
// The accessible object that currently has the "accessibility focus"
// usually indicated by a yellow rectangle on screen.
@@ -62,13 +60,11 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
}
}
- public QtAccessibilityDelegate(Activity activity, ViewGroup layout, QtActivityDelegate activityDelegate)
+ public QtAccessibilityDelegate(QtLayout layout)
{
- m_activity = activity;
m_layout = layout;
- m_activityDelegate = activityDelegate;
- m_manager = (AccessibilityManager) m_activity.getSystemService(Context.ACCESSIBILITY_SERVICE);
+ m_manager = (AccessibilityManager) m_layout.getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
if (m_manager != null) {
AccessibilityManagerListener accServiceListener = new AccessibilityManagerListener();
if (!m_manager.addAccessibilityStateChangeListener(accServiceListener))
@@ -89,7 +85,7 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
try {
View view = m_view;
if (view == null) {
- view = new View(m_activity);
+ view = new View(m_layout.getContext());
view.setId(View.NO_ID);
}
@@ -105,7 +101,7 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
// if all is fine, add it to the layout
if (m_view == null) {
//m_layout.addAccessibilityView(view);
- m_layout.addView(view, m_activityDelegate.getSurfaceCount(),
+ m_layout.addView(view, m_layout.getChildCount(),
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
}
m_view = view;
@@ -289,7 +285,7 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
return null;
}
- if (m_activityDelegate.getSurfaceCount() == 0)
+ if (m_layout.getChildCount() == 0)
return null;
final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
@@ -356,7 +352,7 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
// Spit out the entire hierarchy for debugging purposes
// dumpNodes(-1);
- if (m_activityDelegate.getSurfaceCount() != 0) {
+ if (m_layout.getChildCount() == 0) {
int[] ids = QtNativeAccessibility.childIdListForAccessibleObject(-1);
for (int id : ids)
result.addChild(m_view, id);
@@ -388,7 +384,7 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
node.setClassName(m_view.getClass().getName() + DEFAULT_CLASS_NAME);
node.setPackageName(m_view.getContext().getPackageName());
- if (m_activityDelegate.getSurfaceCount() == 0 || !QtNativeAccessibility.populateNode(virtualViewId, node)) {
+ if (m_layout.getChildCount() == 0 || !QtNativeAccessibility.populateNode(virtualViewId, node)) {
return node;
}
@@ -439,7 +435,7 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
@Override
public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId)
{
- if (virtualViewId == View.NO_ID || m_activityDelegate.getSurfaceCount() == 0) {
+ if (virtualViewId == View.NO_ID || m_layout.getChildCount() == 0) {
return getNodeForView();
}
return getNodeForVirtualViewId(virtualViewId);
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 6a87c187be0..8f98dfa28fe 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java
@@ -11,6 +11,7 @@ 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;
import android.os.Build;
import android.util.DisplayMetrics;
@@ -36,9 +37,8 @@ class QtActivityDelegate
{
private Activity m_activity;
- private HashMap<Integer, QtSurface> m_surfaces = null;
- private HashMap<Integer, View> m_nativeViews = null;
private QtLayout m_layout = null;
+ private HashMap<Integer, QtWindow> m_topLevelWindows;
private ImageView m_splashScreen = null;
private boolean m_splashScreenSticky = false;
@@ -48,6 +48,7 @@ class QtActivityDelegate
private QtDisplayManager m_displayManager = null;
private QtInputDelegate m_inputDelegate = null;
+ private boolean m_membersInitialized = false;
QtActivityDelegate(Activity activity)
{
@@ -55,6 +56,7 @@ class QtActivityDelegate
QtNative.setActivity(m_activity);
setActionBarVisibility(false);
+ setActivityBackgroundDrawable();
}
QtDisplayManager displayManager() {
@@ -116,7 +118,7 @@ class QtActivityDelegate
public void startNativeApplication(String appParams, String mainLib)
{
- if (m_surfaces != null)
+ if (m_membersInitialized)
return;
initMembers();
@@ -134,6 +136,8 @@ class QtActivityDelegate
private void initMembers()
{
m_layout = new QtLayout(m_activity);
+ m_membersInitialized = true;
+ m_topLevelWindows = new HashMap<Integer, QtWindow>();
m_displayManager = new QtDisplayManager(m_activity);
m_displayManager.registerDisplayListener();
@@ -173,8 +177,6 @@ class QtActivityDelegate
e.printStackTrace();
}
- m_surfaces = new HashMap<>();
- m_nativeViews = new HashMap<>();
m_activity.registerForContextMenu(m_layout);
m_activity.setContentView(m_layout,
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
@@ -293,9 +295,7 @@ class QtActivityDelegate
@UsedFromNativeCode
public void initializeAccessibility()
{
- final QtActivityDelegate currentDelegate = this;
- QtNative.runAction(() -> m_accessibilityDelegate = new QtAccessibilityDelegate(m_activity,
- m_layout, currentDelegate));
+ QtNative.runAction(() -> m_accessibilityDelegate = new QtAccessibilityDelegate(m_layout));
}
void handleUiModeChange(int uiMode)
@@ -377,153 +377,79 @@ class QtActivityDelegate
}
@UsedFromNativeCode
- public void insertNativeView(int id, View view, int x, int y, int w, int h) {
- QtNative.runAction(() -> {
- if (m_dummyView != null) {
- m_layout.removeView(m_dummyView);
- m_dummyView = null;
- }
-
- if (m_nativeViews.containsKey(id))
- m_layout.removeView(m_nativeViews.remove(id));
-
- if (w < 0 || h < 0) {
- view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT));
- } else {
- view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
- }
-
- view.setId(id);
- m_layout.addView(view);
- m_nativeViews.put(id, view);
- });
- }
-
- @UsedFromNativeCode
- public void createSurface(int id, boolean onTop, int x, int y, int w, int h, int imageDepth) {
- QtNative.runAction(() -> {
- if (m_surfaces.size() == 0) {
- TypedValue attr = new TypedValue();
- m_activity.getTheme().resolveAttribute(android.R.attr.windowBackground, attr, true);
- if (attr.type >= TypedValue.TYPE_FIRST_COLOR_INT && attr.type <= TypedValue.TYPE_LAST_COLOR_INT) {
- m_activity.getWindow().setBackgroundDrawable(new ColorDrawable(attr.data));
- } else {
- m_activity.getWindow().setBackgroundDrawable(m_activity.getResources().getDrawable(attr.resourceId, m_activity.getTheme()));
- }
+ public void addTopLevelWindow(final QtWindow window)
+ {
+ QtNative.runAction(()-> {
+ if (m_topLevelWindows.size() == 0) {
if (m_dummyView != null) {
m_layout.removeView(m_dummyView);
m_dummyView = null;
}
}
- if (m_surfaces.containsKey(id))
- m_layout.removeView(m_surfaces.remove(id));
-
- QtSurface surface = new QtSurface(m_activity, id, onTop, imageDepth);
- if (w < 0 || h < 0) {
- surface.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT));
- } else {
- surface.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
- }
-
- // Native views are always inserted in the end of the stack (i.e., on top).
- // All other views are stacked based on the order they are created.
- final int surfaceCount = getSurfaceCount();
- m_layout.addView(surface, surfaceCount);
+ window.setLayoutParams(new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT));
- m_surfaces.put(id, surface);
+ m_layout.addView(window, m_topLevelWindows.size());
+ m_topLevelWindows.put(window.getId(), window);
if (!m_splashScreenSticky)
hideSplashScreen();
});
}
@UsedFromNativeCode
- public void setSurfaceGeometry(int id, int x, int y, int w, int h) {
- QtNative.runAction(() -> {
- if (m_surfaces.containsKey(id)) {
- QtSurface surface = m_surfaces.get(id);
- if (surface != null)
- surface.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
- else
- Log.e(QtNative.QtTAG, "setSurfaceGeometry(): surface is null!");
- } else if (m_nativeViews.containsKey(id)) {
- View view = m_nativeViews.get(id);
- if (view != null)
- view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
- else
- Log.e(QtNative.QtTAG, "setSurfaceGeometry(): view is null!");
- } else {
- Log.e(QtNative.QtTAG, "Surface " + id + " not found!");
+ public void removeTopLevelWindow(final int id)
+ {
+ QtNative.runAction(()-> {
+ if (m_topLevelWindows.containsKey(id)) {
+ QtWindow window = m_topLevelWindows.remove(id);
+ if (m_topLevelWindows.isEmpty()) {
+ // Keep last frame in stack until it is replaced to get correct
+ // shutdown transition
+ m_dummyView = window;
+ } else {
+ m_layout.removeView(window);
+ }
}
});
}
@UsedFromNativeCode
- public void destroySurface(int id) {
+ public void bringChildToFront(final int id)
+ {
QtNative.runAction(() -> {
- View view = null;
-
- if (m_surfaces.containsKey(id)) {
- view = m_surfaces.remove(id);
- } else if (m_nativeViews.containsKey(id)) {
- view = m_nativeViews.remove(id);
- } else {
- Log.e(QtNative.QtTAG, "Surface " + id + " not found!");
- }
-
- if (view == null)
- return;
-
- // Keep last frame in stack until it is replaced to get correct
- // shutdown transition
- if (m_surfaces.size() == 0 && m_nativeViews.size() == 0) {
- m_dummyView = view;
- } else {
- m_layout.removeView(view);
+ QtWindow window = m_topLevelWindows.get(id);
+ if (window != null) {
+ m_layout.moveChild(window, m_topLevelWindows.size() - 1);
}
});
}
- public int getSurfaceCount()
- {
- return m_surfaces.size();
- }
-
@UsedFromNativeCode
- public void bringChildToFront(int id)
+ public void bringChildToBack(int id)
{
QtNative.runAction(() -> {
- View view = m_surfaces.get(id);
- if (view != null) {
- final int surfaceCount = getSurfaceCount();
- if (surfaceCount > 0)
- m_layout.moveChild(view, surfaceCount - 1);
- return;
- }
-
- view = m_nativeViews.get(id);
- if (view != null)
- m_layout.moveChild(view, -1);
+ QtWindow window = m_topLevelWindows.get(id);
+ if (window != null)
+ m_layout.moveChild(window, 0);
});
}
- @UsedFromNativeCode
- public void bringChildToBack(int id)
+ private void setActivityBackgroundDrawable()
{
- QtNative.runAction(() -> {
- View view = m_surfaces.get(id);
- if (view != null) {
- m_layout.moveChild(view, 0);
- return;
- }
+ TypedValue attr = new TypedValue();
+ m_activity.getTheme().resolveAttribute(android.R.attr.windowBackground,
+ attr, true);
+ Drawable backgroundDrawable;
+ if (attr.type >= TypedValue.TYPE_FIRST_COLOR_INT &&
+ attr.type <= TypedValue.TYPE_LAST_COLOR_INT) {
+ backgroundDrawable = new ColorDrawable(attr.data);
+ } else {
+ backgroundDrawable = m_activity.getResources().
+ getDrawable(attr.resourceId, m_activity.getTheme());
+ }
- view = m_nativeViews.get(id);
- if (view != null) {
- final int index = getSurfaceCount();
- m_layout.moveChild(view, index);
- }
- });
+ m_activity.getWindow().setBackgroundDrawable(backgroundDrawable);
}
}
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 92050c88855..7682d87d96c 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtSurface.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtSurface.java
@@ -9,6 +9,7 @@ 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,24 +17,33 @@ import android.view.SurfaceView;
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;
- public QtSurface(Context context, int id, boolean onTop, int imageDepth)
+ interface SurfaceChangedCallback {
+ void onSurfaceChanged(Surface surface);
+ }
+
+ public QtSurface(Context context, SurfaceChangedCallback surfaceCallback, int id, boolean onTop,
+ int imageDepth)
{
super(context);
setFocusable(false);
setFocusableInTouchMode(false);
setZOrderMediaOverlay(onTop);
+ m_surfaceCallback = surfaceCallback;
getHolder().addCallback(this);
if (imageDepth == 16)
getHolder().setFormat(PixelFormat.RGB_565);
else
getHolder().setFormat(PixelFormat.RGBA_8888);
- setId(id);
+ m_windowId = id;
m_gestureDetector =
new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
public void onLongPress(MotionEvent event) {
- QtInputDelegate.longPress(getId(), (int) event.getX(), (int) event.getY());
+ QtInputDelegate.longPress(m_windowId, (int) event.getX(), (int) event.getY());
}
});
m_gestureDetector.setIsLongpressEnabled(true);
@@ -49,14 +59,15 @@ class QtSurface extends SurfaceView implements SurfaceHolder.Callback
{
if (width < 1 || height < 1)
return;
-
- QtNative.setSurface(getId(), holder.getSurface());
+ if (m_surfaceCallback != null)
+ m_surfaceCallback.onSurfaceChanged(holder.getSurface());
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
- QtNative.setSurface(getId(), null);
+ if (m_surfaceCallback != null)
+ m_surfaceCallback.onSurfaceChanged(null);
}
@Override
@@ -67,7 +78,7 @@ class QtSurface extends SurfaceView implements SurfaceHolder.Callback
// 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, getId());
+ QtInputDelegate.sendTouchEvent(event, m_windowId);
m_gestureDetector.onTouchEvent(event);
return true;
}
@@ -75,13 +86,13 @@ class QtSurface extends SurfaceView implements SurfaceHolder.Callback
@Override
public boolean onTrackballEvent(MotionEvent event)
{
- QtInputDelegate.sendTrackballEvent(event, getId());
+ QtInputDelegate.sendTrackballEvent(event, m_windowId);
return true;
}
@Override
public boolean onGenericMotionEvent(MotionEvent event)
{
- return QtInputDelegate.sendGenericMotionEvent(event, getId());
+ return QtInputDelegate.sendGenericMotionEvent(event, m_windowId);
}
}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtWindow.java b/src/android/jar/src/org/qtproject/qt/android/QtWindow.java
new file mode 100644
index 00000000000..ba19e8dba16
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt/android/QtWindow.java
@@ -0,0 +1,114 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+package org.qtproject.qt.android;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+import android.view.Surface;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.HashMap;
+
+public class QtWindow extends QtLayout implements QtSurface.SurfaceChangedCallback {
+ private final static String TAG = "QtWindow";
+
+ private QtSurface m_surface;
+ private View m_nativeView;
+ private Handler m_androidHandler;
+
+ private static native void setSurface(int windowId, Surface surface);
+
+ public QtWindow(Context context)
+ {
+ super(context);
+ setId(View.generateViewId());
+ }
+
+ @Override
+ public void onSurfaceChanged(Surface surface)
+ {
+ setSurface(getId(), surface);
+ }
+
+ public void createSurface(final boolean onTop,
+ final int x, final int y, final int w, final int h,
+ final int imageDepth)
+ {
+ QtNative.runAction(new Runnable() {
+ @Override
+ public void run() {
+ if (m_surface != null)
+ removeView(m_surface);
+
+ QtSurface surface = new QtSurface(getContext(),
+ QtWindow.this, QtWindow.this.getId(),
+ onTop, imageDepth);
+ surface.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
+
+ addView(surface, 0);
+ m_surface = surface;
+ }
+ });
+ }
+
+ public void destroySurface()
+ {
+ QtNative.runAction(new Runnable() {
+ @Override
+ public void run() {
+ if (m_surface != null) {
+ removeView(m_surface);
+ m_surface = null;
+ }
+ }
+ });
+ }
+
+ public void setSurfaceGeometry(final int x, final int y, final int w, final int h)
+ {
+ QtNative.runAction(new Runnable() {
+ @Override
+ public void run() {
+ QtLayout.LayoutParams lp = new QtLayout.LayoutParams(w, h, x, y);
+ if (m_surface != null)
+ m_surface.setLayoutParams(lp);
+ else if (m_nativeView != null)
+ m_nativeView.setLayoutParams(lp);
+ }
+ });
+ }
+
+ public void setNativeView(final View view,
+ final int x, final int y, final int w, final int h)
+ {
+ QtNative.runAction(new Runnable() {
+ @Override
+ public void run() {
+ if (m_nativeView != null)
+ removeView(m_nativeView);
+
+ m_nativeView = view;
+ m_nativeView.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
+
+ addView(m_nativeView);
+ }
+ });
+ }
+
+ public void removeNativeView()
+ {
+ QtNative.runAction(new Runnable() {
+ @Override
+ public void run() {
+ if (m_nativeView != null) {
+ removeView(m_nativeView);
+ m_nativeView = null;
+ }
+ }
+ });
+ }
+}
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index fdf4611ff64..d59c170095d 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -70,10 +70,6 @@ static void *m_mainLibraryHnd = nullptr;
static QList<QByteArray> m_applicationParams;
static sem_t m_exitSemaphore, m_terminateSemaphore;
-QHash<int, QAndroidPlatformWindow *> m_surfaces;
-
-Q_CONSTINIT static QBasicMutex m_surfacesMutex;
-
static QAndroidPlatformIntegration *m_androidPlatformIntegration = nullptr;
@@ -319,56 +315,6 @@ namespace QtAndroid
return manufacturer + u' ' + model;
}
- jint generateViewId()
- {
- return QJniObject::callStaticMethod<jint>("android/view/View", "generateViewId", "()I");
- }
-
- int createSurface(QAndroidPlatformWindow *window, const QRect &geometry, bool onTop, int imageDepth)
- {
- QJniEnvironment env;
- if (!env.jniEnv())
- return -1;
-
- m_surfacesMutex.lock();
- jint surfaceId = generateViewId();
- m_surfaces[surfaceId] = window;
- m_surfacesMutex.unlock();
-
- jint x = 0, y = 0, w = -1, h = -1;
- if (!geometry.isNull()) {
- x = geometry.x();
- y = geometry.y();
- w = std::max(geometry.width(), 1);
- h = std::max(geometry.height(), 1);
- }
- qtActivityDelegate().callMethod<void>("createSurface", surfaceId, jboolean(onTop),
- x, y, w, h, imageDepth);
- return surfaceId;
- }
-
- int insertNativeView(QtJniTypes::View view, const QRect &geometry)
- {
- m_surfacesMutex.lock();
- jint surfaceId = generateViewId();
- m_surfaces[surfaceId] = nullptr; // dummy
- m_surfacesMutex.unlock();
-
- jint x = 0, y = 0, w = -1, h = -1;
- if (!geometry.isNull())
- geometry.getRect(&x, &y, &w, &h);
-
- qtActivityDelegate().callMethod<void>("insertNativeView",
- surfaceId,
- view,
- x,
- y,
- qMax(w, 1),
- qMax(h, 1));
-
- return surfaceId;
- }
-
void setViewVisibility(jobject view, bool visible)
{
QJniObject::callStaticMethod<void>(m_applicationClass,
@@ -378,56 +324,6 @@ namespace QtAndroid
visible);
}
- void setSurfaceGeometry(int surfaceId, const QRect &geometry)
- {
- if (surfaceId == -1)
- return;
-
- QJniEnvironment env;
- if (!env.jniEnv())
- return;
- jint x = 0, y = 0, w = -1, h = -1;
- if (!geometry.isNull()) {
- x = geometry.x();
- y = geometry.y();
- w = geometry.width();
- h = geometry.height();
- }
- qtActivityDelegate().callMethod<void>("setSurfaceGeometry", surfaceId, x, y, w, h);
- }
-
-
- void destroySurface(int surfaceId)
- {
- if (surfaceId == -1)
- return;
-
- {
- QMutexLocker lock(&m_surfacesMutex);
- const auto &it = m_surfaces.find(surfaceId);
- if (it != m_surfaces.end())
- m_surfaces.erase(it);
- }
-
- qtActivityDelegate().callMethod<void>("destroySurface", surfaceId);
- }
-
- void bringChildToFront(int surfaceId)
- {
- if (surfaceId == -1)
- return;
-
- qtActivityDelegate().callMethod<void>("bringChildToFront", surfaceId);
- }
-
- void bringChildToBack(int surfaceId)
- {
- if (surfaceId == -1)
- return;
-
- qtActivityDelegate().callMethod<void>("bringChildToBack", surfaceId);
- }
-
bool blockEventLoopsWhenSuspended()
{
static bool block = qEnvironmentVariableIntValue("QT_BLOCK_EVENT_LOOPS_WHEN_SUSPENDED");
@@ -595,21 +491,6 @@ static void terminateQt(JNIEnv *env, jclass /*clazz*/)
sem_post(&m_exitSemaphore);
}
-static void setSurface(JNIEnv *env, jobject thiz, jint id, jobject jSurface)
-{
- Q_UNUSED(env);
- Q_UNUSED(thiz);
-
- QMutexLocker lock(&m_surfacesMutex);
- const auto &it = m_surfaces.find(id);
- if (it == m_surfaces.end())
- return;
-
- auto surfaceClient = it.value();
- if (surfaceClient)
- surfaceClient->onSurfaceChanged(jSurface);
-}
-
static void setDisplayMetrics(JNIEnv * /*env*/, jclass /*clazz*/, jint screenWidthPixels,
jint screenHeightPixels, jint availableLeftPixels,
jint availableTopPixels, jint availableWidthPixels,
@@ -802,7 +683,6 @@ static JNINativeMethod methods[] = {
{ "quitQtCoreApplication", "()V", (void *)quitQtCoreApplication },
{ "terminateQt", "()V", (void *)terminateQt },
{ "waitForServiceSetup", "()V", (void *)waitForServiceSetup },
- { "setSurface", "(ILjava/lang/Object;)V", (void *)setSurface },
{ "updateWindow", "()V", (void *)updateWindow },
{ "updateApplicationState", "(I)V", (void *)updateApplicationState },
{ "onActivityResult", "(IILandroid/content/Intent;)V", (void *)onActivityResult },
@@ -948,7 +828,8 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/)
|| !QtAndroidMenu::registerNatives(env)
|| !QtAndroidAccessibility::registerNatives(env)
|| !QtAndroidDialogHelpers::registerNatives(env)
- || !QAndroidPlatformClipboard::registerNatives(env)) {
+ || !QAndroidPlatformClipboard::registerNatives(env)
+ || !QAndroidPlatformWindow::registerNatives(env)) {
__android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed");
return -1;
}
diff --git a/src/plugins/platforms/android/androidjnimain.h b/src/plugins/platforms/android/androidjnimain.h
index 090e87d7f7b..f65f82d6c3d 100644
--- a/src/plugins/platforms/android/androidjnimain.h
+++ b/src/plugins/platforms/android/androidjnimain.h
@@ -28,7 +28,6 @@ class QBasicMutex;
Q_DECLARE_JNI_CLASS(QtActivityDelegate, "org/qtproject/qt/android/QtActivityDelegate")
Q_DECLARE_JNI_CLASS(QtInputDelegate, "org/qtproject/qt/android/QtInputDelegate")
-Q_DECLARE_JNI_CLASS(View, "android/view/View");
namespace QtAndroid
{
@@ -36,14 +35,7 @@ namespace QtAndroid
QAndroidPlatformIntegration *androidPlatformIntegration();
void setAndroidPlatformIntegration(QAndroidPlatformIntegration *androidPlatformIntegration);
void setQtThread(QThread *thread);
-
- int createSurface(QAndroidPlatformWindow *window, const QRect &geometry, bool onTop, int imageDepth);
- int insertNativeView(QtJniTypes::View view, const QRect &geometry);
void setViewVisibility(jobject view, bool visible);
- void setSurfaceGeometry(int surfaceId, const QRect &geometry);
- void destroySurface(int surfaceId);
- void bringChildToFront(int surfaceId);
- void bringChildToBack(int surfaceId);
QWindow *topLevelWindowAt(const QPoint &globalPos);
int availableWidthPixels();
diff --git a/src/plugins/platforms/android/qandroidplatformforeignwindow.cpp b/src/plugins/platforms/android/qandroidplatformforeignwindow.cpp
index c2ce2c84b2e..0fc83d05c38 100644
--- a/src/plugins/platforms/android/qandroidplatformforeignwindow.cpp
+++ b/src/plugins/platforms/android/qandroidplatformforeignwindow.cpp
@@ -6,12 +6,12 @@
#include <QtCore/qvariant.h>
#include <qpa/qwindowsysteminterface.h>
#include <QtCore/private/qjnihelpers_p.h>
+#include <QtCore/qjnitypes.h>
QT_BEGIN_NAMESPACE
QAndroidPlatformForeignWindow::QAndroidPlatformForeignWindow(QWindow *window, WId nativeHandle)
- : QAndroidPlatformWindow(window),
- m_surfaceId(-1)
+ : QAndroidPlatformWindow(window), m_view(nullptr), m_nativeViewInserted(false)
{
m_view = reinterpret_cast<jobject>(nativeHandle);
if (m_view.isValid())
@@ -22,34 +22,17 @@ QAndroidPlatformForeignWindow::~QAndroidPlatformForeignWindow()
{
if (m_view.isValid())
QtAndroid::setViewVisibility(m_view.object(), false);
- if (m_surfaceId != -1)
- QtAndroid::destroySurface(m_surfaceId);
-}
-
-void QAndroidPlatformForeignWindow::lower()
-{
- if (m_surfaceId == -1)
- return;
-
- QAndroidPlatformWindow::lower();
- QtAndroid::bringChildToBack(m_surfaceId);
-}
-void QAndroidPlatformForeignWindow::raise()
-{
- if (m_surfaceId == -1)
- return;
+ m_nativeQtWindow.callMethod<void>("removeNativeView");
- QAndroidPlatformWindow::raise();
- QtAndroid::bringChildToFront(m_surfaceId);
}
void QAndroidPlatformForeignWindow::setGeometry(const QRect &rect)
{
QAndroidPlatformWindow::setGeometry(rect);
- if (m_surfaceId != -1)
- QtAndroid::setSurfaceGeometry(m_surfaceId, rect);
+ if (m_nativeViewInserted)
+ setSurfaceGeometry(rect);
}
void QAndroidPlatformForeignWindow::setVisible(bool visible)
@@ -60,22 +43,21 @@ void QAndroidPlatformForeignWindow::setVisible(bool visible)
QtAndroid::setViewVisibility(m_view.object(), visible);
QAndroidPlatformWindow::setVisible(visible);
- if (!visible && m_surfaceId != -1) {
- QtAndroid::destroySurface(m_surfaceId);
- m_surfaceId = -1;
- } else if (m_surfaceId == -1) {
- m_surfaceId = QtAndroid::insertNativeView(m_view.object(), geometry());
+ if (!visible && m_nativeViewInserted) {
+ m_nativeQtWindow.callMethod<void>("removeNativeView");
+ m_nativeViewInserted = false;
+ } else if (!m_nativeViewInserted) {
+ addViewToWindow();
}
}
void QAndroidPlatformForeignWindow::applicationStateChanged(Qt::ApplicationState state)
{
- if (state <= Qt::ApplicationHidden
- && m_surfaceId != -1) {
- QtAndroid::destroySurface(m_surfaceId);
- m_surfaceId = -1;
- } else if (m_view.isValid() && m_surfaceId == -1){
- m_surfaceId = QtAndroid::insertNativeView(m_view.object(), geometry());
+ if (state <= Qt::ApplicationHidden && m_nativeViewInserted) {
+ m_nativeQtWindow.callMethod<void>("removeNativeView");
+ m_nativeViewInserted = false;
+ } else if (m_view.isValid() && !m_nativeViewInserted){
+ addViewToWindow();
}
QAndroidPlatformWindow::applicationStateChanged(state);
@@ -86,4 +68,14 @@ void QAndroidPlatformForeignWindow::setParent(const QPlatformWindow *window)
Q_UNUSED(window);
}
+void QAndroidPlatformForeignWindow::addViewToWindow()
+{
+ jint x = 0, y = 0, w = -1, h = -1;
+ if (!geometry().isNull())
+ geometry().getRect(&x, &y, &w, &h);
+
+ m_nativeQtWindow.callMethod<void>("setNativeView", m_view, x, y, qMax(w, 1), qMax(h, 1));
+ m_nativeViewInserted = true;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/qandroidplatformforeignwindow.h b/src/plugins/platforms/android/qandroidplatformforeignwindow.h
index 7ddacda17f0..19588c7ad7e 100644
--- a/src/plugins/platforms/android/qandroidplatformforeignwindow.h
+++ b/src/plugins/platforms/android/qandroidplatformforeignwindow.h
@@ -10,13 +10,13 @@
QT_BEGIN_NAMESPACE
+Q_DECLARE_JNI_CLASS(View, "android/view/View")
+
class QAndroidPlatformForeignWindow : public QAndroidPlatformWindow
{
public:
explicit QAndroidPlatformForeignWindow(QWindow *window, WId nativeHandle);
~QAndroidPlatformForeignWindow();
- void lower() override;
- void raise() override;
void setGeometry(const QRect &rect) override;
void setVisible(bool visible) override;
void applicationStateChanged(Qt::ApplicationState state) override;
@@ -24,8 +24,10 @@ public:
bool isForeignWindow() const override { return true; }
private:
- int m_surfaceId;
- QJniObject m_view;
+ void addViewToWindow();
+
+ QtJniTypes::View m_view;
+ bool m_nativeViewInserted;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp
index 7f2252a4e93..7ffa79e2c1e 100644
--- a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp
+++ b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp
@@ -58,12 +58,14 @@ void QAndroidPlatformOpenGLWindow::setGeometry(const QRect &rect)
EGLSurface QAndroidPlatformOpenGLWindow::eglSurface(EGLConfig config)
{
- if (QAndroidEventDispatcherStopper::stopped() || QGuiApplication::applicationState() == Qt::ApplicationSuspended)
+ if (QAndroidEventDispatcherStopper::stopped() ||
+ QGuiApplication::applicationState() == Qt::ApplicationSuspended || !window()->isTopLevel()) {
return m_eglSurface;
+ }
QMutexLocker lock(&m_surfaceMutex);
- if (m_nativeSurfaceId == -1) {
+ if (!m_surfaceCreated) {
AndroidDeadlockProtector protector;
if (!protector.acquire())
return m_eglSurface;
@@ -83,7 +85,7 @@ EGLSurface QAndroidPlatformOpenGLWindow::eglSurface(EGLConfig config)
bool QAndroidPlatformOpenGLWindow::checkNativeSurface(EGLConfig config)
{
QMutexLocker lock(&m_surfaceMutex);
- if (m_nativeSurfaceId == -1 || !m_androidSurfaceObject.isValid())
+ if (!m_surfaceCreated || !m_androidSurfaceObject.isValid())
return false; // makeCurrent is NOT needed.
createEgl(config);
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp
index 268772e2655..9e20b7ac4bd 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.cpp
+++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp
@@ -132,16 +132,16 @@ QAndroidPlatformScreen::~QAndroidPlatformScreen()
{
}
-QWindow *QAndroidPlatformScreen::topWindow() const
+QWindow *QAndroidPlatformScreen::topVisibleWindow() const
{
for (QAndroidPlatformWindow *w : m_windowStack) {
- if (w->window()->type() == Qt::Window ||
- w->window()->type() == Qt::Popup ||
- w->window()->type() == Qt::Dialog) {
+ Qt::WindowType type = w->window()->type();
+ if (w->window()->isVisible() &&
+ (type == Qt::Window || type == Qt::Popup || type == Qt::Dialog)) {
return w->window();
}
}
- return 0;
+ return nullptr;
}
QWindow *QAndroidPlatformScreen::topLevelAt(const QPoint &p) const
@@ -162,37 +162,34 @@ void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window)
return;
m_windowStack.prepend(window);
+ QtAndroid::qtActivityDelegate().callMethod<void>("addTopLevelWindow", window->nativeWindow());
- QWindow *w = topWindow();
- QWindowSystemInterface::handleFocusWindowChanged(w, Qt::ActiveWindowFocusReason);
- topWindowChanged(w);
+ if (window->window()->isVisible())
+ topVisibleWindowChanged();
}
void QAndroidPlatformScreen::removeWindow(QAndroidPlatformWindow *window)
{
- if (window->parent() && window->isRaster())
- return;
-
m_windowStack.removeOne(window);
if (m_windowStack.contains(window))
qWarning() << "Failed to remove window";
- QWindow *w = topWindow();
- QWindowSystemInterface::handleFocusWindowChanged(w, Qt::ActiveWindowFocusReason);
- topWindowChanged(w);
+ QtAndroid::qtActivityDelegate().callMethod<void>("removeTopLevelWindow", window->nativeViewId());
+
+ topVisibleWindowChanged();
}
void QAndroidPlatformScreen::raise(QAndroidPlatformWindow *window)
{
int index = m_windowStack.indexOf(window);
- if (index <= 0)
+ if (index < 0)
return;
- m_windowStack.move(index, 0);
-
- QWindow *w = topWindow();
- QWindowSystemInterface::handleFocusWindowChanged(w, Qt::ActiveWindowFocusReason);
- topWindowChanged(w);
+ if (index > 0) {
+ m_windowStack.move(index, 0);
+ QtAndroid::qtActivityDelegate().callMethod<void>("bringChildToFront", window->nativeViewId());
+ }
+ topVisibleWindowChanged();
}
void QAndroidPlatformScreen::lower(QAndroidPlatformWindow *window)
@@ -201,10 +198,9 @@ void QAndroidPlatformScreen::lower(QAndroidPlatformWindow *window)
if (index == -1 || index == (m_windowStack.size() - 1))
return;
m_windowStack.move(index, m_windowStack.size() - 1);
+ QtAndroid::qtActivityDelegate().callMethod<void>("bringChildToBack", window->nativeViewId());
- QWindow *w = topWindow();
- QWindowSystemInterface::handleFocusWindowChanged(w, Qt::ActiveWindowFocusReason);
- topWindowChanged(w);
+ topVisibleWindowChanged();
}
void QAndroidPlatformScreen::setPhysicalSize(const QSize &size)
@@ -284,13 +280,14 @@ void QAndroidPlatformScreen::applicationStateChanged(Qt::ApplicationState state)
w->applicationStateChanged(state);
}
-void QAndroidPlatformScreen::topWindowChanged(QWindow *w)
+void QAndroidPlatformScreen::topVisibleWindowChanged()
{
+ QWindow *w = topVisibleWindow();
+ QWindowSystemInterface::handleFocusWindowChanged(w, Qt::ActiveWindowFocusReason);
QtAndroidMenu::setActiveTopLevelWindow(w);
-
- if (w != 0) {
+ if (w && w->handle()) {
QAndroidPlatformWindow *platformWindow = static_cast<QAndroidPlatformWindow *>(w->handle());
- if (platformWindow != 0)
+ if (platformWindow)
platformWindow->updateSystemUiVisibility();
}
}
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.h b/src/plugins/platforms/android/qandroidplatformscreen.h
index 0e2f788886b..e7ce6ed59f0 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.h
+++ b/src/plugins/platforms/android/qandroidplatformscreen.h
@@ -37,7 +37,7 @@ public:
int currentMode() const override { return m_currentMode; }
int preferredMode() const override { return m_currentMode; }
qreal refreshRate() const override { return m_refreshRate; }
- inline QWindow *topWindow() const;
+ inline QWindow *topVisibleWindow() const;
QWindow *topLevelAt(const QPoint & p) const override;
void addWindow(QAndroidPlatformWindow *window);
@@ -45,7 +45,7 @@ public:
void raise(QAndroidPlatformWindow *window);
void lower(QAndroidPlatformWindow *window);
- void topWindowChanged(QWindow *w);
+ void topVisibleWindowChanged();
int displayId() const override;
public slots:
@@ -60,7 +60,6 @@ public slots:
protected:
typedef QList<QAndroidPlatformWindow *> WindowStackType;
WindowStackType m_windowStack;
-
QRect m_availableGeometry;
int m_depth;
QImage::Format m_format;
diff --git a/src/plugins/platforms/android/qandroidplatformvulkanwindow.cpp b/src/plugins/platforms/android/qandroidplatformvulkanwindow.cpp
index df87240c2b0..43b3a903734 100644
--- a/src/plugins/platforms/android/qandroidplatformvulkanwindow.cpp
+++ b/src/plugins/platforms/android/qandroidplatformvulkanwindow.cpp
@@ -94,7 +94,7 @@ VkSurfaceKHR *QAndroidPlatformVulkanWindow::vkSurface()
clearSurface();
QMutexLocker lock(&m_surfaceMutex);
- if (m_nativeSurfaceId == -1) {
+ if (!m_surfaceCreated) {
AndroidDeadlockProtector protector;
if (!protector.acquire())
return &m_vkSurface;
@@ -102,7 +102,7 @@ VkSurfaceKHR *QAndroidPlatformVulkanWindow::vkSurface()
m_surfaceWaitCondition.wait(&m_surfaceMutex);
}
- if (m_nativeSurfaceId == -1 || !m_androidSurfaceObject.isValid())
+ if (!m_surfaceCreated || !m_androidSurfaceObject.isValid())
return &m_vkSurface;
QJniEnvironment env;
diff --git a/src/plugins/platforms/android/qandroidplatformwindow.cpp b/src/plugins/platforms/android/qandroidplatformwindow.cpp
index 23b83834d45..1e30799ae45 100644
--- a/src/plugins/platforms/android/qandroidplatformwindow.cpp
+++ b/src/plugins/platforms/android/qandroidplatformwindow.cpp
@@ -14,11 +14,15 @@
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window")
+
Q_CONSTINIT static QBasicAtomicInt winIdGenerator = Q_BASIC_ATOMIC_INITIALIZER(0);
QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window)
- : QPlatformWindow(window), m_androidSurfaceObject(nullptr)
+ : QPlatformWindow(window), m_nativeQtWindow(QNativeInterface::QAndroidApplication::context()),
+ m_androidSurfaceObject(nullptr)
{
+ m_nativeViewId = m_nativeQtWindow.callMethod<jint>("getId");
m_windowFlags = Qt::Widget;
m_windowState = Qt::WindowNoState;
// the surfaceType is overwritten in QAndroidPlatformOpenGLWindow ctor so let's save
@@ -44,8 +48,15 @@ QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window)
if (requestedNativeGeometry != finalNativeGeometry)
setGeometry(finalNativeGeometry);
}
+ platformScreen()->addWindow(this);
+}
+
+QAndroidPlatformWindow::~QAndroidPlatformWindow()
+{
+ platformScreen()->removeWindow(this);
}
+
void QAndroidPlatformWindow::lower()
{
platformScreen()->lower(this);
@@ -76,23 +87,19 @@ void QAndroidPlatformWindow::setGeometry(const QRect &rect)
void QAndroidPlatformWindow::setVisible(bool visible)
{
- if (visible)
- updateSystemUiVisibility();
-
if (visible) {
+ updateSystemUiVisibility();
if ((m_windowState & Qt::WindowFullScreen)
|| ((m_windowState & Qt::WindowMaximized) && (window()->flags() & Qt::MaximizeUsingFullscreenGeometryHint))) {
setGeometry(platformScreen()->geometry());
} else if (m_windowState & Qt::WindowMaximized) {
setGeometry(platformScreen()->availableGeometry());
}
+ requestActivateWindow();
+ } else if (window() == qGuiApp->focusWindow()) {
+ platformScreen()->topVisibleWindowChanged();
}
- if (visible)
- platformScreen()->addWindow(this);
- else
- platformScreen()->removeWindow(this);
-
QRect availableGeometry = screen()->availableGeometry();
if (geometry().width() > 0 && geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0)
QPlatformWindow::setVisible(visible);
@@ -125,7 +132,14 @@ Qt::WindowFlags QAndroidPlatformWindow::windowFlags() const
void QAndroidPlatformWindow::setParent(const QPlatformWindow *window)
{
- Q_UNUSED(window);
+ // even though we do not yet support child windows properly, any windows getting a parent
+ // should be removed from screen's window stack which is only for top level windows,
+ // and respectively any window becoming top level should go in there
+ if (window) {
+ platformScreen()->removeWindow(this);
+ } else {
+ platformScreen()->addWindow(this);
+ }
}
QAndroidPlatformScreen *QAndroidPlatformWindow::platformScreen() const
@@ -140,7 +154,8 @@ void QAndroidPlatformWindow::propagateSizeHints()
void QAndroidPlatformWindow::requestActivateWindow()
{
- platformScreen()->topWindowChanged(window());
+ if (!blockedByModal())
+ raise();
}
void QAndroidPlatformWindow::updateSystemUiVisibility()
@@ -176,25 +191,62 @@ void QAndroidPlatformWindow::applicationStateChanged(Qt::ApplicationState)
void QAndroidPlatformWindow::createSurface()
{
+ const QRect rect = geometry();
+ jint x = 0, y = 0, w = -1, h = -1;
+ if (!rect.isNull()) {
+ x = rect.x();
+ y = rect.y();
+ w = std::max(rect.width(), 1);
+ h = std::max(rect.height(), 1);
+ }
+
const bool windowStaysOnTop = bool(window()->flags() & Qt::WindowStaysOnTopHint);
- m_nativeSurfaceId = QtAndroid::createSurface(this, geometry(), windowStaysOnTop, 32);
+
+ m_nativeQtWindow.callMethod<void>("createSurface", windowStaysOnTop, x, y, w, h, 32);
+ m_surfaceCreated = true;
}
void QAndroidPlatformWindow::destroySurface()
{
- if (m_nativeSurfaceId != -1) {
- QtAndroid::destroySurface(m_nativeSurfaceId);
- m_nativeSurfaceId = -1;
+ if (m_surfaceCreated) {
+ m_nativeQtWindow.callMethod<void>("destroySurface");
+ m_surfaceCreated = false;
}
}
-void QAndroidPlatformWindow::setSurfaceGeometry(const QRect &rect)
+void QAndroidPlatformWindow::setSurfaceGeometry(const QRect &geometry)
{
- if (m_nativeSurfaceId != -1)
- QtAndroid::setSurfaceGeometry(m_nativeSurfaceId, rect);
+ if (!m_surfaceCreated)
+ return;
+
+ jint x = 0;
+ jint y = 0;
+ jint w = -1;
+ jint h = -1;
+ if (!geometry.isNull()) {
+ x = geometry.x();
+ y = geometry.y();
+ w = geometry.width();
+ h = geometry.height();
+ }
+ m_nativeQtWindow.callMethod<void>("setSurfaceGeometry", x, y, w, h);
}
-void QAndroidPlatformWindow::sendExpose()
+void QAndroidPlatformWindow::onSurfaceChanged(QtJniTypes::Surface surface)
+{
+ lockSurface();
+ m_androidSurfaceObject = surface;
+ if (m_androidSurfaceObject.isValid()) // wait until we have a valid surface to draw into
+ m_surfaceWaitCondition.wakeOne();
+ unlockSurface();
+
+ if (m_androidSurfaceObject.isValid()) {
+ // repaint the window, when we have a valid surface
+ sendExpose();
+ }
+}
+
+void QAndroidPlatformWindow::sendExpose() const
{
QRect availableGeometry = screen()->availableGeometry();
if (!geometry().isNull() && !availableGeometry.isNull()) {
@@ -203,15 +255,41 @@ void QAndroidPlatformWindow::sendExpose()
}
}
-void QAndroidPlatformWindow::onSurfaceChanged(QtJniTypes::Surface surface)
+bool QAndroidPlatformWindow::blockedByModal() const
{
- lockSurface();
- m_androidSurfaceObject = surface;
- if (m_androidSurfaceObject.isValid())
- m_surfaceWaitCondition.wakeOne();
- unlockSurface();
- if (m_androidSurfaceObject.isValid())
- sendExpose();
+ QWindow *modalWindow = QGuiApplication::modalWindow();
+ return modalWindow && modalWindow != window();
+}
+
+void QAndroidPlatformWindow::setSurface(JNIEnv *env, jobject object, jint windowId,
+ QtJniTypes::Surface surface)
+{
+ Q_UNUSED(env)
+ Q_UNUSED(object)
+
+ if (!qGuiApp)
+ return;
+
+ const QList<QWindow*> windows = qGuiApp->allWindows();
+ for (QWindow * window : windows) {
+ if (!window->handle())
+ continue;
+ QAndroidPlatformWindow *platformWindow =
+ static_cast<QAndroidPlatformWindow *>(window->handle());
+ if (platformWindow->nativeViewId() == windowId)
+ platformWindow->onSurfaceChanged(surface);
+ }
+}
+
+bool QAndroidPlatformWindow::registerNatives(QJniEnvironment &env)
+{
+ if (!env.registerNativeMethods(QtJniTypes::Traits<QtJniTypes::QtWindow>::className(),
+ {Q_JNI_NATIVE_SCOPED_METHOD(setSurface, QAndroidPlatformWindow)})) {
+ qCCritical(lcQpaWindow) << "RegisterNatives failed for"
+ << QtJniTypes::Traits<QtJniTypes::QtWindow>::className();
+ return false;
+ }
+ return true;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/qandroidplatformwindow.h b/src/plugins/platforms/android/qandroidplatformwindow.h
index a676ef1dd3b..88949d84daa 100644
--- a/src/plugins/platforms/android/qandroidplatformwindow.h
+++ b/src/plugins/platforms/android/qandroidplatformwindow.h
@@ -17,6 +17,8 @@
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcQpaWindow)
+Q_DECLARE_JNI_CLASS(QtWindow, "org/qtproject/qt/android/QtWindow")
Q_DECLARE_JNI_CLASS(Surface, "android/view/Surface")
class QAndroidPlatformScreen;
@@ -25,7 +27,7 @@ class QAndroidPlatformWindow: public QPlatformWindow
{
public:
explicit QAndroidPlatformWindow(QWindow *window);
-
+ ~QAndroidPlatformWindow();
void lower() override;
void raise() override;
@@ -49,9 +51,12 @@ public:
void updateSystemUiVisibility();
inline bool isRaster() const { return m_isRaster; }
bool isExposed() const override;
+ QtJniTypes::QtWindow nativeWindow() const { return m_nativeQtWindow; }
virtual void applicationStateChanged(Qt::ApplicationState);
+ int nativeViewId() const { return m_nativeViewId; }
+ static bool registerNatives(QJniEnvironment &env);
void onSurfaceChanged(QtJniTypes::Surface surface);
protected:
@@ -60,20 +65,27 @@ protected:
void unlockSurface() { m_surfaceMutex.unlock(); }
void createSurface();
void destroySurface();
- void setSurfaceGeometry(const QRect &rect);
- void sendExpose();
+ void setSurfaceGeometry(const QRect &geometry);
+ void sendExpose() const;
+ bool blockedByModal() const;
-protected:
Qt::WindowFlags m_windowFlags;
Qt::WindowStates m_windowState;
bool m_isRaster;
WId m_windowId;
+
+ QtJniTypes::QtWindow m_nativeQtWindow;
// The Android Surface, accessed from multiple threads, guarded by m_surfaceMutex
QtJniTypes::Surface m_androidSurfaceObject;
QWaitCondition m_surfaceWaitCondition;
- int m_nativeSurfaceId = -1;
+ int m_nativeViewId = -1;
+ bool m_surfaceCreated = false;
QMutex m_surfaceMutex;
+
+private:
+ static void setSurface(JNIEnv *env, jobject obj, jint windowId, QtJniTypes::Surface surface);
+ Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(setSurface)
};
QT_END_NAMESPACE