diff options
Diffstat (limited to 'src/plugins/platforms/android/src')
28 files changed, 741 insertions, 82 deletions
diff --git a/src/plugins/platforms/android/src/androidjniaccessibility.cpp b/src/plugins/platforms/android/src/androidjniaccessibility.cpp index a27d9f5aed..b987c49c9c 100644 --- a/src/plugins/platforms/android/src/androidjniaccessibility.cpp +++ b/src/plugins/platforms/android/src/androidjniaccessibility.cpp @@ -46,7 +46,7 @@ #include "qguiapplication.h" #include "qwindow.h" #include "qrect.h" -#include "private/qaccessible2_p.h" +#include "QtGui/qaccessible.h" #include "qdebug.h" diff --git a/src/plugins/platforms/android/src/androidjniinput.cpp b/src/plugins/platforms/android/src/androidjniinput.cpp index 30d4e69afe..8ce95532d3 100644 --- a/src/plugins/platforms/android/src/androidjniinput.cpp +++ b/src/plugins/platforms/android/src/androidjniinput.cpp @@ -47,6 +47,10 @@ #include <QTouchEvent> #include <QPointer> +#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL +# include <QDebug> +#endif + using namespace QtAndroid; namespace QtAndroidInput @@ -63,12 +67,32 @@ namespace QtAndroidInput static QPointer<QWindow> m_mouseGrabber; + static int m_lastCursorPos = -1; + void updateSelection(int selStart, int selEnd, int candidatesStart, int candidatesEnd) { AttachedJNIEnv env; if (!env.jniEnv) return; +#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL + qDebug() << ">>> UPDATESELECTION" << selStart << selEnd << candidatesStart << candidatesEnd; +#endif + if (candidatesStart == -1 && candidatesEnd == -1 && selStart == selEnd) { + // Qt only gives us position inside the block, so if we move to the + // same position in another block, the Android keyboard will believe + // we have not changed position, and be terribly confused. + if (selStart == m_lastCursorPos) { +#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL + qDebug() << ">>> FAKEUPDATESELECTION" << selStart+1; +#endif + env.jniEnv->CallStaticVoidMethod(applicationClass(), m_updateSelectionMethodID, + selStart+1, selEnd+1, candidatesStart, candidatesEnd); + } + m_lastCursorPos = selStart; + } else { + m_lastCursorPos = -1; + } env.jniEnv->CallStaticVoidMethod(applicationClass(), m_updateSelectionMethodID, selStart, selEnd, candidatesStart, candidatesEnd); } @@ -86,6 +110,9 @@ namespace QtAndroidInput width, height, inputHints); +#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL + qDebug() << "@@@ SHOWSOFTWAREKEYBOARD" << left << top << width << height << inputHints; +#endif } void resetSoftwareKeyboard() @@ -95,6 +122,9 @@ namespace QtAndroidInput return; env.jniEnv->CallStaticVoidMethod(applicationClass(), m_resetSoftwareKeyboardMethodID); +#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL + qDebug() << "@@@ RESETSOFTWAREKEYBOARD"; +#endif } void hideSoftwareKeyboard() @@ -104,6 +134,9 @@ namespace QtAndroidInput return; env.jniEnv->CallStaticVoidMethod(applicationClass(), m_hideSoftwareKeyboardMethodID); +#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL + qDebug() << "@@@ HIDESOFTWAREKEYBOARD"; +#endif } bool isSoftwareKeyboardVisible() @@ -112,7 +145,11 @@ namespace QtAndroidInput if (!env.jniEnv) return false; - return env.jniEnv->CallStaticBooleanMethod(applicationClass(), m_isSoftwareKeyboardVisibleMethodID); + bool visibility = env.jniEnv->CallStaticBooleanMethod(applicationClass(), m_isSoftwareKeyboardVisibleMethodID); +#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL + qDebug() << "@@@ ISSOFTWAREKEYBOARDVISIBLE" << visibility; +#endif + return visibility; } @@ -511,6 +548,15 @@ namespace QtAndroidInput false); } + static void keyboardVisibilityChanged(JNIEnv */*env*/, jobject /*thiz*/, jboolean /*visibility*/) + { + QAndroidInputContext *inputContext = QAndroidInputContext::androidInputContext(); + if (inputContext) + inputContext->emitInputPanelVisibleChanged(); +#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL + qDebug() << "@@@ KEYBOARDVISIBILITYCHANGED" << inputContext; +#endif + } static JNINativeMethod methods[] = { {"touchBegin","(I)V",(void*)touchBegin}, @@ -521,7 +567,8 @@ namespace QtAndroidInput {"mouseMove", "(III)V", (void *)mouseMove}, {"longPress", "(III)V", (void *)longPress}, {"keyDown", "(III)V", (void *)keyDown}, - {"keyUp", "(III)V", (void *)keyUp} + {"keyUp", "(III)V", (void *)keyUp}, + {"keyboardVisibilityChanged", "(Z)V", (void *)keyboardVisibilityChanged} }; #define GET_AND_CHECK_STATIC_METHOD(VAR, CLASS, METHOD_NAME, METHOD_SIGNATURE) \ diff --git a/src/plugins/platforms/android/src/androidjnimain.cpp b/src/plugins/platforms/android/src/androidjnimain.cpp index 5c9ca798a8..3064e5d4e2 100644 --- a/src/plugins/platforms/android/src/androidjnimain.cpp +++ b/src/plugins/platforms/android/src/androidjnimain.cpp @@ -40,6 +40,7 @@ ** ****************************************************************************/ +#include <QtGui/private/qguiapplication_p.h> #include <dlfcn.h> #include <pthread.h> @@ -59,6 +60,7 @@ #include "androidjniinput.h" #include "androidjniclipboard.h" #include "androidjnimenu.h" +#include "qandroidplatformdialoghelpers.h" #include "qandroidplatformintegration.h" #include <QtWidgets/QApplication> @@ -97,6 +99,9 @@ static jmethodID m_createBitmapMethodID = 0; static jobject m_ARGB_8888_BitmapConfigValue = 0; static jobject m_RGB_565_BitmapConfigValue = 0; +jmethodID m_setFullScreenMethodID = 0; +static bool m_statusBarShowing = true; + static jclass m_bitmapDrawableClass = 0; static jmethodID m_bitmapDrawableConstructorMethodID = 0; @@ -111,8 +116,6 @@ static jobject m_surface = NULL; static EGLNativeWindowType m_nativeWindow = 0; static QSemaphore m_waitForWindowSemaphore; static bool m_waitForWindow = false; - -static jfieldID m_surfaceFieldID = 0; #endif @@ -247,17 +250,6 @@ namespace QtAndroid m_surfaceMutex.unlock(); return m_nativeWindow; } - - QSize nativeWindowSize() - { - if (m_nativeWindow == 0) - return QAndroidPlatformIntegration::defaultDesktopSize(); - - int width = ANativeWindow_getWidth(m_nativeWindow); - int height = ANativeWindow_getHeight(m_nativeWindow); - - return QSize(width, height); - } #endif void setAndroidPlatformIntegration(QAndroidPlatformIntegration *androidPlatformIntegration) @@ -323,6 +315,36 @@ namespace QtAndroid return m_activityObject; } + void showStatusBar() + { + if (m_statusBarShowing) + return; + + QtAndroid::AttachedJNIEnv env; + if (env.jniEnv == 0) { + qWarning("Failed to get JNI Environment."); + return; + } + + env.jniEnv->CallStaticVoidMethod(m_applicationClass, m_setFullScreenMethodID, false); + m_statusBarShowing = true; + } + + void hideStatusBar() + { + if (!m_statusBarShowing) + return; + + QtAndroid::AttachedJNIEnv env; + if (env.jniEnv == 0) { + qWarning("Failed to get JNI Environment."); + return; + } + + env.jniEnv->CallStaticVoidMethod(m_applicationClass, m_setFullScreenMethodID, true); + m_statusBarShowing = false; + } + void setApplicationActive() { if (m_activityActive) @@ -564,12 +586,16 @@ static void setSurface(JNIEnv *env, jobject /*thiz*/, jobject jSurface) m_waitForWindowSemaphore.release(); if (m_androidPlatformIntegration) { - QSize size = QtAndroid::nativeWindowSize(); + // 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); - QWindowSystemInterface::handleScreenAvailableGeometryChange(screen->screen(), geometry); - QWindowSystemInterface::handleScreenGeometryChange(screen->screen(), geometry); + if (screen) { + QWindowSystemInterface::handleScreenAvailableGeometryChange(screen->screen(), geometry); + QWindowSystemInterface::handleScreenGeometryChange(screen->screen(), geometry); + } if (!sameNativeWindow) { m_surfaceMutex.unlock(); @@ -666,7 +692,7 @@ static void updateApplicationState(JNIEnv */*env*/, jobject /*thiz*/, jint state { m_activityActive = (state == Qt::ApplicationActive); - if (!m_androidPlatformIntegration) + if (!m_androidPlatformIntegration || !QGuiApplicationPrivate::platformIntegration()) return; QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState(state)); @@ -762,6 +788,7 @@ static int registerNatives(JNIEnv *env) jclass clazz; FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/QtNative"); m_applicationClass = static_cast<jclass>(env->NewGlobalRef(clazz)); + GET_AND_CHECK_STATIC_METHOD(m_setFullScreenMethodID, m_applicationClass, "setFullScreen", "(Z)V"); if (env->RegisterNatives(m_applicationClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) { __android_log_print(ANDROID_LOG_FATAL,"Qt", "RegisterNatives failed"); @@ -770,11 +797,6 @@ static int registerNatives(JNIEnv *env) GET_AND_CHECK_STATIC_METHOD(m_redrawSurfaceMethodID, m_applicationClass, "redrawSurface", "(IIII)V"); -#ifdef ANDROID_PLUGIN_OPENGL - FIND_AND_CHECK_CLASS("android/view/Surface"); - GET_AND_CHECK_FIELD(m_surfaceFieldID, clazz, "mNativeSurface", "I"); -#endif - jmethodID methodID; GET_AND_CHECK_STATIC_METHOD(methodID, m_applicationClass, "activity", "()Landroid/app/Activity;"); jobject activityObject = env->CallStaticObjectMethod(m_applicationClass, methodID); @@ -814,6 +836,15 @@ static int registerNatives(JNIEnv *env) return JNI_TRUE; } +jint androidApiLevel(JNIEnv *env) +{ + jclass clazz; + FIND_AND_CHECK_CLASS("android/os/Build$VERSION"); + jfieldID fieldId; + GET_AND_CHECK_STATIC_FIELD(fieldId, clazz, "SDK_INT", "I"); + return env->GetStaticIntField(clazz, fieldId); +} + Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/) { typedef union { @@ -836,11 +867,18 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/) || !QtAndroidInput::registerNatives(env) || !QtAndroidClipboard::registerNatives(env) || !QtAndroidMenu::registerNatives(env) - || !QtAndroidAccessibility::registerNatives(env)) { + || !QtAndroidAccessibility::registerNatives(env) + || !QtAndroidDialogHelpers::registerNatives(env)) { __android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed"); return -1; } + jint apiLevel = androidApiLevel(env); + if (apiLevel >= 16 && !QtAndroidAccessibility::registerNatives(env)) { + __android_log_print(ANDROID_LOG_FATAL, "Qt A11y", "registerNatives failed"); + return -1; + } + m_javaVM = vm; return JNI_VERSION_1_4; } diff --git a/src/plugins/platforms/android/src/androidjnimain.h b/src/plugins/platforms/android/src/androidjnimain.h index 9a3d8a9607..11d3573404 100644 --- a/src/plugins/platforms/android/src/androidjnimain.h +++ b/src/plugins/platforms/android/src/androidjnimain.h @@ -69,13 +69,10 @@ namespace QtAndroid void setAndroidPlatformIntegration(QAndroidPlatformIntegration *androidPlatformIntegration); void setQtThread(QThread *thread); - void setFullScreen(QWidget *widget); - #ifndef ANDROID_PLUGIN_OPENGL void flushImage(const QPoint &pos, const QImage &image, const QRect &rect); #else EGLNativeWindowType nativeWindow(bool waitToCreate = true); - QSize nativeWindowSize(); #endif QWindow *topLevelWindowAt(const QPoint &globalPos); @@ -90,6 +87,9 @@ namespace QtAndroid void setApplicationActive(); + void showStatusBar(); + void hideStatusBar(); + jobject createBitmap(QImage img, JNIEnv *env = 0); jobject createBitmapDrawable(jobject bitmap, JNIEnv *env = 0); diff --git a/src/plugins/platforms/android/src/androidjnimenu.cpp b/src/plugins/platforms/android/src/androidjnimenu.cpp index bb180347c1..293af2b9cd 100644 --- a/src/plugins/platforms/android/src/androidjnimenu.cpp +++ b/src/plugins/platforms/android/src/androidjnimenu.cpp @@ -41,13 +41,14 @@ #include "androidjnimenu.h" #include "androidjnimain.h" -#include <qmutex.h> -#include <qset.h> -#include <qqueue.h> -#include <android/log.h> #include "qandroidplatformmenubar.h" #include "qandroidplatformmenu.h" -#include <qandroidplatformmenuitem.h> +#include "qandroidplatformmenuitem.h" + +#include <QMutex> +#include <QSet> +#include <QQueue> +#include <QWindow> using namespace QtAndroid; @@ -141,18 +142,17 @@ namespace QtAndroidMenu void setActiveTopLevelWindow(QWindow *window) { + Qt::WindowFlags flags = window ? window->flags() : Qt::WindowFlags(); + bool isNonRegularWindow = flags & (Qt::Desktop | Qt::Popup | Qt::Dialog | Qt::Sheet) & ~Qt::Window; + if (isNonRegularWindow) + return; + QMutexLocker lock(&menuBarMutex); if (activeTopLevelWindow == window) return; visibleMenuBar = 0; activeTopLevelWindow = window; -#ifdef ANDROID_PLUGIN_OPENGL - //only one toplevel window, so the menu bar always belongs to us - if (menuBars.size() == 1) { - visibleMenuBar = *menuBars.constBegin(); //since QSet doesn't have first() - } else -#endif foreach (QAndroidPlatformMenuBar *menuBar, menuBars) { if (menuBar->parentWindow() == window) { visibleMenuBar = menuBar; @@ -173,8 +173,10 @@ namespace QtAndroidMenu { QMutexLocker lock(&menuBarMutex); menuBars.remove(menuBar); - if (visibleMenuBar == menuBar) + if (visibleMenuBar == menuBar) { + visibleMenuBar = 0; resetMenuBar(); + } } static QString removeAmpersandEscapes(QString s) @@ -197,16 +199,18 @@ namespace QtAndroidMenu env->CallObjectMethod(menuItem, setCheckedMenuItemMethodID, checked); env->CallObjectMethod(menuItem, setEnabledMenuItemMethodID, enabled); - if (!icon.isNull()) { + if (!icon.isNull()) { // isNull() only checks the d pointer, not the actual image data. int sz = qMax(36, qgetenv("QT_ANDROID_APP_ICON_SIZE").toInt()); QImage img = icon.pixmap(QSize(sz,sz), enabled ? QIcon::Normal : QIcon::Disabled, QIcon::On).toImage(); - env->CallObjectMethod(menuItem, - setIconMenuItemMethodID, - createBitmapDrawable(createBitmap(img, env), env)); + if (!img.isNull()) { // Make sure we have a valid image. + env->CallObjectMethod(menuItem, + setIconMenuItemMethodID, + createBitmapDrawable(createBitmap(img, env), env)); + } } env->CallObjectMethod(menuItem, setVisibleMenuItemMethodID, visible); diff --git a/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.cpp b/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.cpp index 9d6d4003f7..6431914812 100644 --- a/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.cpp +++ b/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.cpp @@ -71,6 +71,8 @@ void QAndroidOpenGLContext::swapBuffers(QPlatformSurface *surface) 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(); diff --git a/src/plugins/platforms/android/src/opengl/qandroidopenglplatformscreen.cpp b/src/plugins/platforms/android/src/opengl/qandroidopenglplatformscreen.cpp new file mode 100644 index 0000000000..de4075feff --- /dev/null +++ b/src/plugins/platforms/android/src/opengl/qandroidopenglplatformscreen.cpp @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** 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 "qandroidopenglplatformscreen.h" +#include "qandroidopenglplatformwindow.h" +#include "androidjnimenu.h" + +QT_BEGIN_NAMESPACE + +QAndroidOpenGLPlatformScreen::QAndroidOpenGLPlatformScreen(EGLDisplay display) + : QEglFSScreen(display) +{ +} + +void QAndroidOpenGLPlatformScreen::topWindowChanged(QPlatformWindow *window) +{ + QtAndroidMenu::setActiveTopLevelWindow(window->window()); + QAndroidOpenGLPlatformWindow *platformWindow = static_cast<QAndroidOpenGLPlatformWindow *>(window); + if (platformWindow != 0) + platformWindow->updateStatusBarVisibility(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/src/opengl/qandroidopenglplatformscreen.h b/src/plugins/platforms/android/src/opengl/qandroidopenglplatformscreen.h new file mode 100644 index 0000000000..e9251592aa --- /dev/null +++ b/src/plugins/platforms/android/src/opengl/qandroidopenglplatformscreen.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** 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 QANDROIDOPENGLPLATFORMSCREEN_H +#define QANDROIDOPENGLPLATFORMSCREEN_H + +#include "qeglfsscreen.h" + +QT_BEGIN_NAMESPACE + +class QAndroidOpenGLPlatformScreen : public QEglFSScreen +{ +public: + QAndroidOpenGLPlatformScreen(EGLDisplay display); + +protected: + void topWindowChanged(QPlatformWindow *window); +}; + +QT_END_NAMESPACE + +#endif // QANDROIDOPENGLPLATFORMSCREEN_H diff --git a/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.cpp b/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.cpp index 4934047af9..6ed805174b 100644 --- a/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.cpp +++ b/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.cpp @@ -41,6 +41,7 @@ #include "qandroidopenglplatformwindow.h" #include "androidjnimain.h" +#include "qandroidplatformintegration.h" #include <qpa/qwindowsysteminterface.h> QT_BEGIN_NAMESPACE @@ -52,6 +53,7 @@ QBasicAtomicInt QAndroidOpenGLPlatformWindow::m_referenceCount = Q_BASIC_ATOMIC_ QAndroidOpenGLPlatformWindow::QAndroidOpenGLPlatformWindow(QWindow *window) : QEglFSWindow(window) + , m_state(Qt::WindowNoState) { } @@ -110,7 +112,9 @@ void QAndroidOpenGLPlatformWindow::resetSurface() { lock(); - scheduleResize(QtAndroid::nativeWindowSize()); + // 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(); } @@ -128,12 +132,38 @@ void QAndroidOpenGLPlatformWindow::destroy() } } +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 diff --git a/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.h b/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.h index 9a25957ccd..e4ff0444d4 100644 --- a/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.h +++ b/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.h @@ -66,16 +66,19 @@ public: void invalidateSurface(); void resetSurface(); + void setWindowState(Qt::WindowState state); void setVisible(bool visible); void destroy(); static void updateStaticNativeWindow(); + void updateStatusBarVisibility(); private: QSize m_scheduledResize; QMutex m_lock; + Qt::WindowState m_state; static QReadWriteLock m_staticSurfaceLock; static EGLSurface m_staticSurface; diff --git a/src/plugins/platforms/android/src/opengl/qeglfshooks_android.cpp b/src/plugins/platforms/android/src/opengl/qeglfshooks_android.cpp index 338966eb40..278cd553f4 100644 --- a/src/plugins/platforms/android/src/opengl/qeglfshooks_android.cpp +++ b/src/plugins/platforms/android/src/opengl/qeglfshooks_android.cpp @@ -82,7 +82,7 @@ EGLNativeDisplayType QEglFSAndroidHooks::platformDisplay() const QSize QEglFSAndroidHooks::screenSize() const { - return QtAndroid::nativeWindowSize(); + return QAndroidPlatformIntegration::defaultDesktopSize(); } QSizeF QEglFSAndroidHooks::physicalScreenSize() const @@ -120,7 +120,8 @@ EGLNativeWindowType QEglFSAndroidHooks::createNativeWindow(QPlatformWindow *plat void QEglFSAndroidHooks::destroyNativeWindow(EGLNativeWindowType window) { - ANativeWindow_release(window); + if (window != 0) + ANativeWindow_release(window); } bool QEglFSAndroidHooks::hasCapability(QPlatformIntegration::Capability capability) const diff --git a/src/plugins/platforms/android/src/qandroidassetsfileenginehandler.cpp b/src/plugins/platforms/android/src/qandroidassetsfileenginehandler.cpp index f3cb2586cc..95844fc649 100644 --- a/src/plugins/platforms/android/src/qandroidassetsfileenginehandler.cpp +++ b/src/plugins/platforms/android/src/qandroidassetsfileenginehandler.cpp @@ -43,20 +43,32 @@ #include "androidjnimain.h" #include <QCoreApplication> +#include <QVector> + +typedef QVector<QString> FilesList; + +struct AndroidAssetDir +{ + AndroidAssetDir(AAssetDir* ad) + { + const char *fileName; + while ((fileName = AAssetDir_getNextFileName(ad))) + m_items.push_back(QString::fromUtf8(fileName)); + AAssetDir_close(ad); + } + FilesList m_items; +}; class AndroidAbstractFileEngineIterator: public QAbstractFileEngineIterator { public: AndroidAbstractFileEngineIterator(QDir::Filters filters, const QStringList &nameFilters, - AAssetDir *asset, + QSharedPointer<AndroidAssetDir> asset, const QString &path) : QAbstractFileEngineIterator(filters, nameFilters) { - AAssetDir_rewind(asset); - const char *fileName; - while ((fileName = AAssetDir_getNextFileName(asset))) - m_items << fileName; + m_items = asset->m_items; m_index = -1; m_path = path; } @@ -93,7 +105,7 @@ public: private: QString m_path; - QStringList m_items; + FilesList m_items; int m_index; }; @@ -102,12 +114,11 @@ class AndroidAbstractFileEngine: public QAbstractFileEngine public: explicit AndroidAbstractFileEngine(AAsset *asset, const QString &fileName) { - m_assetDir = 0; m_assetFile = asset; m_fileName = fileName; } - explicit AndroidAbstractFileEngine(AAssetDir *asset, const QString &fileName) + explicit AndroidAbstractFileEngine(QSharedPointer<AndroidAssetDir> asset, const QString &fileName) { m_assetFile = 0; m_assetDir = asset; @@ -119,8 +130,6 @@ public: ~AndroidAbstractFileEngine() { close(); - if (m_assetDir) - AAssetDir_close(m_assetDir); } virtual bool open(QIODevice::OpenMode openMode) @@ -188,7 +197,7 @@ public: FileFlags flags(ReadOwnerPerm|ReadUserPerm|ReadGroupPerm|ReadOtherPerm|ExistsFlag); if (m_assetFile) flags |= FileType; - if (m_assetDir) + if (!m_assetDir.isNull()) flags |= DirectoryType; return type & flags; @@ -233,19 +242,19 @@ public: virtual Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) { - if (m_assetDir) + if (!m_assetDir.isNull()) return new AndroidAbstractFileEngineIterator(filters, filterNames, m_assetDir, m_fileName); return 0; } private: AAsset *m_assetFile; - AAssetDir *m_assetDir; + QSharedPointer<AndroidAssetDir> m_assetDir; QString m_fileName; }; -AndroidAssetsFileEngineHandler::AndroidAssetsFileEngineHandler() +AndroidAssetsFileEngineHandler::AndroidAssetsFileEngineHandler():m_assetsCache(std::max(5, qgetenv("QT_ANDROID_MAX_ASSETS_CACHE_SIZE").toInt())) { m_assetManager = QtAndroid::assetManager(); } @@ -264,25 +273,37 @@ QAbstractFileEngine * AndroidAssetsFileEngineHandler::create(const QString &file int prefixSize=8; - m_path.clear(); + QByteArray path; if (!fileName.endsWith(QLatin1Char('/'))) { - m_path = fileName.toUtf8(); + path = fileName.toUtf8(); AAsset *asset = AAssetManager_open(m_assetManager, - m_path.constData() + prefixSize, + path.constData() + prefixSize, AASSET_MODE_BUFFER); if (asset) return new AndroidAbstractFileEngine(asset, fileName); } - if (!m_path.size()) - m_path = fileName.left(fileName.length() - 1).toUtf8(); - - AAssetDir *assetDir = AAssetManager_openDir(m_assetManager, m_path.constData() + prefixSize); - if (assetDir) { - if (AAssetDir_getNextFileName(assetDir)) - return new AndroidAbstractFileEngine(assetDir, fileName); - else - AAssetDir_close(assetDir); + if (!path.size()) + path = fileName.left(fileName.length() - 1).toUtf8(); + + m_assetsCacheMutext.lock(); + QSharedPointer<AndroidAssetDir> *aad = m_assetsCache.object(path); + m_assetsCacheMutext.unlock(); + if (!aad) { + AAssetDir *assetDir = AAssetManager_openDir(m_assetManager, path.constData() + prefixSize); + if (assetDir) { + if (AAssetDir_getNextFileName(assetDir)) { + aad = new QSharedPointer<AndroidAssetDir>(new AndroidAssetDir(assetDir)); + m_assetsCacheMutext.lock(); + m_assetsCache.insert(path, aad); + m_assetsCacheMutext.unlock(); + return new AndroidAbstractFileEngine(*aad, fileName); + } else { + AAssetDir_close(assetDir); + } + } + } else { + return new AndroidAbstractFileEngine(*aad, fileName); } return 0; } diff --git a/src/plugins/platforms/android/src/qandroidassetsfileenginehandler.h b/src/plugins/platforms/android/src/qandroidassetsfileenginehandler.h index 9bff6a012e..7bd560886c 100644 --- a/src/plugins/platforms/android/src/qandroidassetsfileenginehandler.h +++ b/src/plugins/platforms/android/src/qandroidassetsfileenginehandler.h @@ -43,8 +43,13 @@ #define QANDROIDASSETSFILEENGINEHANDLER_H #include <QtCore/private/qabstractfileengine_p.h> +#include <QCache> +#include <QMutex> +#include <QSharedPointer> + #include <android/asset_manager.h> +struct AndroidAssetDir; class AndroidAssetsFileEngineHandler: public QAbstractFileEngineHandler { public: @@ -54,7 +59,8 @@ public: private: AAssetManager *m_assetManager; - mutable QByteArray m_path; + mutable QCache<QByteArray, QSharedPointer<AndroidAssetDir>> m_assetsCache; + mutable QMutex m_assetsCacheMutext; }; #endif // QANDROIDASSETSFILEENGINEHANDLER_H diff --git a/src/plugins/platforms/android/src/qandroidinputcontext.cpp b/src/plugins/platforms/android/src/qandroidinputcontext.cpp index 386c8e006a..8556e8ebf1 100644 --- a/src/plugins/platforms/android/src/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/src/qandroidinputcontext.cpp @@ -381,6 +381,11 @@ QAndroidInputContext::~QAndroidInputContext() m_textFieldID = 0; } +QAndroidInputContext *QAndroidInputContext::androidInputContext() +{ + return m_androidInputContext; +} + void QAndroidInputContext::reset() { clear(); diff --git a/src/plugins/platforms/android/src/qandroidinputcontext.h b/src/plugins/platforms/android/src/qandroidinputcontext.h index d19dcc384b..041bd0dc49 100644 --- a/src/plugins/platforms/android/src/qandroidinputcontext.h +++ b/src/plugins/platforms/android/src/qandroidinputcontext.h @@ -80,6 +80,7 @@ public: public: QAndroidInputContext(); ~QAndroidInputContext(); + static QAndroidInputContext * androidInputContext(); bool isValid() const { return true; } void reset(); diff --git a/src/plugins/platforms/android/src/qandroidplatformdialoghelpers.cpp b/src/plugins/platforms/android/src/qandroidplatformdialoghelpers.cpp new file mode 100644 index 0000000000..f379402e18 --- /dev/null +++ b/src/plugins/platforms/android/src/qandroidplatformdialoghelpers.cpp @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 <QtWidgets/QApplication> +#include <QtWidgets/QStyle> +#include "qandroidplatformdialoghelpers.h" +#include "androidjnimain.h" + +namespace QtAndroidDialogHelpers { +static jclass g_messageDialogHelperClass = 0; + +QAndroidPlatformMessageDialogHelper::QAndroidPlatformMessageDialogHelper() + :m_buttonId(-1) + ,m_javaMessageDialog(g_messageDialogHelperClass, "(Landroid/app/Activity;)V", QtAndroid::activity()) + ,m_shown(false) +{ +} + +void QAndroidPlatformMessageDialogHelper::exec() +{ + if (!m_shown) + show(Qt::Dialog, Qt::ApplicationModal, 0); + m_loop.exec(); +} + +static QString standardButtonText(int sbutton) +{ + switch (sbutton) { + case QMessageDialogOptions::Ok: + return QAndroidPlatformMessageDialogHelper::tr("OK"); + case QMessageDialogOptions::Save: + return QAndroidPlatformMessageDialogHelper::tr("Save"); + case QMessageDialogOptions::Open: + return QAndroidPlatformMessageDialogHelper::tr("Open"); + case QMessageDialogOptions::Cancel: + return QAndroidPlatformMessageDialogHelper::tr("Cancel"); + case QMessageDialogOptions::Close: + return QAndroidPlatformMessageDialogHelper::tr("Close"); + case QMessageDialogOptions::Apply: + return QAndroidPlatformMessageDialogHelper::tr("Apply"); + case QMessageDialogOptions::Reset: + return QAndroidPlatformMessageDialogHelper::tr("Reset"); + case QMessageDialogOptions::Help: + return QAndroidPlatformMessageDialogHelper::tr("Help"); + case QMessageDialogOptions::Discard: + return QAndroidPlatformMessageDialogHelper::tr("Discard"); + case QMessageDialogOptions::Yes: + return QAndroidPlatformMessageDialogHelper::tr("Yes"); + case QMessageDialogOptions::YesToAll: + return QAndroidPlatformMessageDialogHelper::tr("Yes to All"); + case QMessageDialogOptions::No: + return QAndroidPlatformMessageDialogHelper::tr("No"); + case QMessageDialogOptions::NoToAll: + return QAndroidPlatformMessageDialogHelper::tr("No to All"); + case QMessageDialogOptions::SaveAll: + return QAndroidPlatformMessageDialogHelper::tr("Save All"); + case QMessageDialogOptions::Abort: + return QAndroidPlatformMessageDialogHelper::tr("Abort"); + case QMessageDialogOptions::Retry: + return QAndroidPlatformMessageDialogHelper::tr("Retry"); + case QMessageDialogOptions::Ignore: + return QAndroidPlatformMessageDialogHelper::tr("Ignore"); + case QMessageDialogOptions::RestoreDefaults: + return QAndroidPlatformMessageDialogHelper::tr("Restore Defaults"); + } // switch + return QString(); +} + +bool QAndroidPlatformMessageDialogHelper::show(Qt::WindowFlags windowFlags + , Qt::WindowModality windowModality + , QWindow *parent) +{ + Q_UNUSED(windowFlags) + Q_UNUSED(windowModality) + Q_UNUSED(parent) + QSharedPointer<QMessageDialogOptions> opt = options(); + if (!opt.data()) + return false; + + m_javaMessageDialog.callMethod<void>("setIcon", "(I)V", opt->icon()); + + QString str = opt->windowTitle(); + if (!str.isEmpty()) + m_javaMessageDialog.callMethod<void>("setTile", "(Ljava/lang/String;)V", QJNIObjectPrivate::fromString(str).object()); + + str = opt->text(); + if (!str.isEmpty()) + m_javaMessageDialog.callMethod<void>("setText", "(Ljava/lang/String;)V", QJNIObjectPrivate::fromString(str).object()); + + str = opt->informativeText(); + if (!str.isEmpty()) + m_javaMessageDialog.callMethod<void>("setInformativeText", "(Ljava/lang/String;)V", QJNIObjectPrivate::fromString(str).object()); + + str = opt->detailedText(); + if (!str.isEmpty()) + m_javaMessageDialog.callMethod<void>("setDetailedText", "(Ljava/lang/String;)V", QJNIObjectPrivate::fromString(str).object()); + + for (int i = QMessageDialogOptions::FirstButton; i < QMessageDialogOptions::LastButton; i<<=1) { + if ( opt->standardButtons() & i ) + m_javaMessageDialog.callMethod<void>("addButton", "(ILjava/lang/String;)V", i, QJNIObjectPrivate::fromString(standardButtonText(i)).object()); + } + + m_javaMessageDialog.callMethod<void>("show", "(J)V", jlong(static_cast<QObject*>(this))); + m_shown = true; + return true; +} + +void QAndroidPlatformMessageDialogHelper::hide() +{ + m_javaMessageDialog.callMethod<void>("hide", "()V"); + m_shown = false; +} + +void QAndroidPlatformMessageDialogHelper::dialogResult(int buttonID) +{ + m_buttonId = buttonID; + if (m_loop.isRunning()) + m_loop.exit(); + if (m_buttonId < 0) { + emit reject(); + return; + } + + QMessageDialogOptions::StandardButton standardButton = static_cast<QMessageDialogOptions::StandardButton>(buttonID); + QMessageDialogOptions::ButtonRole role = QMessageDialogOptions::buttonRole(standardButton); + emit clicked(standardButton, role); +} + +static void dialogResult(JNIEnv * /*env*/, jobject /*thiz*/, jlong handler, int buttonID) +{ + QObject *object = reinterpret_cast<QObject *>(handler); + QMetaObject::invokeMethod(object, "dialogResult", Qt::QueuedConnection, Q_ARG(int, buttonID)); +} + +static JNINativeMethod methods[] = { + {"dialogResult", "(JI)V", (void *)dialogResult} +}; + + +#define FIND_AND_CHECK_CLASS(CLASS_NAME) \ + clazz = env->FindClass(CLASS_NAME); \ + if (!clazz) { \ + __android_log_print(ANDROID_LOG_FATAL, QtAndroid::qtTagText(), QtAndroid::classErrorMsgFmt(), CLASS_NAME); \ + return false; \ + } + +bool registerNatives(JNIEnv *env) +{ + jclass clazz = QtAndroid::findClass("org/qtproject/qt5/android/QtMessageDialogHelper", env); + if (!clazz) { + __android_log_print(ANDROID_LOG_FATAL, QtAndroid::qtTagText(), QtAndroid::classErrorMsgFmt() + , "org/qtproject/qt5/android/QtMessageDialogHelper"); + return false; + } + g_messageDialogHelperClass = static_cast<jclass>(env->NewGlobalRef(clazz)); + FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/QtNativeDialogHelper"); + jclass appClass = static_cast<jclass>(env->NewGlobalRef(clazz)); + + if (env->RegisterNatives(appClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) { + __android_log_print(ANDROID_LOG_FATAL, "Qt", "RegisterNatives failed"); + return false; + } + + return true; +} +} diff --git a/src/plugins/platforms/android/src/qandroidplatformdialoghelpers.h b/src/plugins/platforms/android/src/qandroidplatformdialoghelpers.h new file mode 100644 index 0000000000..88ec91d936 --- /dev/null +++ b/src/plugins/platforms/android/src/qandroidplatformdialoghelpers.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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$ +** +****************************************************************************/ + +#ifndef QANDROIDPLATFORMDIALOGHELPERS_H +#define QANDROIDPLATFORMDIALOGHELPERS_H +#include <jni.h> +#include <qpa/qplatformdialoghelper.h> +#include <QEventLoop> +#include <private/qjni_p.h> + +namespace QtAndroidDialogHelpers { + +class QAndroidPlatformMessageDialogHelper: public QPlatformMessageDialogHelper +{ + Q_OBJECT +public: + QAndroidPlatformMessageDialogHelper(); + void exec(); + bool show(Qt::WindowFlags windowFlags, + Qt::WindowModality windowModality, + QWindow *parent); + void hide(); + +public slots: + void dialogResult(int buttonID); + +private: + int m_buttonId; + QEventLoop m_loop; + QJNIObjectPrivate m_javaMessageDialog; + bool m_shown; +}; + + +bool registerNatives(JNIEnv *env); + +} + +#endif // QANDROIDPLATFORMDIALOGHELPERS_H diff --git a/src/plugins/platforms/android/src/qandroidplatformintegration.cpp b/src/plugins/platforms/android/src/qandroidplatformintegration.cpp index a3db421de9..ae3e257d3c 100644 --- a/src/plugins/platforms/android/src/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/src/qandroidplatformintegration.cpp @@ -61,6 +61,7 @@ # include "androidjnimenu.h" # include "qandroidopenglcontext.h" # include "qandroidopenglplatformwindow.h" +# include "qandroidopenglplatformscreen.h" # include "qeglfshooks.h" # include <QtGui/qopenglcontext.h> #endif @@ -123,7 +124,6 @@ bool QAndroidPlatformIntegration::hasCapability(Capability cap) const switch (cap) { case ThreadedPixmaps: return true; case ApplicationState: return true; - case NonFullScreenWindows: return false; case NativeWidgets: return false; default: #ifndef ANDROID_PLUGIN_OPENGL @@ -142,7 +142,10 @@ QPlatformBackingStore *QAndroidPlatformIntegration::createPlatformBackingStore(Q QPlatformWindow *QAndroidPlatformIntegration::createPlatformWindow(QWindow *window) const { - return new QAndroidPlatformWindow(window); + QAndroidPlatformWindow *platformWindow = new QAndroidPlatformWindow(window); + platformWindow->setWindowState(window->windowState()); + + return platformWindow; } QAbstractEventDispatcher *QAndroidPlatformIntegration::createEventDispatcher() const @@ -155,6 +158,7 @@ QPlatformWindow *QAndroidPlatformIntegration::createPlatformWindow(QWindow *wind QAndroidOpenGLPlatformWindow *platformWindow = new QAndroidOpenGLPlatformWindow(window); platformWindow->create(); platformWindow->requestActivateWindow(); + platformWindow->setWindowState(window->windowState()); QtAndroidMenu::setActiveTopLevelWindow(window); return platformWindow; @@ -231,13 +235,22 @@ QPlatformServices *QAndroidPlatformIntegration::services() const QVariant QAndroidPlatformIntegration::styleHint(StyleHint hint) const { switch (hint) { - case ShowIsFullScreen: + case ShowIsMaximized: return true; default: return QPlatformIntegration::styleHint(hint); } } +Qt::WindowState QAndroidPlatformIntegration::defaultWindowState(Qt::WindowFlags flags) const +{ + // Don't maximize dialogs on Android + if (flags & Qt::Dialog & ~Qt::Window) + return Qt::WindowNoState; + + return QPlatformIntegration::defaultWindowState(flags); +} + static const QLatin1String androidThemeName("android"); QStringList QAndroidPlatformIntegration::themeNames() const { @@ -308,6 +321,11 @@ void QAndroidPlatformIntegration::setDisplayMetrics(int width, int height) m_defaultPhysicalSizeHeight = height; } +QEglFSScreen *QAndroidPlatformIntegration::createScreen() const +{ + return new QAndroidOpenGLPlatformScreen(display()); +} + #endif void QAndroidPlatformIntegration::pauseApp() diff --git a/src/plugins/platforms/android/src/qandroidplatformintegration.h b/src/plugins/platforms/android/src/qandroidplatformintegration.h index 5ebdf9e65c..bd08ad694c 100644 --- a/src/plugins/platforms/android/src/qandroidplatformintegration.h +++ b/src/plugins/platforms/android/src/qandroidplatformintegration.h @@ -121,6 +121,7 @@ public: #endif QVariant styleHint(StyleHint hint) const; + Qt::WindowState defaultWindowState(Qt::WindowFlags flags) const Q_DECL_OVERRIDE; QStringList themeNames() const; QPlatformTheme *createPlatformTheme(const QString &name) const; @@ -140,6 +141,10 @@ 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; diff --git a/src/plugins/platforms/android/src/qandroidplatformmenu.cpp b/src/plugins/platforms/android/src/qandroidplatformmenu.cpp index 253c22a12f..1ecabb25e2 100644 --- a/src/plugins/platforms/android/src/qandroidplatformmenu.cpp +++ b/src/plugins/platforms/android/src/qandroidplatformmenu.cpp @@ -141,6 +141,15 @@ bool QAndroidPlatformMenu::isVisible() const return m_isVisible; } +void QAndroidPlatformMenu::showPopup(const QWindow *parentWindow, QPoint pos, const QPlatformMenuItem *item) +{ + Q_UNUSED(parentWindow); + Q_UNUSED(pos); + Q_UNUSED(item); + setVisible(true); + QtAndroidMenu::showContextMenu(this); +} + QPlatformMenuItem *QAndroidPlatformMenu::menuItemAt(int position) const { if (position < m_menuItems.size()) @@ -154,7 +163,6 @@ QPlatformMenuItem *QAndroidPlatformMenu::menuItemForTag(quintptr tag) const if (menuItem->tag() == tag) return menuItem; } - return 0; } diff --git a/src/plugins/platforms/android/src/qandroidplatformmenu.h b/src/plugins/platforms/android/src/qandroidplatformmenu.h index 20236cb636..305b64168a 100644 --- a/src/plugins/platforms/android/src/qandroidplatformmenu.h +++ b/src/plugins/platforms/android/src/qandroidplatformmenu.h @@ -71,6 +71,7 @@ public: bool isEnabled() const; void setVisible(bool visible); bool isVisible() const; + void showPopup(const QWindow *parentWindow, QPoint pos, const QPlatformMenuItem *item); QPlatformMenuItem *menuItemAt(int position) const; QPlatformMenuItem *menuItemForTag(quintptr tag) const; diff --git a/src/plugins/platforms/android/src/qandroidplatformmenubar.cpp b/src/plugins/platforms/android/src/qandroidplatformmenubar.cpp index ef1ac61356..134062fb32 100644 --- a/src/plugins/platforms/android/src/qandroidplatformmenubar.cpp +++ b/src/plugins/platforms/android/src/qandroidplatformmenubar.cpp @@ -79,6 +79,8 @@ void QAndroidPlatformMenuBar::syncMenu(QPlatformMenu *menu) void QAndroidPlatformMenuBar::handleReparent(QWindow *newParentWindow) { + if (m_parentWindow == newParentWindow) + return; m_parentWindow = newParentWindow; QtAndroidMenu::setMenuBar(this, newParentWindow); } diff --git a/src/plugins/platforms/android/src/qandroidplatformtheme.cpp b/src/plugins/platforms/android/src/qandroidplatformtheme.cpp index 79fbc440fc..308bb70faf 100644 --- a/src/plugins/platforms/android/src/qandroidplatformtheme.cpp +++ b/src/plugins/platforms/android/src/qandroidplatformtheme.cpp @@ -43,6 +43,7 @@ #include "qandroidplatformmenubar.h" #include "qandroidplatformmenu.h" #include "qandroidplatformmenuitem.h" +#include "qandroidplatformdialoghelpers.h" #include <QVariant> #include <QFileInfo> #include <qandroidplatformintegration.h> @@ -124,7 +125,7 @@ const QFont *QAndroidPlatformTheme::font(Font type) const return &(it.value()); // default in case the style has not set a font - static QFont systemFont("Roboto", 12.0 * 100 / 72); // keep default size the same after changing from 100 dpi to 72 dpi + static QFont systemFont("Roboto", 14.0 * 100 / 72); // keep default size the same after changing from 100 dpi to 72 dpi if (type == QPlatformTheme::SystemFont) return &systemFont; return 0; @@ -150,3 +151,20 @@ QVariant QAndroidPlatformTheme::themeHint(ThemeHint hint) const return QPlatformTheme::themeHint(hint); } } + +bool QAndroidPlatformTheme::usePlatformNativeDialog(QPlatformTheme::DialogType type) const +{ + if (type == MessageDialog) + return qgetenv("QT_USE_ANDROID_NATIVE_DIALOGS").toInt() == 1; + return false; +} + +QPlatformDialogHelper *QAndroidPlatformTheme::createPlatformDialogHelper(QPlatformTheme::DialogType type) const +{ + switch (type) { + case MessageDialog: + return new QtAndroidDialogHelpers::QAndroidPlatformMessageDialogHelper; + default: + return 0; + } +} diff --git a/src/plugins/platforms/android/src/qandroidplatformtheme.h b/src/plugins/platforms/android/src/qandroidplatformtheme.h index 15d2cb2000..ec259a9b0a 100644 --- a/src/plugins/platforms/android/src/qandroidplatformtheme.h +++ b/src/plugins/platforms/android/src/qandroidplatformtheme.h @@ -54,6 +54,9 @@ public: virtual const QPalette *palette(Palette type = SystemPalette) const; virtual const QFont *font(Font type = SystemFont) const; virtual QVariant themeHint(ThemeHint hint) const; + virtual bool usePlatformNativeDialog(DialogType type) const; + virtual QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const; + private: QAndroidPlatformNativeInterface * m_androidPlatformNativeInterface; diff --git a/src/plugins/platforms/android/src/raster/qandroidplatformscreen.cpp b/src/plugins/platforms/android/src/raster/qandroidplatformscreen.cpp index 0250a6122c..2e59c307c3 100644 --- a/src/plugins/platforms/android/src/raster/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/src/raster/qandroidplatformscreen.cpp @@ -43,6 +43,7 @@ #include "qandroidplatformintegration.h" #include "androidjnimain.h" #include "androidjnimenu.h" +#include "qandroidplatformwindow.h" QAndroidPlatformScreen::QAndroidPlatformScreen():QFbScreen() { @@ -57,6 +58,12 @@ QAndroidPlatformScreen::QAndroidPlatformScreen():QFbScreen() 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() diff --git a/src/plugins/platforms/android/src/raster/qandroidplatformwindow.cpp b/src/plugins/platforms/android/src/raster/qandroidplatformwindow.cpp index f5fce0ae34..7ff18526d9 100644 --- a/src/plugins/platforms/android/src/raster/qandroidplatformwindow.cpp +++ b/src/plugins/platforms/android/src/raster/qandroidplatformwindow.cpp @@ -44,7 +44,8 @@ #include "androidjnimain.h" #include <qpa/qwindowsysteminterface.h> -QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window) : QFbWindow(window) +QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window) + : QFbWindow(window) { } @@ -58,8 +59,40 @@ 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(); + } +} + +void QAndroidPlatformWindow::raise() +{ + updateStatusBarVisibility(); + QFbWindow::raise(); +} + +void QAndroidPlatformWindow::setWindowState(Qt::WindowState state) +{ + if (mWindowState == state) + return; + + if (window()->isVisible()) + updateStatusBarVisibility(); + + QFbWindow::setWindowState(state); +} + void QAndroidPlatformWindow::setVisible(bool visible) { + if (visible) + updateStatusBarVisibility(); + QFbWindow::setVisible(visible); // The Android Activity is activated before Qt is initialized, causing the application state to diff --git a/src/plugins/platforms/android/src/raster/qandroidplatformwindow.h b/src/plugins/platforms/android/src/raster/qandroidplatformwindow.h index 58e6451ea1..9e3f203201 100644 --- a/src/plugins/platforms/android/src/raster/qandroidplatformwindow.h +++ b/src/plugins/platforms/android/src/raster/qandroidplatformwindow.h @@ -52,11 +52,13 @@ public: void propagateSizeHints(); + void raise(); + void setWindowState(Qt::WindowState state); void setVisible(bool visible); + void updateStatusBarVisibility(); public slots: void setGeometry(const QRect &rect); - }; #endif // ANDROIDPLATFORMWINDOW_H diff --git a/src/plugins/platforms/android/src/src.pri b/src/plugins/platforms/android/src/src.pri index 6cc41c3e68..9b64e846f7 100644 --- a/src/plugins/platforms/android/src/src.pri +++ b/src/plugins/platforms/android/src/src.pri @@ -21,6 +21,7 @@ SOURCES += $$PWD/androidplatformplugin.cpp \ $$PWD/qandroidinputcontext.cpp \ $$PWD/qandroidplatformaccessibility.cpp \ $$PWD/qandroidplatformfontdatabase.cpp \ + $$PWD/qandroidplatformdialoghelpers.cpp \ $$PWD/qandroidplatformclipboard.cpp \ $$PWD/qandroidplatformtheme.cpp \ $$PWD/qandroidplatformmenubar.cpp \ @@ -41,6 +42,7 @@ HEADERS += $$PWD/qandroidplatformintegration.h \ $$PWD/qandroidplatformaccessibility.h \ $$PWD/qandroidplatformfontdatabase.h \ $$PWD/qandroidplatformclipboard.h \ + $$PWD/qandroidplatformdialoghelpers.h \ $$PWD/qandroidplatformtheme.h \ $$PWD/qandroidplatformmenubar.h \ $$PWD/qandroidplatformmenu.h \ |