Android: Add Foreign Window support

Change-Id: Ie41edd3f17214805673311a375191cd93d2378f6
Reviewed-by: BogDan Vatra <bogdan@kde.org>
bb10
Christian Strømme 2014-02-04 11:30:00 +01:00 committed by The Qt Project
parent 4ce43b565f
commit 539196689e
8 changed files with 213 additions and 8 deletions

View File

@ -107,6 +107,7 @@ public class QtActivityDelegate
private boolean m_fullScreen = false;
private boolean m_started = false;
private HashMap<Integer, QtSurface> m_surfaces = null;
private HashMap<Integer, View> 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<Integer, QtSurface>();
m_nativeViews = new HashMap<Integer, View>();
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!");
}
}
}

View File

@ -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() {

View File

@ -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

View File

@ -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");

View File

@ -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);

View File

@ -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 <QtCore/qvariant.h>
QAndroidPlatformForeignWindow::QAndroidPlatformForeignWindow(QWindow *window)
: QAndroidPlatformWindow(window)
{
const WId wId = window->property("_q_foreignWinId").value<WId>();
if (wId) {
m_view = reinterpret_cast<jobject>(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);
}

View File

@ -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 <QtCore/private/qjni_p.h>
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

View File

@ -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);