Support multiple native surfaces on Android.

Support for multiple native surfaces is needed by applications that need
to mix raster windows with GL windows.
Rework the raster and opengl implementation, get rid of eglfs and
fbconvenience dependencies.
Create a single android platform plugin.

[ChangeLog][Android] Rework the raster and opengl implementation.
[ChangeLog][Android] Create a single android platform plugin.

Task-number: QTBUG-34650

Change-Id: I9b1ab51554823329dda8cfbf8fef27c38f917c7b
Reviewed-by: Paul Olav Tvete <paul.tvete@digia.com>
This commit is contained in:
BogDan Vatra 2014-01-17 10:31:27 +02:00 committed by The Qt Project
parent 338f4c9246
commit 8a9bd001c9
67 changed files with 1395 additions and 1309 deletions

View File

@ -1,4 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="org.qtproject.qt5.android">
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<uses-sdk android:minSdkVersion="9" />
</manifest>

View File

@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Android port of the Qt Toolkit.
@ -73,6 +73,7 @@ import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
public class QtActivityDelegate
@ -105,7 +106,7 @@ public class QtActivityDelegate
private int m_lastChar = 0;
private boolean m_fullScreen = false;
private boolean m_started = false;
private QtSurface m_surface = null;
private HashMap<Integer, QtSurface> m_surfaces = null;
private QtLayout m_layout = null;
private QtEditText m_editText = null;
private InputMethodManager m_imm = null;
@ -116,21 +117,6 @@ public class QtActivityDelegate
public boolean m_backKeyPressedSent = false;
public QtLayout getQtLayout()
{
return m_layout;
}
public QtSurface getQtSurface()
{
return m_surface;
}
public void redrawWindow(int left, int top, int right, int bottom)
{
m_surface.drawBitmap(new Rect(left, top, right, bottom));
}
public void setFullScreen(boolean enterFullScreen)
{
if (m_fullScreen == enterFullScreen)
@ -175,6 +161,7 @@ public class QtActivityDelegate
}
}
}
m_layout.requestLayout();
}
@ -233,7 +220,8 @@ public class QtActivityDelegate
{
if (m_imm == null)
return;
if (height > m_surface.getHeight()*2/3)
if (height > m_layout.getHeight() * 2 / 3)
m_activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
else
m_activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
@ -330,7 +318,7 @@ public class QtActivityDelegate
{
if (m_imm == null)
return;
m_imm.hideSoftInputFromWindow(m_editText.getWindowToken(), 0, new ResultReceiver( new Handler()){
m_imm.hideSoftInputFromWindow(m_editText.getWindowToken(), 0, new ResultReceiver(new Handler()) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
switch (resultCode) {
@ -358,7 +346,7 @@ public class QtActivityDelegate
if (size < 36 || size > 512) { // check size sanity
DisplayMetrics metrics = new DisplayMetrics();
a.getWindowManager().getDefaultDisplay().getMetrics(metrics);
size = metrics.densityDpi/10*3;
size = metrics.densityDpi / 10 * 3;
if (size < 36)
size = 36;
@ -626,13 +614,13 @@ public class QtActivityDelegate
m_applicationParameters += "\t-qmljsdebugger=" + qmljsdebugger;
}
if (null == m_surface)
if (null == m_surfaces)
onCreate(null);
String nativeLibraryDir = QtNativeLibrariesDir.nativeLibrariesDir(m_activity);
m_surface.applicationStarted( QtNative.startApplication(m_applicationParameters,
QtNative.startApplication(m_applicationParameters,
m_environmentVariables,
m_mainLib,
nativeLibraryDir));
nativeLibraryDir);
m_started = true;
return true;
} catch (Exception e) {
@ -657,14 +645,12 @@ public class QtActivityDelegate
metrics.xdpi, metrics.ydpi, metrics.scaledDensity);
}
m_layout = new QtLayout(m_activity);
m_surface = new QtSurface(m_activity, 0);
m_editText = new QtEditText(m_activity, this);
m_imm = (InputMethodManager)m_activity.getSystemService(Context.INPUT_METHOD_SERVICE);
m_layout.addView(m_surface, 0);
m_surfaces = new HashMap<Integer, QtSurface>();
m_activity.setContentView(m_layout,
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT));
m_layout.bringChildToFront(m_surface);
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
m_activity.registerForContextMenu(m_layout);
int orientation = m_activity.getResources().getConfiguration().orientation;
@ -704,18 +690,6 @@ public class QtActivityDelegate
}
}
public void onRestoreInstanceState(Bundle savedInstanceState)
{
try {
m_super_onRestoreInstanceState.invoke(m_activity, savedInstanceState);
} catch (Exception e) {
e.printStackTrace();
}
m_started = savedInstanceState.getBoolean("Started");
if (m_started)
m_surface.applicationStarted(true);
}
public void onPause()
{
QtNative.updateApplicationState(ApplicationInactive);
@ -768,6 +742,19 @@ public class QtActivityDelegate
}
outState.putBoolean("FullScreen", m_fullScreen);
outState.putBoolean("Started", m_started);
// It should never
}
public void onRestoreInstanceState(Bundle savedInstanceState)
{
try {
m_super_onRestoreInstanceState.invoke(m_activity, savedInstanceState);
} catch (Exception e) {
e.printStackTrace();
}
m_started = savedInstanceState.getBoolean("Started");
// FIXME restore all surfaces
}
public boolean onKeyDown(int keyCode, KeyEvent event)
@ -967,4 +954,39 @@ public class QtActivityDelegate
}
}
}
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));
QtSurface surface = new QtSurface(m_activity, id, onTop);
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));
}
m_layout.addView(surface);
if (onTop)
m_layout.bringChildToFront(surface);
m_surfaces.put(id, surface);
}
public void setSurfaceGeometry(int id, int x, int y, int w, int h) {
if (!m_surfaces.containsKey(id)) {
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))
m_layout.removeView(m_surfaces.remove(id));
else
Log.e(QtNative.QtTAG, "Surface " + id +" not found!");
}
}

View File

@ -42,8 +42,10 @@
package org.qtproject.qt5.android;
import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewGroup;
@ -64,6 +66,15 @@ public class QtLayout extends ViewGroup
super(context, attrs, defStyle);
}
@Override
protected void onSizeChanged (int w, int h, int oldw, int oldh)
{
DisplayMetrics metrics = new DisplayMetrics();
((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(metrics);
QtNative.setApplicationDisplayMetrics(metrics.widthPixels,
metrics.heightPixels, w, h, metrics.xdpi, metrics.ydpi, metrics.scaledDensity);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{

View File

@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Android port of the Qt Toolkit.
@ -250,29 +250,10 @@ public class QtNative
}
}
public static void pauseApplication()
{
synchronized (m_mainActivityMutex) {
if (m_started)
pauseQtApp();
}
}
public static void resumeApplication()
{
synchronized (m_mainActivityMutex) {
if (m_started) {
resumeQtApp();
updateWindow();
}
}
}
// application methods
public static native void startQtApplication(String params, String env);
public static native void startQtApp(String params, String env);
public static native void pauseQtApp();
public static native void resumeQtApp();
public static native boolean startQtAndroidPlugin();
public static native void quitQtAndroidPlugin();
public static native void terminateQt();
@ -283,16 +264,6 @@ public class QtNative
m_activity.finish();
}
private static void redrawSurface(final int left, final int top, final int right, final int bottom )
{
runAction(new Runnable() {
@Override
public void run() {
m_activityDelegate.redrawWindow(left, top, right, bottom);
}
});
}
//@ANDROID-9
static private int getAction(int index, MotionEvent event)
{
@ -539,6 +510,36 @@ public class QtNative
return certificateArray;
}
private static void createSurface(final int id, final boolean onTop, final int x, final int y, final int w, final int h)
{
runAction(new Runnable() {
@Override
public void run() {
m_activityDelegate.createSurface(id, onTop, 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() {
@Override
public void run() {
m_activityDelegate.setSurfaceGeometry(id, x, y, w, h);
}
});
}
private static void destroySurface(final int id)
{
runAction(new Runnable() {
@Override
public void run() {
m_activityDelegate.destroySurface(id);
}
});
}
// screen methods
public static native void setDisplayMetrics(int screenWidthPixels,
int screenHeightPixels,
@ -567,10 +568,7 @@ public class QtNative
// keyboard methods
// surface methods
public static native void destroySurface();
public static native void setSurface(Object surface);
public static native void lockSurface();
public static native void unlockSurface();
public static native void setSurface(int id, Object surface, int w, int h);
// surface methods
// window methods

View File

@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Android port of the Qt Toolkit.
@ -44,11 +44,7 @@ package org.qtproject.qt5.android;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.PixelFormat;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
@ -60,61 +56,34 @@ import java.lang.reflect.Method;
public class QtSurface extends SurfaceView implements SurfaceHolder.Callback
{
private Bitmap m_bitmap = null;
private boolean m_started = false;
private boolean m_usesGL = false;
private GestureDetector m_gestureDetector;
private Object m_accessibilityDelegate = null;
private boolean m_onTop;
public QtSurface(Context context, int id)
public QtSurface(Context context, int id, boolean onTop)
{
super(context);
setFocusable(false);
setFocusableInTouchMode(false);
m_onTop = onTop;
setZOrderMediaOverlay(onTop);
getHolder().addCallback(this);
getHolder().setFormat(PixelFormat.RGBA_8888);
getHolder().setType(SurfaceHolder.SURFACE_TYPE_GPU);
setId(id);
m_gestureDetector =
new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
public void onLongPress(MotionEvent event) {
if (!m_started)
return;
QtNative.longPress(getId(), (int) event.getX(), (int) event.getY());
}
});
m_gestureDetector.setIsLongpressEnabled(true);
}
public void applicationStarted(boolean usesGL)
{
m_started = true;
m_usesGL = usesGL;
if (getWidth() < 1 || getHeight() < 1)
return;
if (m_usesGL) {
QtNative.setSurface(getHolder().getSurface());
} else {
QtNative.lockSurface();
QtNative.setSurface(null);
m_bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.RGB_565);
QtNative.setSurface(m_bitmap);
QtNative.unlockSurface();
}
}
@Override
public void surfaceCreated(SurfaceHolder holder)
{
DisplayMetrics metrics = new DisplayMetrics();
((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(metrics);
QtNative.setApplicationDisplayMetrics(metrics.widthPixels,
metrics.heightPixels, getWidth(), getHeight(), metrics.xdpi, metrics.ydpi, metrics.scaledDensity);
if (m_usesGL)
holder.setFormat(PixelFormat.RGBA_8888);
QtNative.setSurface(getId(), holder.getSurface(), getWidth(), getHeight());
// Initialize Accessibility
// The accessibility code depends on android API level 16, so dynamically resolve it
if (android.os.Build.VERSION.SDK_INT >= 16) {
@ -158,71 +127,21 @@ public class QtSurface extends SurfaceView implements SurfaceHolder.Callback
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
if (width<1 || height<1)
if (width < 1 || height < 1)
return;
DisplayMetrics metrics = new DisplayMetrics();
((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(metrics);
QtNative.setApplicationDisplayMetrics(metrics.widthPixels,
metrics.heightPixels,
width,
height,
metrics.xdpi,
metrics.ydpi,
metrics.scaledDensity);
if (!m_started)
return;
if (m_usesGL) {
QtNative.setSurface(holder.getSurface());
} else {
QtNative.lockSurface();
QtNative.setSurface(null);
m_bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
QtNative.setSurface(m_bitmap);
QtNative.unlockSurface();
QtNative.updateWindow();
}
QtNative.setSurface(getId(), holder.getSurface(), width, height);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
if (m_usesGL) {
QtNative.destroySurface();
} else {
if (!m_started)
return;
QtNative.lockSurface();
QtNative.setSurface(null);
QtNative.unlockSurface();
}
}
public void drawBitmap(Rect rect)
{
if (!m_started)
return;
QtNative.lockSurface();
if (null != m_bitmap) {
try {
Canvas cv = getHolder().lockCanvas(rect);
cv.drawBitmap(m_bitmap, rect, rect, null);
getHolder().unlockCanvasAndPost(cv);
} catch (Exception e) {
Log.e(QtNative.QtTAG, "Can't create main activity", e);
}
}
QtNative.unlockSurface();
QtNative.setSurface(getId(), null, 0, 0);
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
if (!m_started)
return false;
QtNative.sendTouchEvent(event, getId());
m_gestureDetector.onTouchEvent(event);
return true;
@ -231,8 +150,6 @@ public class QtSurface extends SurfaceView implements SurfaceHolder.Callback
@Override
public boolean onTrackballEvent(MotionEvent event)
{
if (!m_started)
return false;
QtNative.sendTrackballEvent(event, getId());
return true;
}

View File

@ -871,7 +871,7 @@ static void android_default_message_handler(QtMsgType type,
const QMessageLogContext &context,
const QString &message)
{
android_LogPriority priority;
android_LogPriority priority = ANDROID_LOG_DEBUG;
switch (type) {
case QtDebugMsg: priority = ANDROID_LOG_DEBUG; break;
case QtWarningMsg: priority = ANDROID_LOG_WARN; break;

View File

@ -178,12 +178,14 @@ public:
jobject jobj = static_cast<jobject>(o);
if (!isSameObject(jobj)) {
d = QSharedPointer<QJNIObjectData>(new QJNIObjectData());
if (jobj) {
QJNIEnvironmentPrivate env;
d->m_jobject = env->NewGlobalRef(jobj);
jclass objectClass = env->GetObjectClass(jobj);
d->m_jclass = static_cast<jclass>(env->NewGlobalRef(objectClass));
env->DeleteLocalRef(objectClass);
}
}
return *this;
}

View File

@ -8,9 +8,6 @@ irix-cc*:QMAKE_CXXFLAGS += -no_prelink -ptused
QMAKE_DOCS = $$PWD/doc/qtopengl.qdocconf
ANDROID_LIB_DEPENDENCY_REPLACEMENTS = \
"plugins/platforms/android/libqtforandroid.so:plugins/platforms/android/libqtforandroidGL.so"
load(qt_module)
contains(QT_CONFIG, opengl):CONFIG += opengl

View File

@ -1,3 +1,80 @@
TEMPLATE = subdirs
TARGET = qtforandroid
SUBDIRS += raster opengl
PLUGIN_TYPE = platforms
# STATICPLUGIN needed because there's a Q_IMPORT_PLUGIN in androidjnimain.cpp
# Yes, the plugin imports itself statically
DEFINES += QT_STATICPLUGIN
load(qt_plugin)
!contains(ANDROID_PLATFORM, android-9) {
INCLUDEPATH += $$NDK_ROOT/platforms/android-9/arch-$$ANDROID_ARCHITECTURE/usr/include
LIBS += -L$$NDK_ROOT/platforms/android-9/arch-$$ANDROID_ARCHITECTURE/usr/lib -ljnigraphics -landroid
} else {
LIBS += -ljnigraphics -landroid
}
QT += core-private gui-private platformsupport-private
CONFIG += qpa/genericunixfontdatabase
OTHER_FILES += $$PWD/android.json
INCLUDEPATH += $$PWD
SOURCES += $$PWD/androidplatformplugin.cpp \
$$PWD/androidjnimain.cpp \
$$PWD/androidjniaccessibility.cpp \
$$PWD/androidjniinput.cpp \
$$PWD/androidjnimenu.cpp \
$$PWD/androidjniclipboard.cpp \
$$PWD/qandroidplatformintegration.cpp \
$$PWD/qandroidplatformservices.cpp \
$$PWD/qandroidassetsfileenginehandler.cpp \
$$PWD/qandroidinputcontext.cpp \
$$PWD/qandroidplatformaccessibility.cpp \
$$PWD/qandroidplatformfontdatabase.cpp \
$$PWD/qandroidplatformdialoghelpers.cpp \
$$PWD/qandroidplatformclipboard.cpp \
$$PWD/qandroidplatformtheme.cpp \
$$PWD/qandroidplatformmenubar.cpp \
$$PWD/qandroidplatformmenu.cpp \
$$PWD/qandroidplatformmenuitem.cpp \
$$PWD/qandroidsystemlocale.cpp \
$$PWD/qandroidplatformscreen.cpp \
$$PWD/qandroidplatformwindow.cpp \
$$PWD/qandroidplatformopenglwindow.cpp \
$$PWD/qandroidplatformrasterwindow.cpp \
$$PWD/qandroidplatformbackingstore.cpp \
$$PWD/qandroidplatformopenglcontext.cpp
HEADERS += $$PWD/qandroidplatformintegration.h \
$$PWD/androidjnimain.h \
$$PWD/androidjniaccessibility.h \
$$PWD/androidjniinput.h \
$$PWD/androidjnimenu.h \
$$PWD/androidjniclipboard.h \
$$PWD/qandroidplatformservices.h \
$$PWD/qandroidassetsfileenginehandler.h \
$$PWD/qandroidinputcontext.h \
$$PWD/qandroidplatformaccessibility.h \
$$PWD/qandroidplatformfontdatabase.h \
$$PWD/qandroidplatformclipboard.h \
$$PWD/qandroidplatformdialoghelpers.h \
$$PWD/qandroidplatformtheme.h \
$$PWD/qandroidplatformmenubar.h \
$$PWD/qandroidplatformmenu.h \
$$PWD/qandroidplatformmenuitem.h \
$$PWD/qandroidsystemlocale.h \
$$PWD/androidsurfaceclient.h \
$$PWD/qandroidplatformscreen.h \
$$PWD/qandroidplatformwindow.h \
$$PWD/qandroidplatformopenglwindow.h \
$$PWD/qandroidplatformrasterwindow.h \
$$PWD/qandroidplatformbackingstore.h \
$$PWD/qandroidplatformopenglcontext.h
#Non-standard install directory, QTBUG-29859
DESTDIR = $$DESTDIR/android
target.path = $${target.path}/android

View File

@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@ -53,6 +53,7 @@
#include <qdebug.h>
#include <qglobal.h>
#include <qobjectdefs.h>
#include <QtCore/private/qjni_p.h>
#include <stdlib.h>
#include "androidjnimain.h"
@ -73,14 +74,6 @@
#include <qpa/qwindowsysteminterface.h>
#ifdef ANDROID_PLUGIN_OPENGL
# include "qandroidopenglplatformwindow.h"
#endif
#include <android/native_window_jni.h>
static jmethodID m_redrawSurfaceMethodID = 0;
Q_IMPORT_PLUGIN(QAndroidPlatformIntegrationPlugin)
static JavaVM *m_javaVM = NULL;
@ -90,6 +83,9 @@ static jmethodID m_loadClassMethodID = NULL;
static AAssetManager *m_assetManager = NULL;
static jobject m_resourcesObj;
static jobject m_activityObject = NULL;
static jmethodID m_createSurfaceMethodID = 0;
static jmethodID m_setSurfaceGeometryMethodID = 0;
static jmethodID m_destroySurfaceMethodID = 0;
static bool m_activityActive = true; // defaults to true because when the platform plugin is
// initialized, QtActivity::onResume() has already been called
@ -110,17 +106,19 @@ static Main m_main = NULL;
static void *m_mainLibraryHnd = NULL;
static QList<QByteArray> m_applicationParams;
#ifndef ANDROID_PLUGIN_OPENGL
static jobject m_surface = NULL;
#else
static EGLNativeWindowType m_nativeWindow = 0;
static QSemaphore m_waitForWindowSemaphore;
static bool m_waitForWindow = false;
#endif
struct SurfaceData
{
~SurfaceData() { delete surface; }
QJNIObjectPrivate *surface = 0;
AndroidSurfaceClient *client = 0;
};
QHash<int, AndroidSurfaceClient *> m_surfaces;
static QMutex m_surfacesMutex;
static int m_surfaceId = 1;
static QSemaphore m_quitAppSemaphore;
static QMutex m_surfaceMutex(QMutex::Recursive);
static QSemaphore m_pauseApplicationSemaphore;
static QMutex m_pauseApplicationMutex;
@ -140,128 +138,18 @@ static const char m_qtTag[] = "Qt";
static const char m_classErrorMsg[] = "Can't find class \"%s\"";
static const char m_methodErrorMsg[] = "Can't find method \"%s%s\"";
static inline void checkPauseApplication()
{
m_pauseApplicationMutex.lock();
if (m_pauseApplication) {
m_pauseApplicationMutex.unlock();
m_pauseApplicationSemaphore.acquire(); // wait until surface is created
m_pauseApplicationMutex.lock();
m_pauseApplication = false;
m_pauseApplicationMutex.unlock();
//FIXME
// QWindowSystemInterface::handleScreenAvailableGeometryChange(0);
// QWindowSystemInterface::handleScreenGeometryChange(0);
} else {
m_pauseApplicationMutex.unlock();
}
}
namespace QtAndroid
{
#ifndef ANDROID_PLUGIN_OPENGL
void flushImage(const QPoint &pos, const QImage &image, const QRect &destinationRect)
{
checkPauseApplication();
QMutexLocker locker(&m_surfaceMutex);
if (!m_surface)
return;
AttachedJNIEnv env;
if (!env.jniEnv)
return;
int bpp = 2;
AndroidBitmapInfo info;
int ret;
if ((ret = AndroidBitmap_getInfo(env.jniEnv, m_surface, &info)) < 0) {
qWarning() << "AndroidBitmap_getInfo() failed ! error=" << ret;
m_javaVM->DetachCurrentThread();
return;
}
if (info.format != ANDROID_BITMAP_FORMAT_RGB_565) {
qWarning() << "Bitmap format is not RGB_565!";
m_javaVM->DetachCurrentThread();
return;
}
void *pixels;
unsigned char *screenBits;
if ((ret = AndroidBitmap_lockPixels(env.jniEnv, m_surface, &pixels)) < 0) {
qWarning() << "AndroidBitmap_lockPixels() failed! error=" << ret;
m_javaVM->DetachCurrentThread();
return;
}
screenBits = static_cast<unsigned char *>(pixels);
int sbpl = info.stride;
int swidth = info.width;
int sheight = info.height;
unsigned sposx = pos.x() + destinationRect.x();
unsigned sposy = pos.y() + destinationRect.y();
screenBits += sposy * sbpl;
unsigned ibpl = image.bytesPerLine();
unsigned iposx = destinationRect.x();
unsigned iposy = destinationRect.y();
const unsigned char *imageBits = static_cast<const unsigned char *>(image.bits());
imageBits += iposy * ibpl;
unsigned width = swidth - sposx < unsigned(destinationRect.width())
? (swidth-sposx)
: destinationRect.width();
unsigned height = sheight - sposy < unsigned(destinationRect.height())
? (sheight - sposy)
: destinationRect.height();
for (unsigned y = 0; y < height; y++) {
memcpy(screenBits + y*sbpl + sposx*bpp,
imageBits + y*ibpl + iposx*bpp,
width*bpp);
}
AndroidBitmap_unlockPixels(env.jniEnv, m_surface);
env.jniEnv->CallStaticVoidMethod(m_applicationClass,
m_redrawSurfaceMethodID,
jint(destinationRect.left()),
jint(destinationRect.top()),
jint(destinationRect.right() + 1),
jint(destinationRect.bottom() + 1));
#warning FIXME dirty hack, figure out why it needs to add 1 to right and bottom !!!!
}
#else // for #ifndef ANDROID_PLUGIN_OPENGL
EGLNativeWindowType nativeWindow(bool waitForWindow)
{
m_surfaceMutex.lock();
if (!m_nativeWindow && waitForWindow) {
m_waitForWindow = true;
m_surfaceMutex.unlock();
m_waitForWindowSemaphore.acquire();
m_waitForWindow = false;
return m_nativeWindow;
}
m_surfaceMutex.unlock();
return m_nativeWindow;
}
#endif
void setAndroidPlatformIntegration(QAndroidPlatformIntegration *androidPlatformIntegration)
{
m_surfaceMutex.lock();
m_surfacesMutex.lock();
m_androidPlatformIntegration = androidPlatformIntegration;
m_surfaceMutex.unlock();
m_surfacesMutex.unlock();
}
QAndroidPlatformIntegration *androidPlatformIntegration()
{
QMutexLocker locker(&m_surfaceMutex);
QMutexLocker locker(&m_surfacesMutex);
return m_androidPlatformIntegration;
}
@ -353,14 +241,14 @@ namespace QtAndroid
jobject createBitmap(QImage img, JNIEnv *env)
{
if (img.format() != QImage::Format_ARGB32 && img.format() != QImage::Format_RGB16)
img = img.convertToFormat(QImage::Format_ARGB32);
if (img.format() != QImage::Format_RGBA8888 && img.format() != QImage::Format_RGB16)
img = img.convertToFormat(QImage::Format_RGBA8888);
jobject bitmap = env->CallStaticObjectMethod(m_bitmapClass,
m_createBitmapMethodID,
img.width(),
img.height(),
img.format() == QImage::Format_ARGB32
img.format() == QImage::Format_RGBA8888
? m_ARGB_8888_BitmapConfigValue
: m_RGB_565_BitmapConfigValue);
if (!bitmap)
@ -393,6 +281,21 @@ namespace QtAndroid
return bitmap;
}
jobject createBitmap(int width, int height, QImage::Format format, JNIEnv *env)
{
if (format != QImage::Format_RGBA8888
&& format != QImage::Format_RGB16)
return 0;
return env->CallStaticObjectMethod(m_bitmapClass,
m_createBitmapMethodID,
width,
height,
format == QImage::Format_RGB16
? m_RGB_565_BitmapConfigValue
: m_ARGB_8888_BitmapConfigValue);
}
jobject createBitmapDrawable(jobject bitmap, JNIEnv *env)
{
if (!bitmap)
@ -418,25 +321,74 @@ namespace QtAndroid
{
return m_qtTag;
}
int createSurface(AndroidSurfaceClient *client, const QRect &geometry, bool onTop)
{
QJNIEnvironmentPrivate env;
if (!env)
return 0;
m_surfacesMutex.lock();
int surfaceId = m_surfaceId++;
m_surfaces[surfaceId] = client;
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_createSurfaceMethodID,
surfaceId,
jboolean(onTop),
x, y, w, h);
return surfaceId;
}
void setSurfaceGeometry(int surfaceId, const QRect &geometry)
{
QJNIEnvironmentPrivate env;
if (!env)
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();
}
env->CallStaticVoidMethod(m_applicationClass,
m_setSurfaceGeometryMethodID,
surfaceId,
x, y, w, h);
}
void destroySurface(int surfaceId)
{
QMutexLocker lock(&m_surfacesMutex);
const auto &it = m_surfaces.find(surfaceId);
if (it == m_surfaces.end())
return;
m_surfaces.remove(surfaceId);
QJNIEnvironmentPrivate env;
if (!env)
return;
env->CallStaticVoidMethod(m_applicationClass,
m_destroySurfaceMethodID,
surfaceId);
}
}
static jboolean startQtAndroidPlugin(JNIEnv* /*env*/, jobject /*object*//*, jobject applicationAssetManager*/)
{
#ifndef ANDROID_PLUGIN_OPENGL
m_surface = 0;
#else
m_nativeWindow = 0;
m_waitForWindow = false;
#endif
m_androidPlatformIntegration = 0;
m_androidAssetsFileEngineHandler = new AndroidAssetsFileEngineHandler();
#ifdef ANDROID_PLUGIN_OPENGL
return true;
#else
return false;
#endif
}
static void *startMainMethod(void */*data*/)
@ -512,54 +464,16 @@ static jboolean startQtApplication(JNIEnv *env, jobject /*object*/, jstring para
return pthread_create(&appThread, NULL, startMainMethod, NULL) == 0;
}
static void pauseQtApp(JNIEnv */*env*/, jobject /*thiz*/)
{
m_surfaceMutex.lock();
m_pauseApplicationMutex.lock();
if (m_androidPlatformIntegration)
m_androidPlatformIntegration->pauseApp();
m_pauseApplication = true;
m_pauseApplicationMutex.unlock();
m_surfaceMutex.unlock();
}
static void resumeQtApp(JNIEnv */*env*/, jobject /*thiz*/)
{
m_surfaceMutex.lock();
m_pauseApplicationMutex.lock();
if (m_androidPlatformIntegration)
m_androidPlatformIntegration->resumeApp();
if (m_pauseApplication)
m_pauseApplicationSemaphore.release();
m_pauseApplicationMutex.unlock();
m_surfaceMutex.unlock();
}
static void quitQtAndroidPlugin(JNIEnv *env, jclass /*clazz*/)
{
#ifndef ANDROID_PLUGIN_OPENGL
if (m_surface) {
env->DeleteGlobalRef(m_surface);
m_surface = 0;
}
#else
Q_UNUSED(env);
#endif
m_androidPlatformIntegration = 0;
delete m_androidAssetsFileEngineHandler;
}
static void terminateQt(JNIEnv *env, jclass /*clazz*/)
{
#ifndef ANDROID_PLUGIN_OPENGL
if (m_surface)
env->DeleteGlobalRef(m_surface);
#endif
env->DeleteGlobalRef(m_applicationClass);
env->DeleteGlobalRef(m_classLoaderObject);
env->DeleteGlobalRef(m_resourcesObj);
@ -568,76 +482,19 @@ static void terminateQt(JNIEnv *env, jclass /*clazz*/)
env->DeleteGlobalRef(m_ARGB_8888_BitmapConfigValue);
env->DeleteGlobalRef(m_RGB_565_BitmapConfigValue);
env->DeleteGlobalRef(m_bitmapDrawableClass);
m_androidPlatformIntegration = 0;
delete m_androidAssetsFileEngineHandler;
}
static void setSurface(JNIEnv *env, jobject /*thiz*/, jobject jSurface)
static void setSurface(JNIEnv *env, jobject /*thiz*/, jint id, jobject jSurface, jint w, jint h)
{
#ifndef ANDROID_PLUGIN_OPENGL
if (m_surface)
env->DeleteGlobalRef(m_surface);
m_surface = env->NewGlobalRef(jSurface);
#else
m_surfaceMutex.lock();
EGLNativeWindowType nativeWindow = ANativeWindow_fromSurface(env, jSurface);
bool sameNativeWindow = (nativeWindow != 0 && nativeWindow == m_nativeWindow);
m_nativeWindow = nativeWindow;
if (m_waitForWindow)
m_waitForWindowSemaphore.release();
if (m_androidPlatformIntegration) {
// Use the desktop size.
// On some devices, the getters for the native window size gives wrong values
QSize size = QAndroidPlatformIntegration::defaultDesktopSize();
QPlatformScreen *screen = m_androidPlatformIntegration->screen();
QRect geometry(QPoint(0, 0), size);
if (screen) {
QWindowSystemInterface::handleScreenAvailableGeometryChange(screen->screen(), geometry);
QWindowSystemInterface::handleScreenGeometryChange(screen->screen(), geometry);
QMutexLocker lock(&m_surfacesMutex);
const auto &it = m_surfaces.find(id);
if (it == m_surfaces.end()) {
qWarning()<<"Can't find surface" << id;
return;
}
if (!sameNativeWindow) {
m_surfaceMutex.unlock();
m_androidPlatformIntegration->surfaceChanged();
} else {
// Resize all top level windows, since they share the same surface
foreach (QWindow *w, QGuiApplication::topLevelWindows()) {
QAndroidOpenGLPlatformWindow *window =
static_cast<QAndroidOpenGLPlatformWindow *>(w->handle());
if (window != 0) {
window->lock();
window->scheduleResize(size);
QWindowSystemInterface::handleExposeEvent(window->window(),
QRegion(window->window()->geometry()));
window->unlock();
}
}
m_surfaceMutex.unlock();
}
} else {
m_surfaceMutex.unlock();
}
#endif // for #ifndef ANDROID_PLUGIN_OPENGL
}
static void destroySurface(JNIEnv *env, jobject /*thiz*/)
{
#ifndef ANDROID_PLUGIN_OPENGL
if (m_surface) {
env->DeleteGlobalRef(m_surface);
m_surface = 0;
}
#else
Q_UNUSED(env);
m_nativeWindow = 0;
if (m_androidPlatformIntegration != 0)
m_androidPlatformIntegration->invalidateNativeSurface();
#endif
it.value()->surfaceChanged(env, jSurface, w, h);
}
static void setDisplayMetrics(JNIEnv */*env*/, jclass /*clazz*/,
@ -660,16 +517,6 @@ static void setDisplayMetrics(JNIEnv */*env*/, jclass /*clazz*/,
}
}
static void lockSurface(JNIEnv */*env*/, jobject /*thiz*/)
{
m_surfaceMutex.lock();
}
static void unlockSurface(JNIEnv */*env*/, jobject /*thiz*/)
{
m_surfaceMutex.unlock();
}
static void updateWindow(JNIEnv */*env*/, jobject /*thiz*/)
{
if (!m_androidPlatformIntegration)
@ -680,12 +527,8 @@ static void updateWindow(JNIEnv */*env*/, jobject /*thiz*/)
QWindowSystemInterface::handleExposeEvent(w, QRegion(w->geometry()));
}
#ifndef ANDROID_PLUGIN_OPENGL
QAndroidPlatformScreen *screen = static_cast<QAndroidPlatformScreen *>(m_androidPlatformIntegration->screen());
QMetaObject::invokeMethod(screen, "setDirty", Qt::QueuedConnection, Q_ARG(QRect,screen->geometry()));
#else
qWarning("updateWindow: Dirty screen not implemented yet on OpenGL");
#endif
}
static void updateApplicationState(JNIEnv */*env*/, jobject /*thiz*/, jint state)
@ -734,15 +577,10 @@ static void handleOrientationChanged(JNIEnv */*env*/, jobject /*thiz*/, jint new
static JNINativeMethod methods[] = {
{"startQtAndroidPlugin", "()Z", (void *)startQtAndroidPlugin},
{"startQtApplication", "(Ljava/lang/String;Ljava/lang/String;)V", (void *)startQtApplication},
{"pauseQtApp", "()V", (void *)pauseQtApp},
{"resumeQtApp", "()V", (void *)resumeQtApp},
{"quitQtAndroidPlugin", "()V", (void *)quitQtAndroidPlugin},
{"terminateQt", "()V", (void *)terminateQt},
{"setDisplayMetrics", "(IIIIDDD)V", (void *)setDisplayMetrics},
{"setSurface", "(Ljava/lang/Object;)V", (void *)setSurface},
{"destroySurface", "()V", (void *)destroySurface},
{"lockSurface", "()V", (void *)lockSurface},
{"unlockSurface", "()V", (void *)unlockSurface},
{"setSurface", "(ILjava/lang/Object;II)V", (void *)setSurface},
{"updateWindow", "()V", (void *)updateWindow},
{"updateApplicationState", "(I)V", (void *)updateApplicationState},
{"handleOrientationChanged", "(II)V", (void *)handleOrientationChanged}
@ -795,7 +633,9 @@ static int registerNatives(JNIEnv *env)
return JNI_FALSE;
}
GET_AND_CHECK_STATIC_METHOD(m_redrawSurfaceMethodID, m_applicationClass, "redrawSurface", "(IIII)V");
GET_AND_CHECK_STATIC_METHOD(m_createSurfaceMethodID, m_applicationClass, "createSurface", "(IZIIII)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");
jmethodID methodID;
GET_AND_CHECK_STATIC_METHOD(methodID, m_applicationClass, "activity", "()Landroid/app/Activity;");

View File

@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@ -45,16 +45,11 @@
#include <android/log.h>
#ifdef ANDROID_PLUGIN_OPENGL
# include <EGL/eglplatform.h>
#endif
#include <QtCore/qsize.h>
#include <jni.h>
#include <android/asset_manager.h>
class QImage;
#include <QImage>
class QRect;
class QPoint;
class QThread;
@ -62,6 +57,7 @@ class QAndroidPlatformIntegration;
class QWidget;
class QString;
class QWindow;
class AndroidSurfaceClient;
namespace QtAndroid
{
@ -69,11 +65,10 @@ namespace QtAndroid
void setAndroidPlatformIntegration(QAndroidPlatformIntegration *androidPlatformIntegration);
void setQtThread(QThread *thread);
#ifndef ANDROID_PLUGIN_OPENGL
void flushImage(const QPoint &pos, const QImage &image, const QRect &rect);
#else
EGLNativeWindowType nativeWindow(bool waitToCreate = true);
#endif
int createSurface(AndroidSurfaceClient * client, const QRect &geometry, bool onTop);
void setSurfaceGeometry(int surfaceId, const QRect &geometry);
void destroySurface(int surfaceId);
QWindow *topLevelWindowAt(const QPoint &globalPos);
int desktopWidthPixels();
@ -91,6 +86,7 @@ namespace QtAndroid
void hideStatusBar();
jobject createBitmap(QImage img, JNIEnv *env = 0);
jobject createBitmap(int width, int height, QImage::Format format, JNIEnv *env);
jobject createBitmapDrawable(jobject bitmap, JNIEnv *env = 0);
struct AttachedJNIEnv

View File

@ -143,6 +143,9 @@ namespace QtAndroidMenu
void setActiveTopLevelWindow(QWindow *window)
{
Qt::WindowFlags flags = window ? window->flags() : Qt::WindowFlags();
if (!window)
return;
bool isNonRegularWindow = flags & (Qt::Desktop | Qt::Popup | Qt::Dialog | Qt::Sheet) & ~Qt::Window;
if (isNonRegularWindow)
return;

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@ -39,22 +39,20 @@
**
****************************************************************************/
#ifndef QANDROIDOPENGLPLATFORMSCREEN_H
#define QANDROIDOPENGLPLATFORMSCREEN_H
#ifndef ANDROIDSURFACECLIENT_H
#define ANDROIDSURFACECLIENT_H
#include <QMutex>
#include <jni.h>
#include "qeglfsscreen.h"
QT_BEGIN_NAMESPACE
class QAndroidOpenGLPlatformScreen : public QEglFSScreen
class AndroidSurfaceClient
{
public:
QAndroidOpenGLPlatformScreen(EGLDisplay display);
virtual void surfaceChanged(JNIEnv *jniEnv, jobject surface, int w, int h) = 0;
void lockSurface() { m_surfaceMutex.lock(); }
void unlockSurface() { m_surfaceMutex.unlock(); }
protected:
void topWindowChanged(QPlatformWindow *window);
QMutex m_surfaceMutex;
};
QT_END_NAMESPACE
#endif // QANDROIDOPENGLPLATFORMSCREEN_H
#endif // ANDROIDSURFACECLIENT_H

View File

@ -1,32 +0,0 @@
TARGET = qtforandroidGL
PLUGIN_TYPE = platforms
load(qt_plugin)
# STATICPLUGIN needed because there's a Q_IMPORT_PLUGIN in androidjnimain.cpp
# Yes, the plugin imports itself statically
DEFINES += QT_STATICPLUGIN ANDROID_PLUGIN_OPENGL
!equals(ANDROID_PLATFORM, android-9) {
INCLUDEPATH += $$NDK_ROOT/platforms/android-9/arch-$$ANDROID_ARCHITECTURE/usr/include
LIBS += -L$$NDK_ROOT/platforms/android-9/arch-$$ANDROID_ARCHITECTURE/usr/lib -ljnigraphics -landroid
} else {
LIBS += -ljnigraphics -landroid
}
EGLFS_PLATFORM_HOOKS_SOURCES = $$PWD/../src/opengl/qeglfshooks_android.cpp
INCLUDEPATH += $$PWD/../src/opengl/
HEADERS += \
$$PWD/../src/opengl/qandroidopenglcontext.h \
$$PWD/../src/opengl/qandroidopenglplatformwindow.h \
$$PWD/../src/opengl/qandroidopenglplatformscreen.h
SOURCES += \
$$PWD/../src/opengl/qandroidopenglcontext.cpp \
$$PWD/../src/opengl/qandroidopenglplatformwindow.cpp \
$$PWD/../src/opengl/qandroidopenglplatformscreen.cpp
include($$PWD/../../eglfs/eglfs.pri)
include($$PWD/../src/src.pri)

View File

@ -0,0 +1,78 @@
/****************************************************************************
**
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2013 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 "qandroidplatformbackingstore.h"
#include "qandroidplatformscreen.h"
#include "qandroidplatformrasterwindow.h"
#include <qpa/qplatformscreen.h>
QT_BEGIN_NAMESPACE
QAndroidPlatformBackingStore::QAndroidPlatformBackingStore(QWindow *window)
: QPlatformBackingStore(window)
{
Q_ASSERT(window->handle());
(static_cast<QAndroidPlatformRasterWindow *>(window->handle()))->setBackingStore(this);
}
QPaintDevice *QAndroidPlatformBackingStore::paintDevice()
{
return &m_image;
}
void QAndroidPlatformBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
{
Q_UNUSED(window);
Q_UNUSED(offset);
(static_cast<QAndroidPlatformRasterWindow *>(window->handle()))->repaint(region);
}
void QAndroidPlatformBackingStore::resize(const QSize &size, const QRegion &staticContents)
{
Q_UNUSED(staticContents);
if (m_image.size() != size)
m_image = QImage(size, window()->screen()->handle()->format());
}
QT_END_NAMESPACE

View File

@ -1,5 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
@ -39,23 +40,27 @@
**
****************************************************************************/
#include "qandroidopenglplatformscreen.h"
#include "qandroidopenglplatformwindow.h"
#include "androidjnimenu.h"
#ifndef QANDROIDPLATFORMBACKINGSTORE_H
#define QANDROIDPLATFORMBACKINGSTORE_H
#include <qpa/qplatformbackingstore.h>
#include <qpa/qwindowsysteminterface.h>
QT_BEGIN_NAMESPACE
QAndroidOpenGLPlatformScreen::QAndroidOpenGLPlatformScreen(EGLDisplay display)
: QEglFSScreen(display)
class QAndroidPlatformBackingStore : public QPlatformBackingStore
{
}
public:
explicit QAndroidPlatformBackingStore(QWindow *window);
virtual QPaintDevice *paintDevice();
virtual void flush(QWindow *window, const QRegion &region, const QPoint &offset);
virtual void resize(const QSize &size, const QRegion &staticContents);
const QImage image() { return m_image; }
void QAndroidOpenGLPlatformScreen::topWindowChanged(QPlatformWindow *window)
{
QtAndroidMenu::setActiveTopLevelWindow(window->window());
QAndroidOpenGLPlatformWindow *platformWindow = static_cast<QAndroidOpenGLPlatformWindow *>(window);
if (platformWindow != 0)
platformWindow->updateStatusBarVisibility();
}
protected:
QImage m_image;
};
QT_END_NAMESPACE
#endif // QANDROIDPLATFORMBACKINGSTORE_H

View File

@ -40,35 +40,32 @@
****************************************************************************/
#include "qandroidplatformintegration.h"
#include "qabstracteventdispatcher.h"
#include "androidjnimain.h"
#include <QtGui/qguiapplication.h>
#include <qpa/qwindowsysteminterface.h>
#include <QGuiApplication>
#include <QOpenGLContext>
#include <QThread>
#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformwindow.h>
#warning sort the headers
#include "androidjnimain.h"
#include "qabstracteventdispatcher.h"
#include "qandroidplatformrasterwindow.h"
#include "qandroidplatformopenglwindow.h"
#include "qandroidplatformbackingstore.h"
#include "qandroidplatformservices.h"
#include "qandroidplatformfontdatabase.h"
#include "qandroidplatformclipboard.h"
#include "qandroidplatformaccessibility.h"
#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
#ifndef ANDROID_PLUGIN_OPENGL
# include "qandroidplatformscreen.h"
# include "qandroidplatformwindow.h"
# include <QtPlatformSupport/private/qfbbackingstore_p.h>
#else
# include "qeglfswindow.h"
# include "androidjnimenu.h"
# include "qandroidopenglcontext.h"
# include "qandroidopenglplatformwindow.h"
# include "qandroidopenglplatformscreen.h"
# include "qeglfshooks.h"
# include <QtGui/qopenglcontext.h>
#endif
#include "qandroidplatformopenglcontext.h"
#include "qandroidplatformscreen.h"
#include "qandroidplatformtheme.h"
#include "qandroidsystemlocale.h"
QT_BEGIN_NAMESPACE
int QAndroidPlatformIntegration::m_defaultGeometryWidth = 320;
@ -102,12 +99,21 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList &para
m_androidPlatformNativeInterface = new QAndroidPlatformNativeInterface();
#ifndef ANDROID_PLUGIN_OPENGL
if (!eglBindAPI(EGL_OPENGL_ES_API))
qFatal("Could not bind GL_ES API");
m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (m_eglDisplay == EGL_NO_DISPLAY)
qFatal("Could not open egl display");
EGLint major, minor;
if (!eglInitialize(m_eglDisplay, &major, &minor))
qFatal("Could not initialize egl display");
m_primaryScreen = new QAndroidPlatformScreen();
screenAdded(m_primaryScreen);
m_primaryScreen->setPhysicalSize(QSize(m_defaultPhysicalSizeWidth, m_defaultPhysicalSizeHeight));
m_primaryScreen->setGeometry(QRect(0, 0, m_defaultGeometryWidth, m_defaultGeometryHeight));
#endif
m_mainThread = QThread::currentThread();
QtAndroid::setAndroidPlatformIntegration(this);
@ -124,83 +130,53 @@ bool QAndroidPlatformIntegration::hasCapability(Capability cap) const
switch (cap) {
case ThreadedPixmaps: return true;
case ApplicationState: return true;
case NativeWidgets: return false;
case NativeWidgets: return true;
case OpenGL: return true;
case ThreadedOpenGL: return true;
default:
#ifndef ANDROID_PLUGIN_OPENGL
return QPlatformIntegration::hasCapability(cap);
#else
return QEglFSIntegration::hasCapability(cap);
#endif
}
}
#ifndef ANDROID_PLUGIN_OPENGL
QPlatformBackingStore *QAndroidPlatformIntegration::createPlatformBackingStore(QWindow *window) const
{
return new QFbBackingStore(window);
return new QAndroidPlatformBackingStore(window);
}
QPlatformOpenGLContext *QAndroidPlatformIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
QSurfaceFormat format(context->format());
format.setAlphaBufferSize(8);
format.setRedBufferSize(8);
format.setGreenBufferSize(8);
format.setBlueBufferSize(8);
return new QAndroidPlatformOpenGLContext(format, context->shareHandle(), m_eglDisplay);
}
QPlatformWindow *QAndroidPlatformIntegration::createPlatformWindow(QWindow *window) const
{
QAndroidPlatformWindow *platformWindow = new QAndroidPlatformWindow(window);
platformWindow->setWindowState(window->windowState());
return platformWindow;
if (window->surfaceType() == QSurface::RasterSurface)
return new QAndroidPlatformRasterWindow(window);
else
return new QAndroidPlatformOpenGLWindow(window, m_eglDisplay);
}
QAbstractEventDispatcher *QAndroidPlatformIntegration::createEventDispatcher() const
{
return createUnixEventDispatcher();
}
#else // !ANDROID_PLUGIN_OPENGL
QPlatformWindow *QAndroidPlatformIntegration::createPlatformWindow(QWindow *window) const
{
QAndroidOpenGLPlatformWindow *platformWindow = new QAndroidOpenGLPlatformWindow(window);
platformWindow->create();
platformWindow->requestActivateWindow();
platformWindow->setWindowState(window->windowState());
QtAndroidMenu::setActiveTopLevelWindow(window);
return platformWindow;
}
void QAndroidPlatformIntegration::invalidateNativeSurface()
{
foreach (QWindow *w, QGuiApplication::topLevelWindows()) {
QAndroidOpenGLPlatformWindow *window =
static_cast<QAndroidOpenGLPlatformWindow *>(w->handle());
if (window != 0)
window->invalidateSurface();
}
}
void QAndroidPlatformIntegration::surfaceChanged()
{
QAndroidOpenGLPlatformWindow::updateStaticNativeWindow();
foreach (QWindow *w, QGuiApplication::topLevelWindows()) {
QAndroidOpenGLPlatformWindow *window =
static_cast<QAndroidOpenGLPlatformWindow *>(w->handle());
if (window != 0)
window->resetSurface();
}
}
QPlatformOpenGLContext *QAndroidPlatformIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
return new QAndroidOpenGLContext(this,
QEglFSHooks::hooks()->surfaceFormatFor(context->format()),
context->shareHandle(),
display());
}
#endif // ANDROID_PLUGIN_OPENGL
QAndroidPlatformIntegration::~QAndroidPlatformIntegration()
{
if (m_eglDisplay != EGL_NO_DISPLAY)
eglTerminate(m_eglDisplay);
delete m_androidPlatformNativeInterface;
delete m_androidFDB;
delete m_androidSystemLocale;
QtAndroid::setAndroidPlatformIntegration(NULL);
}
QPlatformFontDatabase *QAndroidPlatformIntegration::fontDatabase() const
{
return m_androidFDB;
@ -295,8 +271,6 @@ QPlatformAccessibility *QAndroidPlatformIntegration::accessibility() const
}
#endif
#ifndef ANDROID_PLUGIN_OPENGL
void QAndroidPlatformIntegration::setDesktopSize(int width, int height)
{
if (m_primaryScreen)
@ -308,36 +282,5 @@ void QAndroidPlatformIntegration::setDisplayMetrics(int width, int height)
if (m_primaryScreen)
QMetaObject::invokeMethod(m_primaryScreen, "setPhysicalSize", Qt::AutoConnection, Q_ARG(QSize, QSize(width, height)));
}
#else
void QAndroidPlatformIntegration::setDesktopSize(int width, int height)
{
m_defaultGeometryWidth = width;
m_defaultGeometryHeight = height;
}
void QAndroidPlatformIntegration::setDisplayMetrics(int width, int height)
{
m_defaultPhysicalSizeWidth = width;
m_defaultPhysicalSizeHeight = height;
}
QEglFSScreen *QAndroidPlatformIntegration::createScreen() const
{
return new QAndroidOpenGLPlatformScreen(display());
}
#endif
void QAndroidPlatformIntegration::pauseApp()
{
if (QAbstractEventDispatcher::instance(m_mainThread))
QAbstractEventDispatcher::instance(m_mainThread)->interrupt();
}
void QAndroidPlatformIntegration::resumeApp()
{
if (QAbstractEventDispatcher::instance(m_mainThread))
QAbstractEventDispatcher::instance(m_mainThread)->wakeUp();
}
QT_END_NAMESPACE

View File

@ -47,14 +47,11 @@
#include <qpa/qplatformnativeinterface.h>
#include <QtWidgets/QAction>
#include <EGL/egl.h>
#include <jni.h>
#include "qandroidinputcontext.h"
#ifndef ANDROID_PLUGIN_OPENGL
# include "qandroidplatformscreen.h"
#else
# include "qeglfsintegration.h"
#endif
#include "qandroidplatformscreen.h"
QT_BEGIN_NAMESPACE
@ -63,10 +60,6 @@ class QAndroidPlatformServices;
class QAndroidSystemLocale;
class QPlatformAccessibility;
#ifdef ANDROID_PLUGIN_OPENGL
class QAndroidOpenGLPlatformWindow;
#endif
class QAndroidPlatformNativeInterface: public QPlatformNativeInterface
{
public:
@ -75,12 +68,7 @@ public:
QHash<int, QFont> m_fonts;
};
class QAndroidPlatformIntegration
#ifndef ANDROID_PLUGIN_OPENGL
: public QPlatformIntegration
#else
: public QEglFSIntegration
#endif
class QAndroidPlatformIntegration : public QPlatformIntegration
{
friend class QAndroidPlatformScreen;
@ -90,17 +78,11 @@ public:
bool hasCapability(QPlatformIntegration::Capability cap) const;
#ifndef ANDROID_PLUGIN_OPENGL
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const;
QPlatformWindow *createPlatformWindow(QWindow *window) const;
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const;
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const;
QAbstractEventDispatcher *createEventDispatcher() const;
QAndroidPlatformScreen *screen() { return m_primaryScreen; }
#else
QPlatformWindow *createPlatformWindow(QWindow *window) const;
void invalidateNativeSurface();
void surfaceChanged();
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const;
#endif
virtual void setDesktopSize(int width, int height);
virtual void setDisplayMetrics(int width, int height);
@ -121,13 +103,11 @@ public:
#endif
QVariant styleHint(StyleHint hint) const;
Qt::WindowState defaultWindowState(Qt::WindowFlags flags) const Q_DECL_OVERRIDE;
Qt::WindowState defaultWindowState(Qt::WindowFlags flags) const;
QStringList themeNames() const;
QPlatformTheme *createPlatformTheme(const QString &name) const;
void pauseApp();
void resumeApp();
static void setDefaultDisplayMetrics(int gw, int gh, int sw, int sh);
static void setDefaultDesktopSize(int gw, int gh);
static void setScreenOrientation(Qt::ScreenOrientation currentOrientation,
@ -141,19 +121,12 @@ public:
QTouchDevice *touchDevice() const { return m_touchDevice; }
void setTouchDevice(QTouchDevice *touchDevice) { m_touchDevice = touchDevice; }
#ifdef ANDROID_PLUGIN_OPENGL
QEglFSScreen *createScreen() const;
#endif
private:
friend class QEglFSAndroidHooks;
EGLDisplay m_eglDisplay;
QTouchDevice *m_touchDevice;
#ifndef ANDROID_PLUGIN_OPENGL
QAndroidPlatformScreen *m_primaryScreen;
#endif
QThread *m_mainThread;

View File

@ -1,5 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
@ -39,49 +40,30 @@
**
****************************************************************************/
#include "qandroidopenglcontext.h"
#include "qandroidopenglplatformwindow.h"
#include "qandroidplatformintegration.h"
#include <QtCore/qdebug.h>
#include <qpa/qwindowsysteminterface.h>
#include "qandroidplatformopenglcontext.h"
#include "qandroidplatformopenglwindow.h"
#include <QSurface>
#include <QtGui/private/qopenglcontext_p.h>
QT_BEGIN_NAMESPACE
QAndroidOpenGLContext::QAndroidOpenGLContext(const QAndroidPlatformIntegration *integration,
const QSurfaceFormat &format,
QPlatformOpenGLContext *share,
EGLDisplay display,
EGLenum eglApi)
: QEglFSContext(format, share, display, eglApi)
, m_platformIntegration(integration)
QAndroidPlatformOpenGLContext::QAndroidPlatformOpenGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display)
:QEGLPlatformContext(format, share, display, EGL_OPENGL_ES_API)
{
}
void QAndroidOpenGLContext::swapBuffers(QPlatformSurface *surface)
void QAndroidPlatformOpenGLContext::swapBuffers(QPlatformSurface *surface)
{
QEglFSContext::swapBuffers(surface);
QEGLPlatformContext::swapBuffers(surface);
if (surface->surface()->surfaceClass() == QSurface::Window) {
QAndroidOpenGLPlatformWindow *window = static_cast<QAndroidOpenGLPlatformWindow *>(surface);
window->lock();
QSize size = window->scheduledResize();
if (size.isValid()) {
QRect geometry(QPoint(0, 0), size);
window->setGeometry(geometry);
QWindowSystemInterface::handleGeometryChange(window->window(), geometry);
QWindowSystemInterface::handleExposeEvent(window->window(), QRegion(geometry));
window->scheduleResize(QSize());
}
window->unlock();
}
if (surface->surface()->surfaceClass() == QSurface::Window)
static_cast<QAndroidPlatformOpenGLWindow *>(surface)->checkNativeSurface(eglConfig());
}
bool QAndroidOpenGLContext::makeCurrent(QPlatformSurface *surface)
bool QAndroidPlatformOpenGLContext::makeCurrent(QPlatformSurface *surface)
{
bool ret = QEglFSContext::makeCurrent(surface);
bool ret = QEGLPlatformContext::makeCurrent(surface);
const char *rendererString = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
if (rendererString != 0 && qstrncmp(rendererString, "Android Emulator", 16) == 0) {
@ -92,4 +74,11 @@ bool QAndroidOpenGLContext::makeCurrent(QPlatformSurface *surface)
return ret;
}
EGLSurface QAndroidPlatformOpenGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface)
{
if (surface->surface()->surfaceClass() == QSurface::Window)
return static_cast<QAndroidPlatformOpenGLWindow *>(surface)->eglSurface(eglConfig());
return EGL_NO_SURFACE;
}
QT_END_NAMESPACE

View File

@ -1,5 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
@ -39,31 +40,24 @@
**
****************************************************************************/
#ifndef QANDROIDOPENGLCONTEXT_H
#define QANDROIDOPENGLCONTEXT_H
#ifndef QANDROIDPLATFORMOPENGLCONTEXT_H
#define QANDROIDPLATFORMOPENGLCONTEXT_H
#include <QtCore/qreadwritelock.h>
#include "qeglfscontext.h"
#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
QT_BEGIN_NAMESPACE
class QAndroidPlatformIntegration;
class QAndroidOpenGLContext : public QEglFSContext
class QAndroidPlatformOpenGLContext : public QEGLPlatformContext
{
public:
QAndroidOpenGLContext(const QAndroidPlatformIntegration *integration,
const QSurfaceFormat &format,
QPlatformOpenGLContext *share,
EGLDisplay display,
EGLenum eglApi = EGL_OPENGL_ES_API);
QAndroidPlatformOpenGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display);
void swapBuffers(QPlatformSurface *surface);
bool makeCurrent(QPlatformSurface *surface);
private:
const QAndroidPlatformIntegration *m_platformIntegration;
virtual EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface);
};
QT_END_NAMESPACE
#endif // QANDROIDOPENGLCONTEXT_H
#endif // QANDROIDPLATFORMOPENGLCONTEXT_H

View File

@ -0,0 +1,160 @@
/****************************************************************************
**
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2013 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 "qandroidplatformopenglwindow.h"
#include "androidjnimain.h"
#include <QSurfaceFormat>
#include <qpa/qwindowsysteminterface.h>
#include <android/native_window.h>
#include <android/native_window_jni.h>
#warning remove me
#include <QDebug>
QT_BEGIN_NAMESPACE
QAndroidPlatformOpenGLWindow::QAndroidPlatformOpenGLWindow(QWindow *window, EGLDisplay display)
:QAndroidPlatformWindow(window), m_eglDisplay(display)
{
lockSurface();
m_nativeSurfaceId = QtAndroid::createSurface(this, geometry(), bool(window->flags() & Qt::WindowStaysOnTopHint));
m_surfaceWaitCondition.wait(&m_surfaceMutex);
unlockSurface();
}
QAndroidPlatformOpenGLWindow::~QAndroidPlatformOpenGLWindow()
{
m_surfaceWaitCondition.wakeOne();
lockSurface();
if (m_nativeSurfaceId != -1)
QtAndroid::destroySurface(m_nativeSurfaceId);
clearEgl();
unlockSurface();
}
void QAndroidPlatformOpenGLWindow::setGeometry(const QRect &rect)
{
if (rect == geometry())
return;
qDebug() << rect;
QAndroidPlatformWindow::setGeometry(rect);
QtAndroid::setSurfaceGeometry(m_nativeSurfaceId, rect);
}
EGLSurface QAndroidPlatformOpenGLWindow::eglSurface(EGLConfig config)
{
QMutexLocker lock(&m_surfaceMutex);
if (m_eglSurface == EGL_NO_SURFACE) {
m_surfaceMutex.unlock();
checkNativeSurface(config);
m_surfaceMutex.lock();
}
return m_eglSurface;
}
void QAndroidPlatformOpenGLWindow::checkNativeSurface(EGLConfig config)
{
QMutexLocker lock(&m_surfaceMutex);
qDebug() << geometry() << m_changedAndroidSurface.isValid();
if (m_nativeSurfaceId == -1 || !m_changedAndroidSurface.isValid())
return;
createEgl(config);
// we've create another surface, the window should be repainted
QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry()));
}
void QAndroidPlatformOpenGLWindow::createEgl(EGLConfig config)
{
clearEgl();
m_androidSurface = QJNIObjectPrivate();
m_androidSurface = m_changedAndroidSurface;
m_changedAndroidSurface = QJNIObjectPrivate();
QJNIEnvironmentPrivate env;
m_nativeWindow = ANativeWindow_fromSurface(env, m_androidSurface.object());
if (m_nativeWindow)
ANativeWindow_acquire(m_nativeWindow);
m_eglSurface = eglCreateWindowSurface(m_eglDisplay, config, m_nativeWindow, NULL);
if (m_eglSurface == EGL_NO_SURFACE) {
EGLint error = eglGetError();
eglTerminate(m_eglDisplay);
qFatal("EGL Error : Could not create the egl surface: error = 0x%x\n", error);
}
}
void QAndroidPlatformOpenGLWindow::clearEgl()
{
eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (m_eglSurface != EGL_NO_SURFACE) {
eglDestroySurface(m_eglDisplay, m_eglSurface);
m_eglSurface = EGL_NO_SURFACE;
}
if (m_nativeWindow) {
ANativeWindow_release(m_nativeWindow);
m_nativeWindow = 0;
}
}
void QAndroidPlatformOpenGLWindow::surfaceChanged(JNIEnv *jniEnv, jobject surface, int w, int h)
{
Q_UNUSED(jniEnv);
Q_UNUSED(w);
Q_UNUSED(h);
qDebug() << w << h;
lockSurface();
m_changedAndroidSurface = surface;
m_surfaceWaitCondition.wakeOne();
unlockSurface();
// repaint the window
QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry()));
}
QT_END_NAMESPACE

View File

@ -1,5 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
@ -39,53 +40,44 @@
**
****************************************************************************/
#ifndef QANDROIDOPENGLPLATFORMWINDOW_H
#define QANDROIDOPENGLPLATFORMWINDOW_H
#ifndef QANDROIDPLATFORMOPENGLWINDOW_H
#define QANDROIDPLATFORMOPENGLWINDOW_H
#include "qeglfswindow.h"
#include <QtCore/qmutex.h>
#include <QtCore/qreadwritelock.h>
#include <EGL/egl.h>
#include <QWaitCondition>
#include <QtCore/private/qjni_p.h>
#include "androidsurfaceclient.h"
#include "qandroidplatformwindow.h"
QT_BEGIN_NAMESPACE
class QAndroidOpenGLPlatformWindow : public QEglFSWindow
class QAndroidPlatformOpenGLWindow : public QAndroidPlatformWindow, public AndroidSurfaceClient
{
public:
QAndroidOpenGLPlatformWindow(QWindow *window);
~QAndroidOpenGLPlatformWindow();
explicit QAndroidPlatformOpenGLWindow(QWindow *window, EGLDisplay display);
~QAndroidPlatformOpenGLWindow();
QSize scheduledResize() const { return m_scheduledResize; }
void scheduleResize(const QSize &size) { m_scheduledResize = size; }
void setGeometry(const QRect &rect);
EGLSurface eglSurface(EGLConfig config);
void lock() { m_lock.lock(); }
void unlock() { m_lock.unlock(); }
void checkNativeSurface(EGLConfig config);
bool isExposed() const;
void raise();
void invalidateSurface();
void resetSurface();
void setWindowState(Qt::WindowState state);
void setVisible(bool visible);
void destroy();
static void updateStaticNativeWindow();
void updateStatusBarVisibility();
protected:
virtual void surfaceChanged(JNIEnv *jniEnv, jobject surface, int w, int h);
void createEgl(EGLConfig config);
void clearEgl();
private:
QSize m_scheduledResize;
QMutex m_lock;
Qt::WindowState m_state;
EGLDisplay m_eglDisplay;
EGLSurface m_eglSurface = EGL_NO_SURFACE;
EGLNativeWindowType m_nativeWindow = nullptr;
static QReadWriteLock m_staticSurfaceLock;
static EGLSurface m_staticSurface;
static EGLNativeWindowType m_staticNativeWindow;
static QBasicAtomicInt m_referenceCount;
int m_nativeSurfaceId = -1;
QJNIObjectPrivate m_androidSurface;
QJNIObjectPrivate m_changedAndroidSurface;
QWaitCondition m_surfaceWaitCondition;
};
QT_END_NAMESPACE
#endif // QANDROIDOPENGLPLATFORMWINDOW_H
#endif // QANDROIDPLATFORMOPENGLWINDOW_H

View File

@ -0,0 +1,78 @@
/****************************************************************************
**
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2013 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 "qandroidplatformrasterwindow.h"
#include "qandroidplatformscreen.h"
QT_BEGIN_NAMESPACE
QAndroidPlatformRasterWindow::QAndroidPlatformRasterWindow(QWindow *window)
:QAndroidPlatformWindow(window)
{
}
void QAndroidPlatformRasterWindow::repaint(const QRegion &region)
{
QRect currentGeometry = geometry();
QRect dirtyClient = region.boundingRect();
QRect dirtyRegion(currentGeometry.left() + dirtyClient.left(),
currentGeometry.top() + dirtyClient.top(),
dirtyClient.width(),
dirtyClient.height());
QRect mOldGeometryLocal = m_oldGeometry;
m_oldGeometry = currentGeometry;
// If this is a move, redraw the previous location
if (mOldGeometryLocal != currentGeometry)
platformScreen()->setDirty(mOldGeometryLocal);
platformScreen()->setDirty(dirtyRegion);
}
void QAndroidPlatformRasterWindow::setGeometry(const QRect &rect)
{
m_oldGeometry = geometry();
QAndroidPlatformWindow::setGeometry(rect);
}
QT_END_NAMESPACE

View File

@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2013 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.
@ -39,24 +40,31 @@
**
****************************************************************************/
#ifndef QANDROIDPLATFORMSCREEN_H
#define QANDROIDPLATFORMSCREEN_H
#ifndef QANDROIDPLATFORMRASTERWINDOW_H
#define QANDROIDPLATFORMRASTERWINDOW_H
#include <QtPlatformSupport/private/qfbscreen_p.h>
#include "qandroidplatformwindow.h"
QT_BEGIN_NAMESPACE
class QAndroidPlatformScreen: public QFbScreen
class QAndroidPlatformBackingStore;
class QAndroidPlatformRasterWindow : public QObject, public QAndroidPlatformWindow
{
Q_OBJECT
public:
QAndroidPlatformScreen();
void topWindowChanged(QWindow *w);
QDpi logicalDpi() const;
Qt::ScreenOrientation orientation() const;
Qt::ScreenOrientation nativeOrientation() const;
QAndroidPlatformRasterWindow(QWindow *window);
void setBackingStore(QAndroidPlatformBackingStore *store) { m_backingStore = store; }
QAndroidPlatformBackingStore *backingStore() const { return m_backingStore; }
void repaint(const QRegion&region);
public slots:
QRegion doRedraw();
void setGeometry(const QRect &rect);
private:
QAndroidPlatformBackingStore *m_backingStore = nullptr;
QRect m_oldGeometry;
};
#endif
QT_END_NAMESPACE
#endif // QANDROIDPLATFORMRASTERWINDOW_H

View File

@ -0,0 +1,352 @@
/****************************************************************************
**
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2013 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 <QDebug>
#include <QTime>
#include <qpa/qwindowsysteminterface.h>
#include "qandroidplatformscreen.h"
#include "qandroidplatformbackingstore.h"
#include "qandroidplatformintegration.h"
#include "androidjnimain.h"
#include "androidjnimenu.h"
#include "qandroidplatformrasterwindow.h"
#include <android/bitmap.h>
QT_BEGIN_NAMESPACE
#warning REMOVE ME
class ScopedProfiler
{
public:
ScopedProfiler(const QString &msg)
{
m_msg = msg;
}
~ScopedProfiler()
{
qDebug() << m_msg << m_timer.elapsed();
}
private:
QTime m_timer;
QString m_msg;
};
#define PROFILE_SCOPE ScopedProfiler ___sp___(__func__)
QAndroidPlatformScreen::QAndroidPlatformScreen():QObject(),QPlatformScreen()
{
m_geometry = QRect(0, 0, QAndroidPlatformIntegration::m_defaultGeometryWidth, QAndroidPlatformIntegration::m_defaultGeometryHeight);
// Raster only apps should set QT_ANDROID_RASTER_IMAGE_DEPTH to 16
// is way much faster than 32
if (qgetenv("QT_ANDROID_RASTER_IMAGE_DEPTH").toInt() == 16) {
m_format = QImage::Format_RGB16;
m_depth = 16;
} else {
m_format = QImage::Format_RGBA8888;
m_depth = 32;
}
m_physicalSize.setHeight(QAndroidPlatformIntegration::m_defaultPhysicalSizeHeight);
m_physicalSize.setWidth(QAndroidPlatformIntegration::m_defaultPhysicalSizeWidth);
m_redrawTimer.setSingleShot(true);
m_redrawTimer.setInterval(0);
connect(&m_redrawTimer, SIGNAL(timeout()), this, SLOT(doRedraw()));
}
QAndroidPlatformScreen::~QAndroidPlatformScreen()
{
if (m_id != -1) {
QtAndroid::destroySurface(m_id);
m_surfaceWaitCondition.wakeOne();
if (m_bitmap)
QtAndroid::AttachedJNIEnv().jniEnv->DeleteGlobalRef(m_bitmap);
}
}
QWindow *QAndroidPlatformScreen::topWindow() const
{
foreach (QAndroidPlatformWindow *w, m_windowStack)
if (w->window()->type() == Qt::Window || w->window()->type() == Qt::Dialog)
return w->window();
return 0;
}
QWindow *QAndroidPlatformScreen::topLevelAt(const QPoint &p) const
{
foreach (QAndroidPlatformWindow *w, m_windowStack) {
if (w->geometry().contains(p, false) && w->window()->isVisible())
return w->window();
}
return 0;
}
void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window)
{
m_windowStack.prepend(window);
if (window->isRaster())
setDirty(window->geometry());
QWindow *w = topWindow();
QWindowSystemInterface::handleWindowActivated(w);
topWindowChanged(w);
}
void QAndroidPlatformScreen::removeWindow(QAndroidPlatformWindow *window)
{
m_windowStack.removeOne(window);
if (window->isRaster()) {
setDirty(window->geometry());
}
QWindow *w = topWindow();
QWindowSystemInterface::handleWindowActivated(w);
topWindowChanged(w);
}
void QAndroidPlatformScreen::raise(QAndroidPlatformWindow *window)
{
int index = m_windowStack.indexOf(window);
if (index <= 0)
return;
m_windowStack.move(index, 0);
if (window->isRaster()) {
setDirty(window->geometry());
}
QWindow *w = topWindow();
QWindowSystemInterface::handleWindowActivated(w);
topWindowChanged(w);
}
void QAndroidPlatformScreen::lower(QAndroidPlatformWindow *window)
{
int index = m_windowStack.indexOf(window);
if (index == -1 || index == (m_windowStack.size() - 1))
return;
m_windowStack.move(index, m_windowStack.size() - 1);
if (window->isRaster()) {
setDirty(window->geometry());
}
QWindow *w = topWindow();
QWindowSystemInterface::handleWindowActivated(w);
topWindowChanged(w);
}
void QAndroidPlatformScreen::scheduleUpdate()
{
if (!m_redrawTimer.isActive())
m_redrawTimer.start();
}
void QAndroidPlatformScreen::setDirty(const QRect &rect)
{
QRect intersection = rect.intersected(m_geometry);
QPoint screenOffset = m_geometry.topLeft();
m_repaintRegion += intersection.translated(-screenOffset); // global to local translation
scheduleUpdate();
}
void QAndroidPlatformScreen::setPhysicalSize(const QSize &size)
{
m_physicalSize = size;
}
void QAndroidPlatformScreen::setGeometry(const QRect &rect)
{
QMutexLocker lock(&m_surfaceMutex);
if (m_geometry == rect)
return;
m_geometry = rect;
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry());
QWindowSystemInterface::handleScreenAvailableGeometryChange(QPlatformScreen::screen(), availableGeometry());
resizeMaximizedWindows();
if (m_id != -1) {
if (m_bitmap) {
QtAndroid::AttachedJNIEnv().jniEnv->DeleteGlobalRef(m_bitmap);
m_bitmap = 0;
}
QtAndroid::setSurfaceGeometry(m_id, rect);
}
}
void QAndroidPlatformScreen::topWindowChanged(QWindow *w)
{
QtAndroidMenu::setActiveTopLevelWindow(w);
if (w != 0) {
QAndroidPlatformWindow *platformWindow = static_cast<QAndroidPlatformWindow *>(w->handle());
if (platformWindow != 0)
platformWindow->updateStatusBarVisibility();
}
}
void QAndroidPlatformScreen::doRedraw()
{
PROFILE_SCOPE;
if (m_repaintRegion.isEmpty())
return;
QVector<QRect> rects = m_repaintRegion.rects();
QMutexLocker lock(&m_surfaceMutex);
if (m_id == -1) {
m_id = QtAndroid::createSurface(this, m_geometry, true);
m_surfaceWaitCondition.wait(&m_surfaceMutex);
}
if (!m_bitmap || !m_surface.isValid())
return;
QJNIEnvironmentPrivate env;
if (!env)
return;
int ret;
void *pixels;
if ((ret = AndroidBitmap_lockPixels(env, m_bitmap, &pixels)) < 0) {
qWarning() << "AndroidBitmap_lockPixels() failed! error=" << ret;
return;
}
QImage mScreenImage(reinterpret_cast<uchar *>(pixels), m_bitmapWidth, m_bitmapHeight, m_bitmapStride, m_format);
QPainter mCompositePainter(&mScreenImage);
for (int rectIndex = 0; rectIndex < rects.size(); rectIndex++) {
QRegion visibleRegion = rects[rectIndex];
foreach (QAndroidPlatformWindow *window, m_windowStack) {
if (!window->window()->isVisible()
|| !window->isRaster())
continue;
foreach (const QRect &rect, visibleRegion.rects()) {
QRect targetRect = window->geometry();
targetRect &= rect;
if (targetRect.isNull())
continue;
visibleRegion -= targetRect;
QRect windowRect = targetRect.translated(-window->geometry().topLeft());
QAndroidPlatformBackingStore *backingStore = static_cast<QAndroidPlatformRasterWindow *>(window)->backingStore();
if (backingStore)
mCompositePainter.drawImage(targetRect, backingStore->image(), windowRect);
}
}
foreach (const QRect &rect, visibleRegion.rects())
mCompositePainter.fillRect(rect, Qt::transparent);
}
QRect br = m_repaintRegion.boundingRect();
m_repaintRegion = QRegion();
AndroidBitmap_unlockPixels(env, m_bitmap);
QJNIObjectPrivate jrect("android.graphics.Rect", "(IIII)V",
jint(br.left()),
jint(br.top()),
jint(br.right() + 1),
jint(br.bottom() + 1));
QJNIObjectPrivate canvas = m_surface.callObjectMethod("lockCanvas",
"(Landroid/graphics/Rect;)Landroid/graphics/Canvas;",
jrect.object());
if (!canvas.isValid()) {
qWarning() << "Can't lockCanvas";
return;
}
canvas.callMethod<void>("drawBitmap",
"(Landroid/graphics/Bitmap;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Paint;)V",
m_bitmap, jrect.object(), jrect.object(), jobject(0));
m_surface.callMethod<void>("unlockCanvasAndPost", "(Landroid/graphics/Canvas;)V", canvas.object());
}
QDpi QAndroidPlatformScreen::logicalDpi() const
{
qreal lDpi = QtAndroid::scaledDensity() * 72;
return QDpi(lDpi, lDpi);
}
Qt::ScreenOrientation QAndroidPlatformScreen::orientation() const
{
return QAndroidPlatformIntegration::m_orientation;
}
Qt::ScreenOrientation QAndroidPlatformScreen::nativeOrientation() const
{
return QAndroidPlatformIntegration::m_nativeOrientation;
}
void QAndroidPlatformScreen::surfaceChanged(JNIEnv *env, jobject surface, int w, int h)
{
lockSurface();
m_surface = surface;
if (surface && w && h) {
if (w != m_bitmapWidth || h != m_bitmapHeight) {
if (m_bitmap)
env->DeleteGlobalRef(m_bitmap);
m_bitmap = env->NewGlobalRef(QtAndroid::createBitmap(w, h, m_format, env));
AndroidBitmapInfo info;
int res = AndroidBitmap_getInfo(env, m_bitmap, &info);
Q_ASSERT(res > -1);
m_bitmapStride = info.stride;
m_bitmapWidth = info.width;
m_bitmapHeight = info.height;
}
} else {
if (m_bitmap) {
env->DeleteGlobalRef(m_bitmap);
m_bitmap = 0;
}
}
unlockSurface();
m_surfaceWaitCondition.wakeOne();
}
QT_END_NAMESPACE

View File

@ -0,0 +1,120 @@
/****************************************************************************
**
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2013 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 QANDROIDPLATFORMSCREEN_H
#define QANDROIDPLATFORMSCREEN_H
#include <qpa/qplatformscreen.h>
#include <QList>
#include <QPainter>
#include <QTimer>
#include <QWaitCondition>
#include <QtCore/private/qjni_p.h>
#include "androidsurfaceclient.h"
QT_BEGIN_NAMESPACE
class QAndroidPlatformWindow;
class QAndroidPlatformBackingStore;
class QAndroidPlatformScreen: public QObject, public QPlatformScreen, public AndroidSurfaceClient
{
Q_OBJECT
public:
QAndroidPlatformScreen();
~QAndroidPlatformScreen();
QRect geometry() const { return m_geometry; }
int depth() const { return m_depth; }
QImage::Format format() const { return m_format; }
QSizeF physicalSize() const { return m_physicalSize; }
inline QWindow *topWindow() const;
QWindow *topLevelAt(const QPoint & p) const;
// compositor api
void addWindow(QAndroidPlatformWindow *window);
void removeWindow(QAndroidPlatformWindow *window);
void raise(QAndroidPlatformWindow *window);
void lower(QAndroidPlatformWindow *window);
void scheduleUpdate();
void topWindowChanged(QWindow *w);
public slots:
void setDirty(const QRect &rect);
void setPhysicalSize(const QSize &size);
void setGeometry(const QRect &rect);
protected:
typedef QList<QAndroidPlatformWindow *> WindowStackType;
WindowStackType m_windowStack;
QRegion m_repaintRegion;
QTimer m_redrawTimer;
QRect m_geometry;
int m_depth;
QImage::Format m_format;
QSizeF m_physicalSize;
private:
QDpi logicalDpi() const;
Qt::ScreenOrientation orientation() const;
Qt::ScreenOrientation nativeOrientation() const;
void surfaceChanged(JNIEnv *env, jobject surface, int w, int h);
private slots:
void doRedraw();
private:
int m_id = -1;
QJNIObjectPrivate m_surface;
jobject m_bitmap = nullptr;
QWaitCondition m_surfaceWaitCondition;
int m_bitmapStride = -1;
int m_bitmapWidth = -1;
int m_bitmapHeight = -1;
};
QT_END_NAMESPACE
#endif

View File

@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2013 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.
@ -40,52 +41,39 @@
****************************************************************************/
#include "qandroidplatformwindow.h"
#include "qandroidplatformopenglcontext.h"
#include "qandroidplatformscreen.h"
#include "androidjnimain.h"
#include <qpa/qwindowsysteminterface.h>
QT_BEGIN_NAMESPACE
QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window)
: QFbWindow(window)
: QPlatformWindow(window)
{
m_windowFlags = Qt::Widget;
m_windowState = Qt::WindowNoState;
static QAtomicInt winIdGenerator(1);
m_windowId = winIdGenerator.fetchAndAddRelaxed(1);
setWindowState(window->windowState());
}
void QAndroidPlatformWindow::setGeometry(const QRect &rect)
void QAndroidPlatformWindow::lower()
{
QFbWindow::setGeometry(rect);
}
void QAndroidPlatformWindow::propagateSizeHints()
{
//shut up warning from default implementation
}
void QAndroidPlatformWindow::updateStatusBarVisibility()
{
Qt::WindowFlags flags = window()->flags();
bool isNonRegularWindow = flags & (Qt::Popup | Qt::Dialog | Qt::Sheet) & ~Qt::Window;
if (!isNonRegularWindow) {
if (mWindowState & Qt::WindowFullScreen)
QtAndroid::hideStatusBar();
else if (mWindowState & Qt::WindowMaximized)
QtAndroid::showStatusBar();
}
platformScreen()->lower(this);
}
void QAndroidPlatformWindow::raise()
{
updateStatusBarVisibility();
QFbWindow::raise();
platformScreen()->raise(this);
}
void QAndroidPlatformWindow::setWindowState(Qt::WindowState state)
void QAndroidPlatformWindow::setGeometry(const QRect &rect)
{
if (mWindowState == state)
return;
if (window()->isVisible())
updateStatusBarVisibility();
QFbWindow::setWindowState(state);
QWindowSystemInterface::handleGeometryChange(window(), rect);
QPlatformWindow::setGeometry(rect);
}
void QAndroidPlatformWindow::setVisible(bool visible)
@ -93,10 +81,77 @@ void QAndroidPlatformWindow::setVisible(bool visible)
if (visible)
updateStatusBarVisibility();
QFbWindow::setVisible(visible);
if (visible) {
if (m_windowState & Qt::WindowFullScreen)
setGeometry(platformScreen()->geometry());
else if (m_windowState & Qt::WindowMaximized)
setGeometry(platformScreen()->availableGeometry());
}
QPlatformWindow::setVisible(visible);
if (visible)
platformScreen()->addWindow(this);
else
platformScreen()->removeWindow(this);
// The Android Activity is activated before Qt is initialized, causing the application state to
// never be set to 'active'. We explicitly set this state when the first window becomes visible.
if (visible)
QtAndroid::setApplicationActive();
}
void QAndroidPlatformWindow::setWindowState(Qt::WindowState state)
{
if (m_windowState == state)
return;
QPlatformWindow::setWindowState(state);
m_windowState = state;
if (window()->isVisible())
updateStatusBarVisibility();
}
void QAndroidPlatformWindow::setWindowFlags(Qt::WindowFlags flags)
{
if (m_windowFlags == flags)
return;
m_windowFlags = flags;
}
Qt::WindowFlags QAndroidPlatformWindow::windowFlags() const
{
return m_windowFlags;
}
QAndroidPlatformScreen *QAndroidPlatformWindow::platformScreen() const
{
return static_cast<QAndroidPlatformScreen *>(window()->screen()->handle());
}
void QAndroidPlatformWindow::propagateSizeHints()
{
//shut up warning from default implementation
}
void QAndroidPlatformWindow::requestActivateWindow()
{
platformScreen()->topWindowChanged(window());
}
void QAndroidPlatformWindow::updateStatusBarVisibility()
{
Qt::WindowFlags flags = window()->flags();
bool isNonRegularWindow = flags & (Qt::Popup | Qt::Dialog | Qt::Sheet) & ~Qt::Window;
if (!isNonRegularWindow) {
if (m_windowState & Qt::WindowFullScreen)
QtAndroid::hideStatusBar();
else if (m_windowState & Qt::WindowMaximized)
QtAndroid::showStatusBar();
}
}
QT_END_NAMESPACE

View File

@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2013 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.
@ -42,23 +43,45 @@
#ifndef ANDROIDPLATFORMWINDOW_H
#define ANDROIDPLATFORMWINDOW_H
#include <qobject.h>
#include <QtPlatformSupport/private/qfbwindow_p.h>
#include <qrect.h>
#include <qpa/qplatformwindow.h>
class QAndroidPlatformWindow: public QObject, public QFbWindow
QT_BEGIN_NAMESPACE
class QAndroidPlatformScreen;
class QAndroidPlatformWindow: public QPlatformWindow
{
Q_OBJECT
public:
explicit QAndroidPlatformWindow(QWindow *window);
void propagateSizeHints();
void lower();
void raise();
void setWindowState(Qt::WindowState state);
void setVisible(bool visible);
void updateStatusBarVisibility();
public slots:
void setVisible(bool visible);
void setWindowState(Qt::WindowState state);
void setWindowFlags(Qt::WindowFlags flags);
Qt::WindowFlags windowFlags() const;
WId winId() const { return m_windowId; }
QAndroidPlatformScreen *platformScreen() const;
void propagateSizeHints();
void requestActivateWindow();
void updateStatusBarVisibility();
inline bool isRaster() const { return window()->surfaceType() == QSurface::RasterSurface; }
protected:
void setGeometry(const QRect &rect);
protected:
Qt::WindowFlags m_windowFlags;
Qt::WindowState m_windowState;
WId m_windowId;
};
QT_END_NAMESPACE
#endif // ANDROIDPLATFORMWINDOW_H

View File

@ -1,19 +0,0 @@
TARGET = qtforandroid
PLUGIN_TYPE = platforms
# STATICPLUGIN needed because there's a Q_IMPORT_PLUGIN in androidjnimain.cpp
# Yes, the plugin imports itself statically
DEFINES += QT_STATICPLUGIN
load(qt_plugin)
!contains(ANDROID_PLATFORM, android-9) {
INCLUDEPATH += $$NDK_ROOT/platforms/android-9/arch-$$ANDROID_ARCHITECTURE/usr/include
LIBS += -L$$NDK_ROOT/platforms/android-9/arch-$$ANDROID_ARCHITECTURE/usr/lib -ljnigraphics -landroid
} else {
LIBS += -ljnigraphics -landroid
}
include($$PWD/../src/src.pri)
include($$PWD/../src/raster/raster.pri)

View File

@ -1,178 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2013 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 "qandroidopenglplatformwindow.h"
#include "androidjnimain.h"
#include "qandroidplatformintegration.h"
#include <qpa/qwindowsysteminterface.h>
QT_BEGIN_NAMESPACE
EGLSurface QAndroidOpenGLPlatformWindow::m_staticSurface = 0;
EGLNativeWindowType QAndroidOpenGLPlatformWindow::m_staticNativeWindow = 0;
QReadWriteLock QAndroidOpenGLPlatformWindow::m_staticSurfaceLock;
QBasicAtomicInt QAndroidOpenGLPlatformWindow::m_referenceCount = Q_BASIC_ATOMIC_INITIALIZER(0);
QAndroidOpenGLPlatformWindow::QAndroidOpenGLPlatformWindow(QWindow *window)
: QEglFSWindow(window)
, m_state(Qt::WindowNoState)
{
}
QAndroidOpenGLPlatformWindow::~QAndroidOpenGLPlatformWindow()
{
destroy();
}
bool QAndroidOpenGLPlatformWindow::isExposed() const
{
return QtAndroid::nativeWindow(false) != 0 && QEglFSWindow::isExposed();
}
void QAndroidOpenGLPlatformWindow::invalidateSurface()
{
QWindowSystemInterface::handleExposeEvent(window(), QRegion()); // Obscure event
QWindowSystemInterface::flushWindowSystemEvents();
m_window = 0;
m_surface = 0;
if (!m_referenceCount.deref()){
QWriteLocker locker(&m_staticSurfaceLock);
EGLDisplay display = (static_cast<QEglFSScreen *>(window()->screen()->handle()))->display();
eglDestroySurface(display, m_staticSurface);
m_staticSurface = 0;
m_staticNativeWindow = 0;
}
}
void QAndroidOpenGLPlatformWindow::updateStaticNativeWindow()
{
QWriteLocker locker(&m_staticSurfaceLock);
m_staticNativeWindow = QtAndroid::nativeWindow(false);
}
void QAndroidOpenGLPlatformWindow::resetSurface()
{
// Only add a reference if we're not already holding one, otherwise we're just updating
// the native window pointer
if (m_window == 0)
m_referenceCount.ref();
if (m_staticSurface == 0) {
QWriteLocker locker(&m_staticSurfaceLock);
QEglFSWindow::resetSurface();
m_staticSurface = m_surface;
m_staticNativeWindow = m_window;
} else {
QReadLocker locker(&m_staticSurfaceLock);
m_window = m_staticNativeWindow;
m_surface = m_staticSurface;
}
{
lock();
// Use the desktop size.
// On some devices, the getters for the native window size gives wrong values
scheduleResize(QAndroidPlatformIntegration::defaultDesktopSize());
QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry())); // Expose event
unlock();
}
QWindowSystemInterface::flushWindowSystemEvents();
}
void QAndroidOpenGLPlatformWindow::destroy()
{
if (!m_referenceCount.deref()) {
QEglFSWindow::destroy();
} else {
m_window = 0;
m_surface = 0;
}
}
void QAndroidOpenGLPlatformWindow::updateStatusBarVisibility()
{
Qt::WindowFlags flags = window()->flags();
bool isNonRegularWindow = flags & (Qt::Popup | Qt::Dialog | Qt::Sheet) & ~Qt::Window;
if (!isNonRegularWindow) {
if (m_state & Qt::WindowFullScreen)
QtAndroid::hideStatusBar();
else if (m_state & Qt::WindowMaximized)
QtAndroid::showStatusBar();
}
}
void QAndroidOpenGLPlatformWindow::raise()
{
updateStatusBarVisibility();
}
void QAndroidOpenGLPlatformWindow::setWindowState(Qt::WindowState state)
{
if (m_state == state)
return;
m_state = state;
if (window()->isVisible())
updateStatusBarVisibility();
}
void QAndroidOpenGLPlatformWindow::setVisible(bool visible)
{
if (visible)
updateStatusBarVisibility();
QEglFSWindow::setVisible(visible);
// The Android Activity is activated before Qt is initialized, causing the application state to
// never be set to 'active'. We explicitly set this state when the first window becomes visible.
if (visible)
QtAndroid::setApplicationActive();
QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry())); // Expose event
QWindowSystemInterface::flushWindowSystemEvents();
}
QT_END_NAMESPACE

View File

@ -1,161 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2012 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 "qeglfshooks.h"
#include "androidjnimain.h"
#include "qandroidplatformintegration.h"
#include <android/native_window.h>
#include <jni.h>
QT_BEGIN_NAMESPACE
class QEglFSAndroidHooks: public QEglFSHooks
{
public:
void platformInit();
void platformDestroy();
EGLNativeDisplayType platformDisplay() const;
QSize screenSize() const;
QSizeF physicalScreenSize() const;
QDpi logicalDpi() const;
Qt::ScreenOrientation orientation() const;
Qt::ScreenOrientation nativeOrientation() const;
int screenDepth() const;
QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const;
EGLNativeWindowType createNativeWindow(QPlatformWindow *platformWindow, const QSize &size, const QSurfaceFormat &format);
void destroyNativeWindow(EGLNativeWindowType window);
bool hasCapability(QPlatformIntegration::Capability cap) const;
QEglFSCursor *createCursor(QEglFSScreen *screen) const;
};
void QEglFSAndroidHooks::platformInit()
{
}
void QEglFSAndroidHooks::platformDestroy()
{
}
EGLNativeDisplayType QEglFSAndroidHooks::platformDisplay() const
{
return EGL_DEFAULT_DISPLAY;
}
QSize QEglFSAndroidHooks::screenSize() const
{
return QAndroidPlatformIntegration::defaultDesktopSize();
}
QSizeF QEglFSAndroidHooks::physicalScreenSize() const
{
return QSizeF(QAndroidPlatformIntegration::m_defaultPhysicalSizeWidth, QAndroidPlatformIntegration::m_defaultPhysicalSizeHeight);
}
QDpi QEglFSAndroidHooks::logicalDpi() const
{
qreal lDpi = QtAndroid::scaledDensity() * 72;
return QDpi(lDpi, lDpi);
}
Qt::ScreenOrientation QEglFSAndroidHooks::orientation() const
{
return QAndroidPlatformIntegration::m_orientation;
}
Qt::ScreenOrientation QEglFSAndroidHooks::nativeOrientation() const
{
return QAndroidPlatformIntegration::m_nativeOrientation;
}
EGLNativeWindowType QEglFSAndroidHooks::createNativeWindow(QPlatformWindow *platformWindow, const QSize &size, const QSurfaceFormat &format)
{
Q_UNUSED(platformWindow);
Q_UNUSED(size);
Q_UNUSED(format);
ANativeWindow *window = QtAndroid::nativeWindow();
if (window != 0)
ANativeWindow_acquire(window);
return window;
}
void QEglFSAndroidHooks::destroyNativeWindow(EGLNativeWindowType window)
{
if (window != 0)
ANativeWindow_release(window);
}
bool QEglFSAndroidHooks::hasCapability(QPlatformIntegration::Capability capability) const
{
switch (capability) {
case QPlatformIntegration::OpenGL: return true;
case QPlatformIntegration::ThreadedOpenGL: return true;
default: return false;
};
}
int QEglFSAndroidHooks::screenDepth() const
{
// ### Hardcoded
return 32;
}
QSurfaceFormat QEglFSAndroidHooks::surfaceFormatFor(const QSurfaceFormat &inputFormat) const
{
QSurfaceFormat ret(inputFormat);
ret.setAlphaBufferSize(8);
ret.setRedBufferSize(8);
ret.setGreenBufferSize(8);
ret.setBlueBufferSize(8);
return ret;
}
QEglFSCursor *QEglFSAndroidHooks::createCursor(QEglFSScreen *screen) const
{
Q_UNUSED(screen);
return 0;
}
static QEglFSAndroidHooks eglFSAndroidHooks;
QEglFSHooks *platformHooks = &eglFSAndroidHooks;
QT_END_NAMESPACE

View File

@ -1,94 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
** 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 "qandroidplatformscreen.h"
#include "qandroidplatformintegration.h"
#include "androidjnimain.h"
#include "androidjnimenu.h"
#include "qandroidplatformwindow.h"
QAndroidPlatformScreen::QAndroidPlatformScreen():QFbScreen()
{
mGeometry = QRect(0, 0, QAndroidPlatformIntegration::m_defaultGeometryWidth, QAndroidPlatformIntegration::m_defaultGeometryHeight);
mFormat = QImage::Format_RGB16;
mDepth = 16;
mPhysicalSize.setHeight(QAndroidPlatformIntegration::m_defaultPhysicalSizeHeight);
mPhysicalSize.setWidth(QAndroidPlatformIntegration::m_defaultPhysicalSizeWidth);
initializeCompositor();
}
void QAndroidPlatformScreen::topWindowChanged(QWindow *w)
{
QtAndroidMenu::setActiveTopLevelWindow(w);
if (w != 0) {
QAndroidPlatformWindow *platformWindow = static_cast<QAndroidPlatformWindow *>(w->handle());
if (platformWindow != 0)
platformWindow->updateStatusBarVisibility();
}
}
QRegion QAndroidPlatformScreen::doRedraw()
{
QRegion touched;
touched = QFbScreen::doRedraw();
if (touched.isEmpty())
return touched;
QtAndroid::flushImage(mGeometry.topLeft(), *mScreenImage, touched.boundingRect());
return touched;
}
QDpi QAndroidPlatformScreen::logicalDpi() const
{
qreal lDpi = QtAndroid::scaledDensity() * 72;
return QDpi(lDpi, lDpi);
}
Qt::ScreenOrientation QAndroidPlatformScreen::orientation() const
{
return QAndroidPlatformIntegration::m_orientation;
}
Qt::ScreenOrientation QAndroidPlatformScreen::nativeOrientation() const
{
return QAndroidPlatformIntegration::m_nativeOrientation;
}

View File

@ -1,7 +0,0 @@
INCLUDEPATH += $$PWD
SOURCES += $$PWD/qandroidplatformscreen.cpp \
$$PWD/qandroidplatformwindow.cpp
HEADERS += $$PWD/qandroidplatformscreen.h \
$$PWD/qandroidplatformwindow.h

View File

@ -1,55 +0,0 @@
load(qt_plugin)
QT += core-private gui-private platformsupport-private
CONFIG += qpa/genericunixfontdatabase
OTHER_FILES += $$PWD/android.json
INCLUDEPATH += $$PWD
INCLUDEPATH += $$PWD/../../../../3rdparty/android/src
SOURCES += $$PWD/androidplatformplugin.cpp \
$$PWD/androidjnimain.cpp \
$$PWD/androidjniaccessibility.cpp \
$$PWD/androidjniinput.cpp \
$$PWD/androidjnimenu.cpp \
$$PWD/androidjniclipboard.cpp \
$$PWD/qandroidplatformintegration.cpp \
$$PWD/qandroidplatformservices.cpp \
$$PWD/qandroidassetsfileenginehandler.cpp \
$$PWD/qandroidinputcontext.cpp \
$$PWD/qandroidplatformaccessibility.cpp \
$$PWD/qandroidplatformfontdatabase.cpp \
$$PWD/qandroidplatformdialoghelpers.cpp \
$$PWD/qandroidplatformclipboard.cpp \
$$PWD/qandroidplatformtheme.cpp \
$$PWD/qandroidplatformmenubar.cpp \
$$PWD/qandroidplatformmenu.cpp \
$$PWD/qandroidplatformmenuitem.cpp \
$$PWD/qandroidsystemlocale.cpp
HEADERS += $$PWD/qandroidplatformintegration.h \
$$PWD/androidjnimain.h \
$$PWD/androidjniaccessibility.h \
$$PWD/androidjniinput.h \
$$PWD/androidjnimenu.h \
$$PWD/androidjniclipboard.h \
$$PWD/qandroidplatformservices.h \
$$PWD/qandroidassetsfileenginehandler.h \
$$PWD/qandroidinputcontext.h \
$$PWD/qandroidplatformaccessibility.h \
$$PWD/qandroidplatformfontdatabase.h \
$$PWD/qandroidplatformclipboard.h \
$$PWD/qandroidplatformdialoghelpers.h \
$$PWD/qandroidplatformtheme.h \
$$PWD/qandroidplatformmenubar.h \
$$PWD/qandroidplatformmenu.h \
$$PWD/qandroidplatformmenuitem.h \
$$PWD/qandroidsystemlocale.h
#Non-standard install directory, QTBUG-29859
DESTDIR = $$DESTDIR/android
target.path = $${target.path}/android