From 539196689e806f8c175bb50343a4dc2cab52e838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Tue, 4 Feb 2014 11:30:00 +0100 Subject: Android: Add Foreign Window support Change-Id: Ie41edd3f17214805673311a375191cd93d2378f6 Reviewed-by: BogDan Vatra --- .../qtproject/qt5/android/QtActivityDelegate.java | 37 ++++++++++-- .../src/org/qtproject/qt5/android/QtNative.java | 11 ++++ src/plugins/platforms/android/android.pro | 6 +- src/plugins/platforms/android/androidjnimain.cpp | 29 +++++++++ src/plugins/platforms/android/androidjnimain.h | 1 + .../android/qandroidplatformforeignwindow.cpp | 70 ++++++++++++++++++++++ .../android/qandroidplatformforeignwindow.h | 61 +++++++++++++++++++ .../android/qandroidplatformintegration.cpp | 6 +- 8 files changed, 213 insertions(+), 8 deletions(-) create mode 100644 src/plugins/platforms/android/qandroidplatformforeignwindow.cpp create mode 100644 src/plugins/platforms/android/qandroidplatformforeignwindow.h diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index 6c71bed7bc..356c096a9a 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -107,6 +107,7 @@ public class QtActivityDelegate private boolean m_fullScreen = false; private boolean m_started = false; private HashMap m_surfaces = null; + private HashMap m_nativeViews = null; private QtLayout m_layout = null; private QtEditText m_editText = null; private InputMethodManager m_imm = null; @@ -648,6 +649,7 @@ public class QtActivityDelegate m_editText = new QtEditText(m_activity, this); m_imm = (InputMethodManager)m_activity.getSystemService(Context.INPUT_METHOD_SERVICE); m_surfaces = new HashMap(); + m_nativeViews = new HashMap(); m_activity.setContentView(m_layout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); @@ -955,6 +957,22 @@ public class QtActivityDelegate } } + public void insertNativeView(int id, View view, int x, int y, int w, int h) { + 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)); + } + + m_layout.addView(view); + m_layout.bringChildToFront(view); + m_nativeViews.put(id, view); + } + public void createSurface(int id, boolean onTop, int x, int y, int w, int h) { if (m_surfaces.containsKey(id)) m_layout.removeView(m_surfaces.remove(id)); @@ -974,19 +992,28 @@ public class QtActivityDelegate } public void setSurfaceGeometry(int id, int x, int y, int w, int h) { - if (!m_surfaces.containsKey(id)) { + if (m_surfaces.containsKey(id)) { + QtSurface surface = m_surfaces.get(id); + surface.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y)); + } else if (m_nativeViews.containsKey(id)) { + View view = m_nativeViews.get(id); + view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y)); + m_layout.bringChildToFront(view); + } else { Log.e(QtNative.QtTAG, "Surface " + id +" not found!"); return; } - QtSurface surface = m_surfaces.get(id); - surface.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y)); + m_layout.requestLayout(); } public void destroySurface(int id) { - if (m_surfaces.containsKey(id)) + if (m_surfaces.containsKey(id)) { m_layout.removeView(m_surfaces.remove(id)); - else + } else if (m_nativeViews.containsKey(id)) { + m_layout.removeView(m_nativeViews.remove(id)); + } else { Log.e(QtNative.QtTAG, "Surface " + id +" not found!"); + } } } diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java index 2437752545..81d70ddc9a 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java @@ -55,6 +55,7 @@ import android.util.Log; import android.view.ContextMenu; import android.view.Menu; import android.view.MotionEvent; +import android.view.View; import java.security.KeyStore; import java.security.cert.X509Certificate; @@ -520,6 +521,16 @@ public class QtNative }); } + private static void insertNativeView(final int id, final View view, final int x, final int y, final int w, final int h) + { + runAction(new Runnable() { + @Override + public void run() { + m_activityDelegate.insertNativeView(id, view, x, y, w, h); + } + }); + } + private static void setSurfaceGeometry(final int id, final int x, final int y, final int w, final int h) { runAction(new Runnable() { diff --git a/src/plugins/platforms/android/android.pro b/src/plugins/platforms/android/android.pro index 4d873dd986..243eea071a 100644 --- a/src/plugins/platforms/android/android.pro +++ b/src/plugins/platforms/android/android.pro @@ -47,7 +47,8 @@ SOURCES += $$PWD/androidplatformplugin.cpp \ $$PWD/qandroidplatformopenglwindow.cpp \ $$PWD/qandroidplatformrasterwindow.cpp \ $$PWD/qandroidplatformbackingstore.cpp \ - $$PWD/qandroidplatformopenglcontext.cpp + $$PWD/qandroidplatformopenglcontext.cpp \ + $$PWD/qandroidplatformforeignwindow.cpp HEADERS += $$PWD/qandroidplatformintegration.h \ $$PWD/androidjnimain.h \ @@ -73,7 +74,8 @@ HEADERS += $$PWD/qandroidplatformintegration.h \ $$PWD/qandroidplatformopenglwindow.h \ $$PWD/qandroidplatformrasterwindow.h \ $$PWD/qandroidplatformbackingstore.h \ - $$PWD/qandroidplatformopenglcontext.h + $$PWD/qandroidplatformopenglcontext.h \ + $$PWD/qandroidplatformforeignwindow.h #Non-standard install directory, QTBUG-29859 DESTDIR = $$DESTDIR/android diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 76129319c5..337e7419aa 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -84,6 +84,7 @@ static AAssetManager *m_assetManager = NULL; static jobject m_resourcesObj; static jobject m_activityObject = NULL; static jmethodID m_createSurfaceMethodID = 0; +static jmethodID m_insertNativeViewMethodID = 0; static jmethodID m_setSurfaceGeometryMethodID = 0; static jmethodID m_destroySurfaceMethodID = 0; @@ -359,6 +360,33 @@ namespace QtAndroid return surfaceId; } + int insertNativeView(jobject view, const QRect &geometry) + { + QJNIEnvironmentPrivate env; + if (!env) + return 0; + + m_surfacesMutex.lock(); + const int surfaceId = m_surfaceId++; + 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); + } + + env->CallStaticVoidMethod(m_applicationClass, + m_insertNativeViewMethodID, + surfaceId, + view, + x, y, w, h); + + return surfaceId; + } + void setSurfaceGeometry(int surfaceId, const QRect &geometry) { QJNIEnvironmentPrivate env; @@ -653,6 +681,7 @@ static int registerNatives(JNIEnv *env) } GET_AND_CHECK_STATIC_METHOD(m_createSurfaceMethodID, m_applicationClass, "createSurface", "(IZIIII)V"); + GET_AND_CHECK_STATIC_METHOD(m_insertNativeViewMethodID, m_applicationClass, "insertNativeView", "(ILandroid/view/View;IIII)V"); GET_AND_CHECK_STATIC_METHOD(m_setSurfaceGeometryMethodID, m_applicationClass, "setSurfaceGeometry", "(IIIII)V"); GET_AND_CHECK_STATIC_METHOD(m_destroySurfaceMethodID, m_applicationClass, "destroySurface", "(I)V"); diff --git a/src/plugins/platforms/android/androidjnimain.h b/src/plugins/platforms/android/androidjnimain.h index eb8dd87ae0..eb604c8da8 100644 --- a/src/plugins/platforms/android/androidjnimain.h +++ b/src/plugins/platforms/android/androidjnimain.h @@ -67,6 +67,7 @@ namespace QtAndroid int createSurface(AndroidSurfaceClient * client, const QRect &geometry, bool onTop); + int insertNativeView(jobject view, const QRect &geometry); void setSurfaceGeometry(int surfaceId, const QRect &geometry); void destroySurface(int surfaceId); diff --git a/src/plugins/platforms/android/qandroidplatformforeignwindow.cpp b/src/plugins/platforms/android/qandroidplatformforeignwindow.cpp new file mode 100644 index 0000000000..e6f9acb2c9 --- /dev/null +++ b/src/plugins/platforms/android/qandroidplatformforeignwindow.cpp @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qandroidplatformforeignwindow.h" +#include "androidjnimain.h" +#include + +QAndroidPlatformForeignWindow::QAndroidPlatformForeignWindow(QWindow *window) + : QAndroidPlatformWindow(window) +{ + const WId wId = window->property("_q_foreignWinId").value(); + if (wId) { + m_view = reinterpret_cast(wId); + Q_ASSERT(m_view.isValid()); + m_surfaceId = QtAndroid::insertNativeView(m_view.object(), geometry()); + } +} + +QAndroidPlatformForeignWindow::~QAndroidPlatformForeignWindow() +{ + if (m_surfaceId != -1) + QtAndroid::destroySurface(m_surfaceId); +} + +void QAndroidPlatformForeignWindow::setGeometry(const QRect &rect) +{ + if (rect == geometry()) + return; + + QAndroidPlatformWindow::setGeometry(rect); + QtAndroid::setSurfaceGeometry(m_surfaceId, rect); +} diff --git a/src/plugins/platforms/android/qandroidplatformforeignwindow.h b/src/plugins/platforms/android/qandroidplatformforeignwindow.h new file mode 100644 index 0000000000..88c87d0540 --- /dev/null +++ b/src/plugins/platforms/android/qandroidplatformforeignwindow.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QANDROIDPLATFORMFOREIGNWINDOW_H +#define QANDROIDPLATFORMFOREIGNWINDOW_H + +#include "androidsurfaceclient.h" +#include "qandroidplatformwindow.h" +#include + +class QAndroidPlatformForeignWindow : public QAndroidPlatformWindow +{ +public: + explicit QAndroidPlatformForeignWindow(QWindow *window); + ~QAndroidPlatformForeignWindow(); + void setGeometry(const QRect &rect); + +private: + QJNIObjectPrivate m_view; + int m_surfaceId = -1; +}; + +#endif // QANDROIDPLATFORMFOREIGNWINDOW_H diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp index 3dc8632374..5848e94aca 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp @@ -64,6 +64,7 @@ #include "qandroidplatformscreen.h" #include "qandroidplatformtheme.h" #include "qandroidsystemlocale.h" +#include "qandroidplatformforeignwindow.h" QT_BEGIN_NAMESPACE @@ -148,6 +149,7 @@ bool QAndroidPlatformIntegration::hasCapability(Capability cap) const case ApplicationState: return true; case NativeWidgets: return true; case OpenGL: return true; + case ForeignWindows: return true; case ThreadedOpenGL: if (needsWorkaround()) return false; @@ -174,7 +176,9 @@ QPlatformOpenGLContext *QAndroidPlatformIntegration::createPlatformOpenGLContext QPlatformWindow *QAndroidPlatformIntegration::createPlatformWindow(QWindow *window) const { - if (window->surfaceType() == QSurface::RasterSurface) + if (window->type() == Qt::ForeignWindow) + return new QAndroidPlatformForeignWindow(window); + else if (window->surfaceType() == QSurface::RasterSurface) return new QAndroidPlatformRasterWindow(window); else return new QAndroidPlatformOpenGLWindow(window, m_eglDisplay); -- cgit v1.2.3