diff options
Diffstat (limited to 'src/platformsupport')
55 files changed, 4604 insertions, 315 deletions
diff --git a/src/platformsupport/cfsocketnotifier/cfsocketnotifier.pri b/src/platformsupport/cfsocketnotifier/cfsocketnotifier.pri new file mode 100644 index 0000000000..9a19d3c278 --- /dev/null +++ b/src/platformsupport/cfsocketnotifier/cfsocketnotifier.pri @@ -0,0 +1,4 @@ +mac { + HEADERS += $$PWD/qcfsocketnotifier_p.h + SOURCES += $$PWD/qcfsocketnotifier.cpp +} diff --git a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp new file mode 100644 index 0000000000..5dcd6a4ffd --- /dev/null +++ b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp @@ -0,0 +1,255 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module 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 "qcfsocketnotifier_p.h" +#include <QtGui/qguiapplication.h> +#include <QtCore/qsocketnotifier.h> +#include <QtCore/qthread.h> + + +/************************************************************************** + Socket Notifiers + *************************************************************************/ +void qt_mac_socket_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef, + const void *, void *info) +{ + + QCFSocketNotifier *cfSocketNotifier = static_cast<QCFSocketNotifier *>(info); + int nativeSocket = CFSocketGetNative(s); + MacSocketInfo *socketInfo = cfSocketNotifier->macSockets.value(nativeSocket); + QEvent notifierEvent(QEvent::SockAct); + + // There is a race condition that happen where we disable the notifier and + // the kernel still has a notification to pass on. We then get this + // notification after we've successfully disabled the CFSocket, but our Qt + // notifier is now gone. The upshot is we have to check the notifier + // every time. + if (callbackType == kCFSocketReadCallBack) { + if (socketInfo->readNotifier) + QGuiApplication::sendEvent(socketInfo->readNotifier, ¬ifierEvent); + } else if (callbackType == kCFSocketWriteCallBack) { + if (socketInfo->writeNotifier) + QGuiApplication::sendEvent(socketInfo->writeNotifier, ¬ifierEvent); + } + + if (cfSocketNotifier->maybeCancelWaitForMoreEvents) + cfSocketNotifier->maybeCancelWaitForMoreEvents(cfSocketNotifier->eventDispatcher); +} + +/* + Adds a loop source for the given socket to the current run loop. +*/ +CFRunLoopSourceRef qt_mac_add_socket_to_runloop(const CFSocketRef socket) +{ + CFRunLoopSourceRef loopSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0); + if (!loopSource) + return 0; + + CFRunLoopAddSource(CFRunLoopGetMain(), loopSource, kCFRunLoopCommonModes); + return loopSource; +} + +/* + Removes the loop source for the given socket from the current run loop. +*/ +void qt_mac_remove_socket_from_runloop(const CFSocketRef socket, CFRunLoopSourceRef runloop) +{ + Q_ASSERT(runloop); + CFRunLoopRemoveSource(CFRunLoopGetMain(), runloop, kCFRunLoopCommonModes); + CFSocketDisableCallBacks(socket, kCFSocketReadCallBack); + CFSocketDisableCallBacks(socket, kCFSocketWriteCallBack); + CFRunLoopSourceInvalidate(runloop); +} + +QCFSocketNotifier::QCFSocketNotifier() +:eventDispatcher(0) +{ + +} + +QCFSocketNotifier::~QCFSocketNotifier() +{ + +} + +void QCFSocketNotifier::setHostEventDispatcher(QAbstractEventDispatcher *hostEventDispacher) +{ + eventDispatcher = hostEventDispacher; +} + +void QCFSocketNotifier::setMaybeCancelWaitForMoreEventsCallback(MaybeCancelWaitForMoreEventsFn callBack) +{ + maybeCancelWaitForMoreEvents = callBack; +} + +void QCFSocketNotifier::registerSocketNotifier(QSocketNotifier *notifier) +{ + Q_ASSERT(notifier); + int nativeSocket = notifier->socket(); + int type = notifier->type(); +#ifndef QT_NO_DEBUG + if (nativeSocket < 0 || nativeSocket > FD_SETSIZE) { + qWarning("QSocketNotifier: Internal error"); + return; + } else if (notifier->thread() != eventDispatcher->thread() + || eventDispatcher->thread() != QThread::currentThread()) { + qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread"); + return; + } +#endif + + if (type == QSocketNotifier::Exception) { + qWarning("QSocketNotifier::Exception is not supported on iOS"); + return; + } + + // Check if we have a CFSocket for the native socket, create one if not. + MacSocketInfo *socketInfo = macSockets.value(nativeSocket); + if (!socketInfo) { + socketInfo = new MacSocketInfo(); + + // Create CFSocket, specify that we want both read and write callbacks (the callbacks + // are enabled/disabled later on). + const int callbackTypes = kCFSocketReadCallBack | kCFSocketWriteCallBack; + CFSocketContext context = {0, this, 0, 0, 0}; + socketInfo->socket = CFSocketCreateWithNative(kCFAllocatorDefault, nativeSocket, callbackTypes, qt_mac_socket_callback, &context); + if (CFSocketIsValid(socketInfo->socket) == false) { + qWarning("QEventDispatcherMac::registerSocketNotifier: Failed to create CFSocket"); + return; + } + + CFOptionFlags flags = CFSocketGetSocketFlags(socketInfo->socket); + flags |= kCFSocketAutomaticallyReenableWriteCallBack; //QSocketNotifier stays enabled after a write + flags &= ~kCFSocketCloseOnInvalidate; //QSocketNotifier doesn't close the socket upon destruction/invalidation + CFSocketSetSocketFlags(socketInfo->socket, flags); + + // Add CFSocket to runloop. + if (!(socketInfo->runloop = qt_mac_add_socket_to_runloop(socketInfo->socket))) { + qWarning("QEventDispatcherMac::registerSocketNotifier: Failed to add CFSocket to runloop"); + CFSocketInvalidate(socketInfo->socket); + CFRelease(socketInfo->socket); + return; + } + + // Disable both callback types by default. This must be done after + // we add the CFSocket to the runloop, or else these calls will have + // no effect. + CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack); + CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); + + macSockets.insert(nativeSocket, socketInfo); + } + + // Increment read/write counters and select enable callbacks if necessary. + if (type == QSocketNotifier::Read) { + Q_ASSERT(socketInfo->readNotifier == 0); + socketInfo->readNotifier = notifier; + CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack); + } else if (type == QSocketNotifier::Write) { + Q_ASSERT(socketInfo->writeNotifier == 0); + socketInfo->writeNotifier = notifier; + CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); + } +} + +void QCFSocketNotifier::unregisterSocketNotifier(QSocketNotifier *notifier) +{ + Q_ASSERT(notifier); + int nativeSocket = notifier->socket(); + int type = notifier->type(); +#ifndef QT_NO_DEBUG + if (nativeSocket < 0 || nativeSocket > FD_SETSIZE) { + qWarning("QSocketNotifier: Internal error"); + return; + } else if (notifier->thread() != eventDispatcher->thread() || eventDispatcher->thread() != QThread::currentThread()) { + qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread"); + return; + } +#endif + + if (type == QSocketNotifier::Exception) { + qWarning("QSocketNotifier::Exception is not supported on iOS"); + return; + } + MacSocketInfo *socketInfo = macSockets.value(nativeSocket); + if (!socketInfo) { + qWarning("QEventDispatcherMac::unregisterSocketNotifier: Tried to unregister a not registered notifier"); + return; + } + + // Decrement read/write counters and disable callbacks if necessary. + if (type == QSocketNotifier::Read) { + Q_ASSERT(notifier == socketInfo->readNotifier); + socketInfo->readNotifier = 0; + CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack); + } else if (type == QSocketNotifier::Write) { + Q_ASSERT(notifier == socketInfo->writeNotifier); + socketInfo->writeNotifier = 0; + CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); + } + + // Remove CFSocket from runloop if this was the last QSocketNotifier. + if (socketInfo->readNotifier == 0 && socketInfo->writeNotifier == 0) { + if (CFSocketIsValid(socketInfo->socket)) + qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop); + CFRunLoopSourceInvalidate(socketInfo->runloop); + CFRelease(socketInfo->runloop); + CFSocketInvalidate(socketInfo->socket); + CFRelease(socketInfo->socket); + delete socketInfo; + macSockets.remove(nativeSocket); + } +} + +void QCFSocketNotifier::removeSocketNotifiers() +{ + // Remove CFSockets from the runloop. + for (MacSocketHash::ConstIterator it = macSockets.constBegin(); it != macSockets.constEnd(); ++it) { + MacSocketInfo *socketInfo = (*it); + if (CFSocketIsValid(socketInfo->socket)) { + qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop); + CFRunLoopSourceInvalidate(socketInfo->runloop); + CFRelease(socketInfo->runloop); + CFSocketInvalidate(socketInfo->socket); + CFRelease(socketInfo->socket); + } + } +} diff --git a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h new file mode 100644 index 0000000000..cd1eb8e4ca --- /dev/null +++ b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module 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 QCFSOCKETNOTIFIER_P_H +#define QCFSOCKETNOTIFIER_P_H + +#include <QtCore/qabstracteventdispatcher.h> +#include <QtCore/qhash.h> + +#include <CoreFoundation/CoreFoundation.h> + +QT_BEGIN_NAMESPACE + +struct MacSocketInfo { + MacSocketInfo() : socket(0), runloop(0), readNotifier(0), writeNotifier(0) {} + CFSocketRef socket; + CFRunLoopSourceRef runloop; + QObject *readNotifier; + QObject *writeNotifier; +}; +typedef QHash<int, MacSocketInfo *> MacSocketHash; + +typedef void (*MaybeCancelWaitForMoreEventsFn)(QAbstractEventDispatcher *hostEventDispacher); + +// The CoreFoundationSocketNotifier class implements socket notifiers support using +// CFSocket for event dispatchers running on top of the Core Foundation run loop system. +// (currently Mac and iOS) +// +// The principal functions are registerSocketNotifier() and unregisterSocketNotifier(). +// +// setHostEventDispatcher() should be called at startup. +// removeSocketNotifiers() should be called at shutdown. +// +class QCFSocketNotifier +{ +public: + QCFSocketNotifier(); + ~QCFSocketNotifier(); + void setHostEventDispatcher(QAbstractEventDispatcher *hostEventDispacher); + void setMaybeCancelWaitForMoreEventsCallback(MaybeCancelWaitForMoreEventsFn callBack); + void registerSocketNotifier(QSocketNotifier *notifier); + void unregisterSocketNotifier(QSocketNotifier *notifier); + void removeSocketNotifiers(); + + MacSocketHash macSockets; + QAbstractEventDispatcher *eventDispatcher; + MaybeCancelWaitForMoreEventsFn maybeCancelWaitForMoreEvents; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/platformsupport/cglconvenience/cglconvenience.mm b/src/platformsupport/cglconvenience/cglconvenience.mm index b0ea2d2225..12ae5965df 100644 --- a/src/platformsupport/cglconvenience/cglconvenience.mm +++ b/src/platformsupport/cglconvenience/cglconvenience.mm @@ -61,6 +61,7 @@ void (*qcgl_getProcAddress(const QByteArray &procName))() QSurfaceFormat qcgl_surfaceFormat() { QSurfaceFormat format; + format.setRenderableType(QSurfaceFormat::OpenGL); format.setRedBufferSize(8); format.setGreenBufferSize(8); format.setBlueBufferSize(8); @@ -125,13 +126,3 @@ void *qcgl_createNSOpenGLPixelFormat(const QSurfaceFormat &format) NSOpenGLPixelFormat* pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs.constData()]; return pixelFormat; } - -CGLContextObj qcgl_createGlContext() -{ - CGLContextObj context; - NSOpenGLPixelFormat *format = reinterpret_cast<NSOpenGLPixelFormat *>(qcgl_createNSOpenGLPixelFormat(qcgl_surfaceFormat())); - CGLPixelFormatObj cglFormat = static_cast<CGLPixelFormatObj>([format CGLPixelFormatObj]); - CGLCreateContext(cglFormat ,NULL, &context); - return context; -} - diff --git a/src/platformsupport/cglconvenience/cglconvenience_p.h b/src/platformsupport/cglconvenience/cglconvenience_p.h index bd2de0abc0..82842a78f0 100644 --- a/src/platformsupport/cglconvenience/cglconvenience_p.h +++ b/src/platformsupport/cglconvenience/cglconvenience_p.h @@ -49,6 +49,5 @@ void (*qcgl_getProcAddress(const QByteArray &procName))(); QSurfaceFormat qcgl_surfaceFormat(); void *qcgl_createNSOpenGLPixelFormat(const QSurfaceFormat &format); -CGLContextObj qcgl_createGlContext(); #endif // QMACGLCONVENIENCE_H diff --git a/src/platformsupport/devicediscovery/devicediscovery.pri b/src/platformsupport/devicediscovery/devicediscovery.pri index 530ae3dbb2..9faf6f24dd 100644 --- a/src/platformsupport/devicediscovery/devicediscovery.pri +++ b/src/platformsupport/devicediscovery/devicediscovery.pri @@ -1,4 +1,4 @@ -linux-*:contains(QT_CONFIG, evdev) { +linux:contains(QT_CONFIG, evdev) { HEADERS += $$PWD/qdevicediscovery_p.h contains(QT_CONFIG, libudev) { diff --git a/src/platformsupport/dnd/qshapedpixmapdndwindow.cpp b/src/platformsupport/dnd/qshapedpixmapdndwindow.cpp index 67c3cb4701..b3e64b01d0 100644 --- a/src/platformsupport/dnd/qshapedpixmapdndwindow.cpp +++ b/src/platformsupport/dnd/qshapedpixmapdndwindow.cpp @@ -91,7 +91,9 @@ void QShapedPixmapWindow::setHotspot(const QPoint &hotspot) void QShapedPixmapWindow::updateGeometry() { QRect rect(QCursor::pos() - m_hotSpot, m_pixmap.size()); - if (m_backingStore->size() != m_pixmap.size()) + if (m_pixmap.isNull()) + m_backingStore->resize(QSize(1,1)); + else if (m_backingStore->size() != m_pixmap.size()) m_backingStore->resize(m_pixmap.size()); setGeometry(rect); } diff --git a/src/platformsupport/dnd/qshapedpixmapdndwindow_p.h b/src/platformsupport/dnd/qshapedpixmapdndwindow_p.h index ed0819cf29..20674b6b19 100644 --- a/src/platformsupport/dnd/qshapedpixmapdndwindow_p.h +++ b/src/platformsupport/dnd/qshapedpixmapdndwindow_p.h @@ -48,8 +48,6 @@ QT_BEGIN_NAMESPACE -QT_BEGIN_HEADER - class QShapedPixmapWindow : public QWindow { Q_OBJECT @@ -72,8 +70,6 @@ private: QPoint m_hotSpot; }; -QT_END_HEADER - QT_END_NAMESPACE #endif // QSHAPEDPIXMAPDNDWINDOW_H diff --git a/src/platformsupport/dnd/qsimpledrag.cpp b/src/platformsupport/dnd/qsimpledrag.cpp index 3b73380cab..fe0146afc3 100644 --- a/src/platformsupport/dnd/qsimpledrag.cpp +++ b/src/platformsupport/dnd/qsimpledrag.cpp @@ -207,6 +207,8 @@ void QBasicDrag::resetDndState(bool /* deleteSource */) void QBasicDrag::startDrag() { + // ### TODO Check if its really necessary to have m_drag_icon_window + // when QDrag is used without a pixmap - QDrag::setPixmap() if (!m_drag_icon_window) m_drag_icon_window = new QShapedPixmapWindow(); diff --git a/src/platformsupport/dnd/qsimpledrag_p.h b/src/platformsupport/dnd/qsimpledrag_p.h index 5cf3394919..bb9d215083 100644 --- a/src/platformsupport/dnd/qsimpledrag_p.h +++ b/src/platformsupport/dnd/qsimpledrag_p.h @@ -48,8 +48,6 @@ QT_BEGIN_NAMESPACE -QT_BEGIN_HEADER - #ifndef QT_NO_DRAGANDDROP class QMouseEvent; @@ -120,8 +118,6 @@ private: #endif // QT_NO_DRAGANDDROP -QT_END_HEADER - QT_END_NAMESPACE #endif diff --git a/src/platformsupport/eglconvenience/eglconvenience.pri b/src/platformsupport/eglconvenience/eglconvenience.pri index 188eb1ce64..22ade42816 100644 --- a/src/platformsupport/eglconvenience/eglconvenience.pri +++ b/src/platformsupport/eglconvenience/eglconvenience.pri @@ -1,10 +1,12 @@ contains(QT_CONFIG,egl) { HEADERS += \ $$PWD/qeglconvenience_p.h \ - $$PWD/qeglplatformcontext_p.h + $$PWD/qeglplatformcontext_p.h \ + $$PWD/qeglpbuffer_p.h SOURCES += \ $$PWD/qeglconvenience.cpp \ - $$PWD/qeglplatformcontext.cpp + $$PWD/qeglplatformcontext.cpp \ + $$PWD/qeglpbuffer.cpp contains(QT_CONFIG,xlib) { HEADERS += \ diff --git a/src/platformsupport/eglconvenience/qeglconvenience.cpp b/src/platformsupport/eglconvenience/qeglconvenience.cpp index 0f40a2e34b..b711a2aebd 100644 --- a/src/platformsupport/eglconvenience/qeglconvenience.cpp +++ b/src/platformsupport/eglconvenience/qeglconvenience.cpp @@ -210,75 +210,106 @@ bool q_reduceConfigAttributes(QVector<EGLint> *configAttributes) return false; } -EGLConfig q_configFromGLFormat(EGLDisplay display, const QSurfaceFormat &format, bool highestPixelFormat, int surfaceType) +QEglConfigChooser::QEglConfigChooser(EGLDisplay display) + : m_display(display) + , m_surfaceType(EGL_WINDOW_BIT) + , m_ignore(false) + , m_confAttrRed(0) + , m_confAttrGreen(0) + , m_confAttrBlue(0) + , m_confAttrAlpha(0) { - EGLConfig cfg = 0; - QVector<EGLint> configureAttributes = q_createConfigAttributesFromFormat(format); +} + +QEglConfigChooser::~QEglConfigChooser() +{ +} + +EGLConfig QEglConfigChooser::chooseConfig() +{ + QVector<EGLint> configureAttributes = q_createConfigAttributesFromFormat(m_format); configureAttributes.append(EGL_SURFACE_TYPE); - configureAttributes.append(surfaceType); + configureAttributes.append(surfaceType()); configureAttributes.append(EGL_RENDERABLE_TYPE); - if (format.renderableType() == QSurfaceFormat::OpenVG) + if (m_format.renderableType() == QSurfaceFormat::OpenVG) configureAttributes.append(EGL_OPENVG_BIT); #ifdef EGL_VERSION_1_4 - else if (format.renderableType() == QSurfaceFormat::OpenGL) + else if (m_format.renderableType() == QSurfaceFormat::OpenGL) configureAttributes.append(EGL_OPENGL_BIT); #endif - else if (format.majorVersion() == 1) + else if (m_format.majorVersion() == 1) configureAttributes.append(EGL_OPENGL_ES_BIT); else configureAttributes.append(EGL_OPENGL_ES2_BIT); configureAttributes.append(EGL_NONE); + EGLConfig cfg = 0; do { // Get the number of matching configurations for this set of properties. EGLint matching = 0; - if (!eglChooseConfig(display, configureAttributes.constData(), 0, 0, &matching) || !matching) + if (!eglChooseConfig(display(), configureAttributes.constData(), 0, 0, &matching) || !matching) continue; - // If we want the best pixel format, then return the first - // matching configuration. - if (highestPixelFormat) { - eglChooseConfig(display, configureAttributes.constData(), &cfg, 1, &matching); - if (matching < 1) - continue; - return cfg; - } - // Fetch all of the matching configurations and find the // first that matches the pixel format we wanted. int i = configureAttributes.indexOf(EGL_RED_SIZE); - int confAttrRed = configureAttributes.at(i+1); + m_confAttrRed = configureAttributes.at(i+1); i = configureAttributes.indexOf(EGL_GREEN_SIZE); - int confAttrGreen = configureAttributes.at(i+1); + m_confAttrGreen = configureAttributes.at(i+1); i = configureAttributes.indexOf(EGL_BLUE_SIZE); - int confAttrBlue = configureAttributes.at(i+1); + m_confAttrBlue = configureAttributes.at(i+1); i = configureAttributes.indexOf(EGL_ALPHA_SIZE); - int confAttrAlpha = i == -1 ? 0 : configureAttributes.at(i+1); - - EGLint size = matching; - EGLConfig *configs = new EGLConfig [size]; - eglChooseConfig(display, configureAttributes.constData(), configs, size, &matching); - for (EGLint index = 0; index < size; ++index) { - EGLint red, green, blue, alpha; - eglGetConfigAttrib(display, configs[index], EGL_RED_SIZE, &red); - eglGetConfigAttrib(display, configs[index], EGL_GREEN_SIZE, &green); - eglGetConfigAttrib(display, configs[index], EGL_BLUE_SIZE, &blue); - eglGetConfigAttrib(display, configs[index], EGL_ALPHA_SIZE, &alpha); - if ((confAttrRed == 0 || red == confAttrRed) && - (confAttrGreen == 0 || green == confAttrGreen) && - (confAttrBlue == 0 || blue == confAttrBlue) && - (confAttrAlpha == 0 || alpha == confAttrAlpha)) { - cfg = configs[index]; - delete [] configs; - return cfg; - } + m_confAttrAlpha = i == -1 ? 0 : configureAttributes.at(i+1); + + QVector<EGLConfig> configs(matching); + eglChooseConfig(display(), configureAttributes.constData(), configs.data(), configs.size(), &matching); + if (!cfg && matching > 0) + cfg = configs.first(); + + for (int i = 0; i < configs.size(); ++i) { + if (filterConfig(configs[i])) + return configs.at(i); } - delete [] configs; } while (q_reduceConfigAttributes(&configureAttributes)); - qWarning("Cant find EGLConfig, returning null config"); - return 0; + + if (!cfg) + qWarning("Cant find EGLConfig, returning null config"); + return cfg; +} + +bool QEglConfigChooser::filterConfig(EGLConfig config) const +{ + if (m_ignore) + return true; + + EGLint red = 0; + EGLint green = 0; + EGLint blue = 0; + EGLint alpha = 0; + + if (m_confAttrRed) + eglGetConfigAttrib(display(), config, EGL_RED_SIZE, &red); + if (m_confAttrGreen) + eglGetConfigAttrib(display(), config, EGL_GREEN_SIZE, &green); + if (m_confAttrBlue) + eglGetConfigAttrib(display(), config, EGL_BLUE_SIZE, &blue); + if (m_confAttrAlpha) + eglGetConfigAttrib(display(), config, EGL_ALPHA_SIZE, &alpha); + + return red == m_confAttrRed && green == m_confAttrGreen + && blue == m_confAttrBlue && alpha == m_confAttrAlpha; +} + +EGLConfig q_configFromGLFormat(EGLDisplay display, const QSurfaceFormat &format, bool highestPixelFormat, int surfaceType) +{ + QEglConfigChooser chooser(display); + chooser.setSurfaceFormat(format); + chooser.setSurfaceType(surfaceType); + chooser.setIgnoreColorChannels(highestPixelFormat); + + return chooser.chooseConfig(); } QSurfaceFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config, const QSurfaceFormat &referenceFormat) diff --git a/src/platformsupport/eglconvenience/qeglconvenience_p.h b/src/platformsupport/eglconvenience/qeglconvenience_p.h index 1e5cbafa61..35c225cc2f 100644 --- a/src/platformsupport/eglconvenience/qeglconvenience_p.h +++ b/src/platformsupport/eglconvenience/qeglconvenience_p.h @@ -56,6 +56,41 @@ QSurfaceFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config, bool q_hasEglExtension(EGLDisplay display,const char* extensionName); void q_printEglConfig(EGLDisplay display, EGLConfig config); +class QEglConfigChooser +{ +public: + QEglConfigChooser(EGLDisplay display); + virtual ~QEglConfigChooser(); + + EGLDisplay display() const { return m_display; } + + void setSurfaceType(EGLint surfaceType) { m_surfaceType = surfaceType; } + EGLint surfaceType() const { return m_surfaceType; } + + void setSurfaceFormat(const QSurfaceFormat &format) { m_format = format; } + QSurfaceFormat surfaceFormat() const { return m_format; } + + void setIgnoreColorChannels(bool ignore) { m_ignore = ignore; } + bool ignoreColorChannels() const { return m_ignore; } + + EGLConfig chooseConfig(); + +protected: + virtual bool filterConfig(EGLConfig config) const; + +private: + QSurfaceFormat m_format; + EGLDisplay m_display; + EGLint m_surfaceType; + bool m_ignore; + + int m_confAttrRed; + int m_confAttrGreen; + int m_confAttrBlue; + int m_confAttrAlpha; +}; + + QT_END_NAMESPACE #endif //QEGLCONVENIENCE_H diff --git a/src/platformsupport/eglconvenience/qeglpbuffer.cpp b/src/platformsupport/eglconvenience/qeglpbuffer.cpp new file mode 100644 index 0000000000..919314e9aa --- /dev/null +++ b/src/platformsupport/eglconvenience/qeglpbuffer.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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 <QtGui/QOffscreenSurface> +#include "qeglpbuffer_p.h" +#include "qeglconvenience_p.h" + +QT_BEGIN_NAMESPACE + +QEGLPbuffer::QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface) + : QPlatformOffscreenSurface(offscreenSurface) + , m_format(format) + , m_display(display) + , m_pbuffer(EGL_NO_SURFACE) +{ + EGLConfig config = q_configFromGLFormat(m_display, m_format, false, EGL_PBUFFER_BIT); + + if (config) { + const EGLint attributes[] = { + EGL_WIDTH, offscreenSurface->size().width(), + EGL_HEIGHT, offscreenSurface->size().height(), + EGL_LARGEST_PBUFFER, EGL_FALSE, + EGL_NONE + }; + + m_pbuffer = eglCreatePbufferSurface(m_display, config, attributes); + + if (m_pbuffer != EGL_NO_SURFACE) + m_format = q_glFormatFromConfig(m_display, config); + } +} + +QEGLPbuffer::~QEGLPbuffer() +{ + eglDestroySurface(m_display, m_pbuffer); +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglpbuffer_p.h b/src/platformsupport/eglconvenience/qeglpbuffer_p.h new file mode 100644 index 0000000000..1b4ac6f991 --- /dev/null +++ b/src/platformsupport/eglconvenience/qeglpbuffer_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** 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 QEGLPBUFFER_H +#define QEGLPBUFFER_H + +#include <EGL/egl.h> +#include <qpa/qplatformoffscreensurface.h> + +QT_BEGIN_NAMESPACE + +class QEGLPbuffer : public QPlatformOffscreenSurface +{ +public: + QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface); + ~QEGLPbuffer(); + + QSurfaceFormat format() const { return m_format; } + bool isValid() const { return m_pbuffer != EGL_NO_SURFACE; } + + EGLSurface pbuffer() const { return m_pbuffer; } + +private: + QSurfaceFormat m_format; + EGLDisplay m_display; + EGLSurface m_pbuffer; +}; + +QT_END_NAMESPACE + +#endif // QEGLPBUFFER_H diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp index 7cce8d89d5..8152f74067 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp @@ -63,9 +63,23 @@ QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatform EGLenum eglApi) : m_eglDisplay(display) , m_eglApi(eglApi) - , m_eglConfig(q_configFromGLFormat(display, format, true)) - , m_format(q_glFormatFromConfig(display, m_eglConfig)) + , m_eglConfig(q_configFromGLFormat(display, format)) { + init(format, share); +} + +QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, + EGLConfig config, EGLenum eglApi) + : m_eglDisplay(display) + , m_eglApi(eglApi) + , m_eglConfig(config) +{ + init(format, share); +} + +void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLContext *share) +{ + m_format = q_glFormatFromConfig(m_eglDisplay, m_eglConfig); m_shareContext = share ? static_cast<QEGLPlatformContext *>(share)->m_eglContext : 0; QVector<EGLint> contextAttrs; diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h index 76002da2df..952f5a856a 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h @@ -51,6 +51,8 @@ class QEGLPlatformContext : public QPlatformOpenGLContext public: QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLenum eglApi = EGL_OPENGL_ES_API); + QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, + EGLConfig config, EGLenum eglApi = EGL_OPENGL_ES_API); ~QEGLPlatformContext(); bool makeCurrent(QPlatformSurface *surface); @@ -70,12 +72,14 @@ protected: virtual EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) = 0; private: + void init(const QSurfaceFormat &format, QPlatformOpenGLContext *share); + EGLContext m_eglContext; EGLContext m_shareContext; EGLDisplay m_eglDisplay; EGLenum m_eglApi; EGLConfig m_eglConfig; - const QSurfaceFormat m_format; + QSurfaceFormat m_format; }; #endif //QEGLPLATFORMCONTEXT_H diff --git a/src/platformsupport/fbconvenience/qfbcursor.cpp b/src/platformsupport/fbconvenience/qfbcursor.cpp index ac2fc8528c..fecf9f6380 100644 --- a/src/platformsupport/fbconvenience/qfbcursor.cpp +++ b/src/platformsupport/fbconvenience/qfbcursor.cpp @@ -120,7 +120,7 @@ void QFbCursor::setCursor(const uchar *data, const uchar *mask, int width, int h void QFbCursor::changeCursor(QCursor * widgetCursor, QWindow *window) { Q_UNUSED(window); - Qt::CursorShape shape = widgetCursor->shape(); + const Qt::CursorShape shape = widgetCursor ? widgetCursor->shape() : Qt::ArrowCursor; if (shape == Qt::BitmapCursor) { // application supplied cursor diff --git a/src/platformsupport/fbconvenience/qfbscreen.cpp b/src/platformsupport/fbconvenience/qfbscreen.cpp index efabf6e2a8..6427b62972 100644 --- a/src/platformsupport/fbconvenience/qfbscreen.cpp +++ b/src/platformsupport/fbconvenience/qfbscreen.cpp @@ -45,6 +45,7 @@ #include "qfbbackingstore_p.h" #include <QtGui/QPainter> +#include <qpa/qwindowsysteminterface.h> QT_BEGIN_NAMESPACE @@ -72,6 +73,9 @@ void QFbScreen::addWindow(QFbWindow *window) mWindowStack.prepend(window); invalidateRectCache(); setDirty(window->geometry()); + QWindow *w = topWindow(); + QWindowSystemInterface::handleWindowActivated(w); + topWindowChanged(w); } void QFbScreen::removeWindow(QFbWindow *window) @@ -79,6 +83,9 @@ void QFbScreen::removeWindow(QFbWindow *window) mWindowStack.removeOne(window); invalidateRectCache(); setDirty(window->geometry()); + QWindow *w = topWindow(); + QWindowSystemInterface::handleWindowActivated(w); + topWindowChanged(w); } void QFbScreen::raise(QFbWindow *window) @@ -89,6 +96,9 @@ void QFbScreen::raise(QFbWindow *window) mWindowStack.move(index, 0); invalidateRectCache(); setDirty(window->geometry()); + QWindow *w = topWindow(); + QWindowSystemInterface::handleWindowActivated(w); + topWindowChanged(w); } void QFbScreen::lower(QFbWindow *window) @@ -99,20 +109,25 @@ void QFbScreen::lower(QFbWindow *window) mWindowStack.move(index, mWindowStack.size() - 1); invalidateRectCache(); setDirty(window->geometry()); + QWindow *w = topWindow(); + QWindowSystemInterface::handleWindowActivated(w); + topWindowChanged(w); +} + +QWindow *QFbScreen::topWindow() const +{ + foreach (QFbWindow *fbw, mWindowStack) + if (fbw->window()->type() == Qt::Window || fbw->window()->type() == Qt::Dialog) + return fbw->window(); + return 0; } QWindow *QFbScreen::topLevelAt(const QPoint & p) const { - Q_UNUSED(p); -#if 0 - for (int i = 0; i < mWindowStack.size(); i++) { - if (mWindowStack[i]->geometry().contains(p, false) && - mWindowStack[i]->visible() && - !mWindowStack[i]->widget()->isMinimized()) { - return mWindowStack[i]->widget(); - } + foreach (QFbWindow *fbw, mWindowStack) { + if (fbw->geometry().contains(p, false) && fbw->window()->isVisible()) + return fbw->window(); } -#endif return 0; } @@ -126,6 +141,24 @@ void QFbScreen::setDirty(const QRect &rect) } } +void QFbScreen::setPhysicalSize(const QSize &size) +{ + mPhysicalSize = size; +} + +void QFbScreen::setGeometry(const QRect &rect) +{ + delete mCompositePainter; + mCompositePainter = 0; + delete mScreenImage; + mGeometry = rect; + mScreenImage = new QImage(mGeometry.size(), mFormat); + invalidateRectCache(); + QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry()); + QWindowSystemInterface::handleScreenAvailableGeometryChange(QPlatformScreen::screen(), availableGeometry()); + resizeMaximizedWindows(); +} + void QFbScreen::generateRects() { mCachedRects.clear(); diff --git a/src/platformsupport/fbconvenience/qfbscreen_p.h b/src/platformsupport/fbconvenience/qfbscreen_p.h index 00e3f9bef4..c7106358d9 100644 --- a/src/platformsupport/fbconvenience/qfbscreen_p.h +++ b/src/platformsupport/fbconvenience/qfbscreen_p.h @@ -64,6 +64,7 @@ public: virtual QImage::Format format() const { return mFormat; } virtual QSizeF physicalSize() const { return mPhysicalSize; } + QWindow *topWindow() const; virtual QWindow *topLevelAt(const QPoint & p) const; // compositor api @@ -71,7 +72,12 @@ public: virtual void removeWindow(QFbWindow *window); virtual void raise(QFbWindow *window); virtual void lower(QFbWindow *window); + virtual void topWindowChanged(QWindow *) {} + +public slots: virtual void setDirty(const QRect &rect); + void setPhysicalSize(const QSize &size); + void setGeometry(const QRect &rect); protected slots: virtual QRegion doRedraw(); diff --git a/src/platformsupport/fbconvenience/qfbwindow.cpp b/src/platformsupport/fbconvenience/qfbwindow.cpp index e052907c79..246f50b4a9 100644 --- a/src/platformsupport/fbconvenience/qfbwindow.cpp +++ b/src/platformsupport/fbconvenience/qfbwindow.cpp @@ -43,6 +43,7 @@ #include "qfbscreen_p.h" #include <QtGui/QScreen> +#include <qpa/qwindowsysteminterface.h> QT_BEGIN_NAMESPACE @@ -71,7 +72,7 @@ void QFbWindow::setGeometry(const QRect &rect) mOldGeometry = geometry(); platformScreen()->invalidateRectCache(); - //### QWindowSystemInterface::handleGeometryChange(window(), rect); + QWindowSystemInterface::handleGeometryChange(window(), rect); QPlatformWindow::setGeometry(rect); } diff --git a/src/platformsupport/fbconvenience/qfbwindow_p.h b/src/platformsupport/fbconvenience/qfbwindow_p.h index 8c7d5c6b7a..25e2afca14 100644 --- a/src/platformsupport/fbconvenience/qfbwindow_p.h +++ b/src/platformsupport/fbconvenience/qfbwindow_p.h @@ -58,7 +58,7 @@ public: virtual void raise(); virtual void lower(); - void setGeometry(const QRect &rect); + virtual void setGeometry(const QRect &rect); virtual void setWindowFlags(Qt::WindowFlags type); virtual Qt::WindowFlags windowFlags() const; diff --git a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp index a74516214b..f17eff4dd7 100644 --- a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp @@ -217,8 +217,8 @@ QSupportedWritingSystems QBasicFontDatabase::determineWritingSystemsFromTrueType static inline bool scriptRequiresOpenType(int script) { - return ((script >= QUnicodeTables::Syriac && script <= QUnicodeTables::Sinhala) - || script == QUnicodeTables::Khmer || script == QUnicodeTables::Nko); + return ((script >= QChar::Script_Syriac && script <= QChar::Script_Sinhala) + || script == QChar::Script_Khmer || script == QChar::Script_Nko); } void QBasicFontDatabase::populateFontDatabase() @@ -242,7 +242,7 @@ void QBasicFontDatabase::populateFontDatabase() } } -QFontEngine *QBasicFontDatabase::fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *usrPtr) +QFontEngine *QBasicFontDatabase::fontEngine(const QFontDef &fontDef, QChar::Script script, void *usrPtr) { QFontEngineFT *engine; FontFile *fontfile = static_cast<FontFile *> (usrPtr); @@ -262,8 +262,7 @@ QFontEngine *QBasicFontDatabase::fontEngine(const QFontDef &fontDef, QUnicodeTab delete engine; engine = 0; } else if (scriptRequiresOpenType(script)) { - HB_Face hbFace = engine->initializedHarfbuzzFace(); - if (!hbFace || !hbFace->supported_scripts[script]) { + if (!engine->supportsScript(script)) { delete engine; engine = 0; } @@ -337,7 +336,7 @@ QFontEngine *QBasicFontDatabase::fontEngine(const QByteArray &fontData, qreal pi return fe; } -QStringList QBasicFontDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const +QStringList QBasicFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const { Q_UNUSED(family); Q_UNUSED(style); diff --git a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h index 23f60fc611..8bb574f335 100644 --- a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h @@ -58,9 +58,9 @@ class QBasicFontDatabase : public QPlatformFontDatabase { public: void populateFontDatabase(); - QFontEngine *fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle); + QFontEngine *fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle); QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference); - QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const; + QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const; QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName); void releaseHandle(void *handle); diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 84eb6613a3..329268395e 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -75,10 +75,11 @@ static inline bool requiresOpenType(int writingSystem) return ((writingSystem >= QFontDatabase::Syriac && writingSystem <= QFontDatabase::Sinhala) || writingSystem == QFontDatabase::Khmer || writingSystem == QFontDatabase::Nko); } + static inline bool scriptRequiresOpenType(int script) { - return ((script >= QUnicodeTables::Syriac && script <= QUnicodeTables::Sinhala) - || script == QUnicodeTables::Khmer || script == QUnicodeTables::Nko); + return ((script >= QChar::Script_Syriac && script <= QChar::Script_Sinhala) + || script == QChar::Script_Khmer || script == QChar::Script_Nko); } static int getFCWeight(int fc_weight) @@ -97,14 +98,17 @@ static int getFCWeight(int fc_weight) } static const char *specialLanguages[] = { - "en", // Common + "", // Unknown + "", // Inherited + "", // Common + "en", // Latin "el", // Greek "ru", // Cyrillic "hy", // Armenian "he", // Hebrew "ar", // Arabic "syr", // Syriac - "div", // Thaana + "dv", // Thaana "hi", // Devanagari "bn", // Bengali "pa", // Gurmukhi @@ -121,45 +125,85 @@ static const char *specialLanguages[] = { "my", // Myanmar "ka", // Georgian "ko", // Hangul - "", // Ogham - "", // Runic + "am", // Ethiopic + "chr", // Cherokee + "cr", // CanadianAboriginal + "sga", // Ogham + "non", // Runic "km", // Khmer - "" // N'Ko + "mn", // Mongolian + "ja", // Hiragana + "ja", // Katakana + "zh", // Bopomofo + "zh", // Han + "ii", // Yi + "ett", // OldItalic + "got", // Gothic + "en", // Deseret + "fil", // Tagalog + "hnn", // Hanunoo + "bku", // Buhid + "tbw", // Tagbanwa + "cop", // Coptic + "lif", // Limbu + "tdd", // TaiLe + "grc", // LinearB + "uga", // Ugaritic + "en", // Shavian + "so", // Osmanya + "grc", // Cypriot + "", // Braille + "bug", // Buginese + "khb", // NewTaiLue + "cu", // Glagolitic + "shi", // Tifinagh + "syl", // SylotiNagri + "peo", // OldPersian + "pra", // Kharoshthi + "ban", // Balinese + "akk", // Cuneiform + "phn", // Phoenician + "lzh", // PhagsPa + "man", // Nko + "su", // Sundanese + "lep", // Lepcha + "sat", // OlChiki + "vai", // Vai + "saz", // Saurashtra + "eky", // KayahLi + "rej", // Rejang + "xlc", // Lycian + "xcr", // Carian + "xld", // Lydian + "cjm", // Cham + "nod", // TaiTham + "blt", // TaiViet + "ae", // Avestan + "egy", // EgyptianHieroglyphs + "smp", // Samaritan + "lis", // Lisu + "bax", // Bamum + "jv", // Javanese + "mni", // MeeteiMayek + "arc", // ImperialAramaic + "xsa", // OldSouthArabian + "xpr", // InscriptionalParthian + "pal", // InscriptionalPahlavi + "otk", // OldTurkic + "bh", // Kaithi + "bbc", // Batak + "pra", // Brahmi + "myz", // Mandaic + "ccp", // Chakma + "xmr", // MeroiticCursive + "xmr", // MeroiticHieroglyphs + "hmd", // Miao + "sa", // Sharada + "srb", // SoraSompeng + "doi" // Takri }; enum { SpecialLanguageCount = sizeof(specialLanguages) / sizeof(const char *) }; -static const ushort specialChars[] = { - 0, // English - 0, // Greek - 0, // Cyrillic - 0, // Armenian - 0, // Hebrew - 0, // Arabic - 0, // Syriac - 0, // Thaana - 0, // Devanagari - 0, // Bengali - 0, // Gurmukhi - 0, // Gujarati - 0, // Oriya - 0, // Tamil - 0xc15, // Telugu - 0xc95, // Kannada - 0xd15, // Malayalam - 0xd9a, // Sinhala - 0, // Thai - 0, // Lao - 0, // Tibetan - 0x1000, // Myanmar - 0, // Georgian - 0, // Hangul - 0x1681, // Ogham - 0x16a0, // Runic - 0, // Khmer - 0x7ca // N'Ko -}; -enum { SpecialCharCount = sizeof(specialChars) / sizeof(ushort) }; - // this could become a list of all languages used for each writing // system, instead of using the single most common language. static const char *languageForWritingSystem[] = { @@ -194,9 +238,9 @@ static const char *languageForWritingSystem[] = { "ko", // Korean "vi", // Vietnamese 0, // Symbol - 0, // Ogham - 0, // Runic - 0 // N'Ko + "sga", // Ogham + "non", // Runic + "man" // N'Ko }; enum { LanguageCount = sizeof(languageForWritingSystem) / sizeof(const char *) }; @@ -402,7 +446,7 @@ void QFontconfigDatabase::populateFontDatabase() // some languages are not supported by FontConfig, we rather check the // charset to detect these for (int i = 1; i < SampleCharCount; ++i) { - if (!sampleCharForWritingSystem[i]) + if (!sampleCharForWritingSystem[i] || writingSystems.supported(QFontDatabase::WritingSystem(i))) continue; if (FcCharSetHasChar(cs, sampleCharForWritingSystem[i])) writingSystems.setSupported(QFontDatabase::WritingSystem(i)); @@ -481,13 +525,12 @@ void QFontconfigDatabase::populateFontDatabase() // QApplication::setFont(font); } -QFontEngineMulti *QFontconfigDatabase::fontEngineMulti(QFontEngine *fontEngine, - QUnicodeTables::Script script) +QFontEngineMulti *QFontconfigDatabase::fontEngineMulti(QFontEngine *fontEngine, QChar::Script script) { return new QFontEngineMultiFontConfig(fontEngine, script); } -QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QUnicodeTables::Script script, void *usrPtr) +QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QChar::Script script, void *usrPtr) { if (!usrPtr) return 0; @@ -595,8 +638,7 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QUnicodeTables:: delete engine; engine = 0; } else if (scriptRequiresOpenType(script)) { - HB_Face hbFace = engine->initializedHarfbuzzFace(); - if (!hbFace || !hbFace->supported_scripts[script]) { + if (!engine->supportsScript(script)) { delete engine; engine = 0; } @@ -605,7 +647,7 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QUnicodeTables:: return engine; } -QStringList QFontconfigDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const +QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const { QStringList fallbackFamilies; FcPattern *pattern = FcPatternCreate(); @@ -625,8 +667,8 @@ QStringList QFontconfigDatabase::fallbacksForFamily(const QString family, const slant_value = FC_SLANT_OBLIQUE; FcPatternAddInteger(pattern, FC_SLANT, slant_value); - if (script != QUnicodeTables::Common && *specialLanguages[script] != '\0') { - Q_ASSERT(script < QUnicodeTables::ScriptCount); + Q_ASSERT(uint(script) < SpecialLanguageCount); + if (*specialLanguages[script] != '\0') { FcLangSet *ls = FcLangSetCreate(); FcLangSetAdd(ls, (const FcChar8*)specialLanguages[script]); FcPatternAddLangSet(pattern, FC_LANG, ls); diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h index cb05ef4722..6d6dae680e 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h @@ -51,9 +51,9 @@ class QFontconfigDatabase : public QBasicFontDatabase { public: void populateFontDatabase(); - QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QUnicodeTables::Script script); - QFontEngine *fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle); - QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const; + QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script); + QFontEngine *fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle); + QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const; QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName); QString resolveFontFamilyAlias(const QString &family) const; QFont defaultFont() const; diff --git a/src/platformsupport/fontdatabases/mac/coretext.pri b/src/platformsupport/fontdatabases/mac/coretext.pri index f7977964fe..d1abf123aa 100644 --- a/src/platformsupport/fontdatabases/mac/coretext.pri +++ b/src/platformsupport/fontdatabases/mac/coretext.pri @@ -1,2 +1,10 @@ HEADERS += $$PWD/qcoretextfontdatabase_p.h $$PWD/qfontengine_coretext_p.h OBJECTIVE_SOURCES += $$PWD/qfontengine_coretext.mm $$PWD/qcoretextfontdatabase.mm + +ios: \ + # On iOS CoreText and CoreGraphics are stand-alone frameworks + LIBS += -framework CoreText -framework CoreGraphics +else: \ + # On Mac OS they are part of the ApplicationServices umbrella framework, + # even in 10.8 where they were also made available stand-alone. + LIBS += -framework ApplicationServices diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index d59bd5f116..fbd836f763 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -39,6 +39,8 @@ ** ****************************************************************************/ +#include "qglobal.h" + #ifndef Q_OS_IOS #import <Cocoa/Cocoa.h> #import <IOKit/graphics/IOGraphicsLib.h> @@ -85,28 +87,12 @@ static const char *languageForWritingSystem[] = { "ko", // Korean "vi", // Vietnamese 0, // Symbol - 0, // Ogham - 0, // Runic - 0 // N'Ko + "sga", // Ogham + "non", // Runic + "man" // N'Ko }; enum { LanguageCount = sizeof(languageForWritingSystem) / sizeof(const char *) }; -QFont::StyleHint styleHintFromNSString(NSString *style) -{ - if ([style isEqual: @"sans-serif"]) - return QFont::SansSerif; - else if ([style isEqual: @"monospace"]) - return QFont::Monospace; - else if ([style isEqual: @"cursive"]) - return QFont::Cursive; - else if ([style isEqual: @"serif"]) - return QFont::Serif; - else if ([style isEqual: @"fantasy"]) - return QFont::Fantasy; - else // if ([style isEqual: @"default"]) - return QFont::AnyStyle; -} - static NSInteger languageMapSort(id obj1, id obj2, void *context) { NSArray *map1 = (NSArray *) obj1; @@ -188,27 +174,6 @@ QCoreTextFontDatabase::~QCoreTextFontDatabase() { } -static QString familyNameFromPostScriptName(QHash<QString, QString> &psNameToFamily, - NSString *psName) -{ - QString name = QCFString::toQString(psName); - if (psNameToFamily.contains(name)) - return psNameToFamily[name]; - else { - // Some of the font name in DefaultFontFallbacks.plist are hidden fonts like AquaHiraKaku, - // their family name begins with a dot, like ".AquaHiraKaku" or ".Apple Symbols Fallback", - // the only way (I've found) to get it are actually creating a CTFont with them. We only - // need to do it once though. - QCFType<CTFontRef> font = CTFontCreateWithName((CFStringRef) psName, 12.0, NULL); - if (font) { - QCFString family = CTFontCopyFamilyName(font); - psNameToFamily[name] = family; - return family; - } - return name; - } -} - void QCoreTextFontDatabase::populateFontDatabase() { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -223,7 +188,6 @@ void QCoreTextFontDatabase::populateFontDatabase() QString foundryName = QLatin1String("CoreText"); const int numFonts = CFArrayGetCount(fonts); - QHash<QString, QString> psNameToFamily; for (int i = 0; i < numFonts; ++i) { CTFontDescriptorRef font = (CTFontDescriptorRef) CFArrayGetValueAtIndex(fonts, i); QCFString familyName = (CFStringRef) CTFontDescriptorCopyLocalizedAttribute(font, kCTFontFamilyNameAttribute, NULL); @@ -289,35 +253,14 @@ void QCoreTextFontDatabase::populateFontDatabase() QPlatformFontDatabase::registerFont(familyName, styleName, foundryName, weight, style, stretch, true /* antialiased */, true /* scalable */, pixelSize, fixedPitch, writingSystems, (void *) font); + + // We need to map back and forth between PostScript-names and family-names for fallback list construction CFStringRef psName = (CFStringRef) CTFontDescriptorCopyAttribute(font, kCTFontNameAttribute); - // we need PostScript Name to family name mapping for fallback list construction psNameToFamily[QCFString::toQString((NSString *) psName)] = familyName; + familyNameToPsName[familyName] = QCFString::toQString((NSString *) psName); CFRelease(psName); } - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - NSArray *languages = [defaults stringArrayForKey: @"AppleLanguages"]; - - NSDictionary *fallbackDict = [NSDictionary dictionaryWithContentsOfFile: @"/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/Resources/DefaultFontFallbacks.plist"]; - - for (NSString *style in [fallbackDict allKeys]) { - NSArray *list = [fallbackDict valueForKey: style]; - QFont::StyleHint styleHint = styleHintFromNSString(style); - QStringList fallbackList; - for (id item in list) { - // sort the array based on system language preferences - if ([item isKindOfClass: [NSArray class]]) { - NSArray *langs = [(NSArray *) item sortedArrayUsingFunction: languageMapSort - context: languages]; - for (NSArray *map in langs) - fallbackList.append(familyNameFromPostScriptName(psNameToFamily, [map objectAtIndex: 1])); - } - else if ([item isKindOfClass: [NSString class]]) - fallbackList.append(familyNameFromPostScriptName(psNameToFamily, item)); - } - fallbackLists[styleHint] = fallbackList; - } - [pool release]; } @@ -326,7 +269,7 @@ void QCoreTextFontDatabase::releaseHandle(void *handle) CFRelease(CTFontDescriptorRef(handle)); } -QFontEngine *QCoreTextFontDatabase::fontEngine(const QFontDef &f, QUnicodeTables::Script script, void *usrPtr) +QFontEngine *QCoreTextFontDatabase::fontEngine(const QFontDef &f, QChar::Script script, void *usrPtr) { Q_UNUSED(script); @@ -376,14 +319,142 @@ QFontEngine *QCoreTextFontDatabase::fontEngine(const QByteArray &fontData, qreal return fontEngine; } -QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const +QFont::StyleHint styleHintFromNSString(NSString *style) +{ + if ([style isEqual: @"sans-serif"]) + return QFont::SansSerif; + else if ([style isEqual: @"monospace"]) + return QFont::Monospace; + else if ([style isEqual: @"cursive"]) + return QFont::Cursive; + else if ([style isEqual: @"serif"]) + return QFont::Serif; + else if ([style isEqual: @"fantasy"]) + return QFont::Fantasy; + else // if ([style isEqual: @"default"]) + return QFont::AnyStyle; +} + +static QString familyNameFromPostScriptName(QHash<QString, QString> &psNameToFamily, + NSString *psName) +{ + QString name = QCFString::toQString(psName); + if (psNameToFamily.contains(name)) + return psNameToFamily[name]; + else { + // Some of the font name in DefaultFontFallbacks.plist are hidden fonts like AquaHiraKaku, + // their family name begins with a dot, like ".AquaHiraKaku" or ".Apple Symbols Fallback", + // the only way (I've found) to get it are actually creating a CTFont with them. We only + // need to do it once though. + QCFType<CTFontRef> font = CTFontCreateWithName((CFStringRef) psName, 12.0, NULL); + if (font) { + QCFString family = CTFontCopyFamilyName(font); + psNameToFamily[name] = family; + return family; + } + return name; + } +} + +QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const { - Q_UNUSED(family); Q_UNUSED(style); Q_UNUSED(script); - if (fallbackLists.isEmpty()) + + static QHash<QString, QStringList> fallbackLists; + +#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_8, __IPHONE_6_0) + // CTFontCopyDefaultCascadeListForLanguages is available in the SDK + #if QT_MAC_DEPLOYMENT_TARGET_BELOW(__MAC_10_8, __IPHONE_6_0) + // But we have to feature check at runtime + if (&CTFontCopyDefaultCascadeListForLanguages) + #endif + { + if (fallbackLists.contains(family)) + return fallbackLists.value(family); + + if (!familyNameToPsName.contains(family)) + const_cast<QCoreTextFontDatabase*>(this)->populateFontDatabase(); + + QCFType<CTFontRef> font = CTFontCreateWithName(QCFString(familyNameToPsName[family]), 12.0, NULL); + if (font) { + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + NSArray *languages = [defaults stringArrayForKey: @"AppleLanguages"]; + + QCFType<CFArrayRef> cascadeList = (CFArrayRef) CTFontCopyDefaultCascadeListForLanguages(font, (CFArrayRef) languages); + if (cascadeList) { + QStringList fallbackList; + const int numCascades = CFArrayGetCount(cascadeList); + for (int i = 0; i < numCascades; ++i) { + CTFontDescriptorRef fontFallback = (CTFontDescriptorRef) CFArrayGetValueAtIndex(cascadeList, i); + QCFString fallbackFamilyName = (CFStringRef) CTFontDescriptorCopyLocalizedAttribute(fontFallback, kCTFontFamilyNameAttribute, NULL); + fallbackList.append(QCFString::toQString(fallbackFamilyName)); + } + fallbackLists[family] = fallbackList; + } + } + + if (fallbackLists.contains(family)) + return fallbackLists.value(family); + } +#else + Q_UNUSED(family); +#endif + + // We were not able to find a fallback for the specific family, + // so we fall back to the stylehint. + + static const QString styleLookupKey = QString::fromLatin1(".QFontStyleHint_%1"); + + static bool didPopulateStyleFallbacks = false; + if (!didPopulateStyleFallbacks) { +#if !defined(Q_OS_IOS) + // Ensure we have the psNameToFamily mapping set up const_cast<QCoreTextFontDatabase*>(this)->populateFontDatabase(); - return fallbackLists[styleHint]; + + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + NSArray *languages = [defaults stringArrayForKey: @"AppleLanguages"]; + + NSDictionary *fallbackDict = [NSDictionary dictionaryWithContentsOfFile: @"/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/Resources/DefaultFontFallbacks.plist"]; + + for (NSString *style in [fallbackDict allKeys]) { + NSArray *list = [fallbackDict valueForKey: style]; + QFont::StyleHint fallbackStyleHint = styleHintFromNSString(style); + QStringList fallbackList; + for (id item in list) { + // sort the array based on system language preferences + if ([item isKindOfClass: [NSArray class]]) { + NSArray *langs = [(NSArray *) item sortedArrayUsingFunction: languageMapSort + context: languages]; + for (NSArray *map in langs) + fallbackList.append(familyNameFromPostScriptName(psNameToFamily, [map objectAtIndex: 1])); + } + else if ([item isKindOfClass: [NSString class]]) + fallbackList.append(familyNameFromPostScriptName(psNameToFamily, item)); + } + + if (QCoreTextFontEngine::supportsColorGlyphs()) + fallbackList.append(QLatin1String("Apple Color Emoji")); + + fallbackLists[styleLookupKey.arg(fallbackStyleHint)] = fallbackList; + } +#else + QStringList staticFallbackList; + staticFallbackList << QString::fromLatin1("Helvetica,Apple Color Emoji,Geeza Pro,Arial Hebrew,Thonburi,Kailasa" + "Hiragino Kaku Gothic ProN,.Heiti J,Apple SD Gothic Neo,.Heiti K,Heiti SC,Heiti TC" + "Bangla Sangam MN,Devanagari Sangam MN,Gujarati Sangam MN,Gurmukhi MN,Kannada Sangam MN" + "Malayalam Sangam MN,Oriya Sangam MN,Sinhala Sangam MN,Tamil Sangam MN,Telugu Sangam MN" + "Euphemia UCAS,.PhoneFallback").split(QLatin1String(",")); + + for (int i = QFont::Helvetica; i <= QFont::Fantasy; ++i) + fallbackLists[styleLookupKey.arg(i)] = staticFallbackList; +#endif + + didPopulateStyleFallbacks = true; + } + + Q_ASSERT(!fallbackLists.isEmpty()); + return fallbackLists[styleLookupKey.arg(styleHint)]; } #ifndef Q_OS_IOS diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h index dcec738598..5b9b8e2329 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h @@ -52,9 +52,9 @@ public: QCoreTextFontDatabase(); ~QCoreTextFontDatabase(); void populateFontDatabase(); - QFontEngine *fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle); + QFontEngine *fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle); QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference); - QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const; + QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const; #ifndef Q_OS_IOS QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName); #endif @@ -64,7 +64,8 @@ public: private: mutable QString defaultFontName; - QHash<QFont::StyleHint, QStringList> fallbackLists; + mutable QHash<QString, QString> psNameToFamily; + mutable QHash<QString, QString> familyNameToPsName; }; QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 5c46907bc5..3e553acd0a 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -46,8 +46,6 @@ #include <private/qimage_p.h> -#if !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - QT_BEGIN_NAMESPACE static float SYNTHETIC_ITALIC_SKEW = tanf(14 * acosf(0) / 90); @@ -158,7 +156,7 @@ void QCoreTextFontEngine::init() synthesisFlags = 0; CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ctfont); -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 +#if defined(Q_OS_IOS) || MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 if (supportsColorGlyphs() && (traits & kCTFontColorGlyphsTrait)) glyphFormat = QFontEngineGlyphCache::Raster_ARGB; else @@ -457,7 +455,9 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition br.y = QFixed::fromReal(br.y.toReal() * vscale); } - QImage im(qAbs(qRound(br.width))+2, qAbs(qRound(br.height))+2, QImage::Format_RGB32); + bool isColorGlyph = glyphFormat == QFontEngineGlyphCache::Raster_ARGB; + QImage::Format format = isColorGlyph ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; + QImage im(qAbs(qRound(br.width)) + 2, qAbs(qRound(br.height)) + 2, format); im.fill(0); #ifndef Q_OS_IOS @@ -465,7 +465,7 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition #else CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); #endif - uint cgflags = kCGImageAlphaNoneSkipFirst; + uint cgflags = isColorGlyph ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst; #ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version cgflags |= kCGBitmapByteOrder32Host; #endif @@ -476,38 +476,49 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition CGContextSetShouldAntialias(ctx, (aa || fontDef.pointSize > antialiasingThreshold) && !(fontDef.styleStrategy & QFont::NoAntialias)); CGContextSetShouldSmoothFonts(ctx, aa); - CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx); - CGAffineTransform cgMatrix = CGAffineTransformIdentity; - CGAffineTransformConcat(cgMatrix, oldTextMatrix); + CGAffineTransform cgMatrix = CGAffineTransformIdentity; if (synthesisFlags & QFontEngine::SynthesizedItalic) cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, SYNTHETIC_ITALIC_SKEW, 1, 0, 0)); - cgMatrix = CGAffineTransformConcat(cgMatrix, transform); + if (!isColorGlyph) // CTFontDrawGlyphs incorporates the font's matrix already + cgMatrix = CGAffineTransformConcat(cgMatrix, transform); + if (m.isScaling()) cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMakeScale(m.m11(), m.m22())); - CGContextSetTextMatrix(ctx, cgMatrix); - CGContextSetRGBFillColor(ctx, 1, 1, 1, 1); - CGContextSetTextDrawingMode(ctx, kCGTextFill); - - CGContextSetFont(ctx, cgFont); - + CGGlyph cgGlyph = glyph; qreal pos_x = -br.x.truncate() + subPixelPosition.toReal(); qreal pos_y = im.height() + br.y.toReal(); - CGContextSetTextPosition(ctx, pos_x, pos_y); - CGSize advance; - advance.width = 0; - advance.height = 0; - CGGlyph cgGlyph = glyph; - CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1); + if (!isColorGlyph) { + CGContextSetTextMatrix(ctx, cgMatrix); + CGContextSetRGBFillColor(ctx, 1, 1, 1, 1); + CGContextSetTextDrawingMode(ctx, kCGTextFill); + CGContextSetFont(ctx, cgFont); + CGContextSetTextPosition(ctx, pos_x, pos_y); - if (synthesisFlags & QFontEngine::SynthesizedBold) { - CGContextSetTextPosition(ctx, pos_x + 0.5 * lineThickness().toReal(), pos_y); - CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1); + CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &CGSizeZero, 1); + + if (synthesisFlags & QFontEngine::SynthesizedBold) { + CGContextSetTextPosition(ctx, pos_x + 0.5 * lineThickness().toReal(), pos_y); + CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &CGSizeZero, 1); + } } +#if defined(Q_OS_IOS) || MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + else if (supportsColorGlyphs()) { + // CGContextSetTextMatrix does not work with color glyphs, so we use + // the CTM instead. This means we must translate the CTM as well, to + // set the glyph position, instead of using CGContextSetTextPosition. + CGContextTranslateCTM(ctx, pos_x, pos_y); + CGContextConcatCTM(ctx, cgMatrix); + + // CGContextShowGlyphsWithAdvances does not support the 'sbix' color-bitmap + // glyphs in the Apple Color Emoji font, so we use CTFontDrawGlyphs instead. + CTFontDrawGlyphs(ctfont, &cgGlyph, &CGPointZero, 1, ctx); + } +#endif CGContextRelease(ctx); CGColorSpaceRelease(colorspace); @@ -517,7 +528,15 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition QImage QCoreTextFontEngine::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) { - QImage im = imageForGlyph(glyph, subPixelPosition, false, QTransform()); + return alphaMapForGlyph(glyph, subPixelPosition, QTransform()); +} + +QImage QCoreTextFontEngine::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &x) +{ + if (x.type() > QTransform::TxScale) + return QFontEngine::alphaMapForGlyph(glyph, subPixelPosition, x); + + QImage im = imageForGlyph(glyph, subPixelPosition, false, x); QImage indexed(im.width(), im.height(), QImage::Format_Indexed8); QVector<QRgb> colors(256); @@ -548,6 +567,14 @@ QImage QCoreTextFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed subPixelPo return im; } +QImage QCoreTextFontEngine::bitmapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) +{ + if (t.type() > QTransform::TxScale) + return QFontEngine::bitmapForGlyph(glyph, subPixelPosition, t); + + return imageForGlyph(glyph, subPixelPosition, true, t); +} + void QCoreTextFontEngine::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags flags) const { int i, numGlyphs = glyphs->numGlyphs; @@ -609,12 +636,15 @@ QFontEngine *QCoreTextFontEngine::cloneWithSize(qreal pixelSize) const return new QCoreTextFontEngine(cgFont, newFontDef); } -bool QCoreTextFontEngine::supportsTransformations(const QTransform &transform) const +bool QCoreTextFontEngine::supportsTransformation(const QTransform &transform) const { - return transform.type() > QTransform::TxTranslate; + if (transform.type() < QTransform::TxScale) + return true; + else if (transform.type() == QTransform::TxScale && + transform.m11() >= 0 && transform.m22() >= 0) + return true; + else + return false; } QT_END_NAMESPACE - -#endif// !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h index dc73d38522..a9b1960491 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h @@ -52,10 +52,6 @@ #include <CoreGraphics/CoreGraphics.h> #endif -#if !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE class QRawFontPrivate; @@ -98,12 +94,14 @@ public: virtual bool getSfntTableData(uint /*tag*/, uchar * /*buffer*/, uint * /*length*/) const; virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics); virtual QImage alphaMapForGlyph(glyph_t, QFixed subPixelPosition); + virtual QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t); virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t); + virtual QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t); virtual qreal minRightBearing() const; virtual qreal minLeftBearing() const; virtual QFixed emSquareSize() const; - bool supportsTransformations(const QTransform &transform) const; + bool supportsTransformation(const QTransform &transform) const; virtual QFontEngine *cloneWithSize(qreal pixelSize) const; virtual int glyphMargin(QFontEngineGlyphCache::Type type) { Q_UNUSED(type); return 0; } @@ -142,8 +140,4 @@ CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef); QT_END_NAMESPACE -QT_END_HEADER - -#endif// !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - #endif // QFONTENGINE_CORETEXT_P_H diff --git a/src/platformsupport/glxconvenience/qglxconvenience.cpp b/src/platformsupport/glxconvenience/qglxconvenience.cpp index e885ecc105..11d9377db7 100644 --- a/src/platformsupport/glxconvenience/qglxconvenience.cpp +++ b/src/platformsupport/glxconvenience/qglxconvenience.cpp @@ -171,7 +171,7 @@ XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *f GLXFBConfig config = qglx_findConfig(display,screen,*format); if (config) { visualInfo = glXGetVisualFromFBConfig(display, config); - *format = qglx_surfaceFormatFromGLXFBConfig(display, config); + qglx_surfaceFormatFromGLXFBConfig(format, display, config); } // attempt to fall back to glXChooseVisual @@ -221,9 +221,8 @@ XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *f return visualInfo; } -QSurfaceFormat qglx_surfaceFormatFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext) +void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, GLXFBConfig config, GLXContext) { - QSurfaceFormat format; int redSize = 0; int greenSize = 0; int blueSize = 0; @@ -245,20 +244,18 @@ QSurfaceFormat qglx_surfaceFormatFromGLXFBConfig(Display *display, GLXFBConfig c glXGetFBConfigAttrib(display, config, GLX_SAMPLES_ARB, &sampleBuffers); glXGetFBConfigAttrib(display, config, GLX_STEREO, &stereo); - format.setRedBufferSize(redSize); - format.setGreenBufferSize(greenSize); - format.setBlueBufferSize(blueSize); - format.setAlphaBufferSize(alphaSize); - format.setDepthBufferSize(depthSize); - format.setStencilBufferSize(stencilSize); + format->setRedBufferSize(redSize); + format->setGreenBufferSize(greenSize); + format->setBlueBufferSize(blueSize); + format->setAlphaBufferSize(alphaSize); + format->setDepthBufferSize(depthSize); + format->setStencilBufferSize(stencilSize); if (sampleBuffers) { glXGetFBConfigAttrib(display, config, GLX_SAMPLES_ARB, &sampleCount); - format.setSamples(sampleCount); + format->setSamples(sampleCount); } - format.setStereo(stereo); - - return format; + format->setStereo(stereo); } QSurfaceFormat qglx_reduceSurfaceFormat(const QSurfaceFormat &format, bool *reduced) diff --git a/src/platformsupport/glxconvenience/qglxconvenience_p.h b/src/platformsupport/glxconvenience/qglxconvenience_p.h index 70f97d8b38..66548a3479 100644 --- a/src/platformsupport/glxconvenience/qglxconvenience_p.h +++ b/src/platformsupport/glxconvenience/qglxconvenience_p.h @@ -50,7 +50,7 @@ XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *format); GLXFBConfig qglx_findConfig(Display *display, int screen, const QSurfaceFormat &format, int drawableBit = GLX_WINDOW_BIT); -QSurfaceFormat qglx_surfaceFormatFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext context = 0); +void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, GLXFBConfig config, GLXContext context = 0); QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit = GLX_WINDOW_BIT); QSurfaceFormat qglx_reduceSurfaceFormat(const QSurfaceFormat &format, bool *reduced); diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h index 3e5dcb2ac9..1065b05d51 100644 --- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h +++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h @@ -46,8 +46,6 @@ #include <QTimer> #include <QDataStream> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE namespace QEvdevKeyboardMap { @@ -198,6 +196,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QEVDEVKEYBOARDHANDLER_P_H diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h index e750f72c3b..37c60c035c 100644 --- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h +++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h @@ -50,8 +50,6 @@ #include <QHash> #include <QSocketNotifier> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE class QEvdevKeyboardManager : public QObject @@ -71,8 +69,6 @@ private: QDeviceDiscovery *m_deviceDiscovery; }; -QT_END_HEADER - QT_END_NAMESPACE #endif // QEVDEVKEYBOARDMANAGER_P_H diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h b/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h index 6e078b2d70..d419a1913e 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h +++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h @@ -45,8 +45,6 @@ #include <QObject> #include <QString> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE class QSocketNotifier; @@ -83,6 +81,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QEVDEVMOUSEHANDLER_P_H diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h b/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h index a2c83c4a1c..6abe933371 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h +++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h @@ -50,8 +50,6 @@ #include <QHash> #include <QSocketNotifier> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE class QEvdevMouseManager : public QObject @@ -79,8 +77,6 @@ private: int m_yoffset; }; -QT_END_HEADER - QT_END_NAMESPACE #endif // QEVDEVMOUSEMANAGER_P_H diff --git a/src/platformsupport/input/evdevtablet/qevdevtablet_p.h b/src/platformsupport/input/evdevtablet/qevdevtablet_p.h index ce49a01e7b..9222db9907 100644 --- a/src/platformsupport/input/evdevtablet/qevdevtablet_p.h +++ b/src/platformsupport/input/evdevtablet/qevdevtablet_p.h @@ -46,8 +46,6 @@ #include <QString> #include <QThread> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE class QEvdevTabletData; @@ -82,6 +80,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QEVDEVTABLET_P_H diff --git a/src/platformsupport/input/evdevtouch/qevdevtouch_p.h b/src/platformsupport/input/evdevtouch/qevdevtouch_p.h index b4de2ca088..ceb57bdf05 100644 --- a/src/platformsupport/input/evdevtouch/qevdevtouch_p.h +++ b/src/platformsupport/input/evdevtouch/qevdevtouch_p.h @@ -48,8 +48,6 @@ #include <QThread> #include <qpa/qwindowsysteminterface.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE class QSocketNotifier; @@ -93,6 +91,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QEVDEVTOUCH_P_H diff --git a/src/platformsupport/jniconvenience/jniconvenience.pri b/src/platformsupport/jniconvenience/jniconvenience.pri new file mode 100644 index 0000000000..991518e370 --- /dev/null +++ b/src/platformsupport/jniconvenience/jniconvenience.pri @@ -0,0 +1,9 @@ +android { + QT += gui-private + + HEADERS += $$PWD/qjnihelpers_p.h \ + $$PWD/qjniobject_p.h + + SOURCES += $$PWD/qjnihelpers.cpp \ + $$PWD/qjniobject.cpp +} diff --git a/src/platformsupport/jniconvenience/qjnihelpers.cpp b/src/platformsupport/jniconvenience/qjnihelpers.cpp new file mode 100644 index 0000000000..3f9b568368 --- /dev/null +++ b/src/platformsupport/jniconvenience/qjnihelpers.cpp @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part 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 "qjnihelpers_p.h" + +#include <qpa/qplatformnativeinterface.h> +#include <qguiapplication.h> + +QT_BEGIN_NAMESPACE + +QString qt_convertJString(jstring string) +{ + QAttachedJNIEnv env; + int strLength = env->GetStringLength(string); + QString res; + res.resize(strLength); + env->GetStringRegion(string, 0, strLength, (jchar*)res.utf16()); + return res; +} + +QJNILocalRef<jstring> qt_toJString(const QString &string) +{ + QAttachedJNIEnv env; + return QJNILocalRef<jstring>(env->NewString(reinterpret_cast<const jchar*>(string.constData()), + string.length())); +} + + +static JavaVM *g_javaVM = 0; + +static JavaVM *getJavaVM() +{ + if (!g_javaVM){ + QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); + g_javaVM = static_cast<JavaVM*>(nativeInterface->nativeResourceForIntegration("JavaVM")); + } + return g_javaVM; +} + +QThreadStorage<int> QAttachedJNIEnv::m_refCount; + +QAttachedJNIEnv::QAttachedJNIEnv() +{ + JavaVM *vm = javaVM(); + if (vm->GetEnv((void**)&jniEnv, JNI_VERSION_1_6) == JNI_EDETACHED) { + if (vm->AttachCurrentThread(&jniEnv, 0) < 0) { + jniEnv = 0; + return; + } + } + + if (!m_refCount.hasLocalData()) + m_refCount.setLocalData(1); + else + m_refCount.setLocalData(m_refCount.localData() + 1); +} + +QAttachedJNIEnv::~QAttachedJNIEnv() +{ + if (!jniEnv) + return; + + int newRef = m_refCount.localData() - 1; + m_refCount.setLocalData(newRef); + + if (newRef == 0) + javaVM()->DetachCurrentThread(); + + jniEnv = 0; +} + +JavaVM *QAttachedJNIEnv::javaVM() +{ + return getJavaVM(); +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/jniconvenience/qjnihelpers_p.h b/src/platformsupport/jniconvenience/qjnihelpers_p.h new file mode 100644 index 0000000000..fb44d156bd --- /dev/null +++ b/src/platformsupport/jniconvenience/qjnihelpers_p.h @@ -0,0 +1,191 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part 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 QJNIHELPERS_H +#define QJNIHELPERS_H + +#include <jni.h> +#include <qglobal.h> +#include <QString> +#include <QThreadStorage> + +QT_BEGIN_NAMESPACE + +template <typename T> +class QJNILocalRef; + +QString qt_convertJString(jstring string); +QJNILocalRef<jstring> qt_toJString(const QString &string); + + +struct QAttachedJNIEnv +{ + QAttachedJNIEnv(); + ~QAttachedJNIEnv(); + + static JavaVM *javaVM(); + + JNIEnv *operator->() + { + return jniEnv; + } + + operator JNIEnv*() const + { + return jniEnv; + } + + JNIEnv *jniEnv; + +private: + static QThreadStorage<int> m_refCount; +}; + + +template <typename T> +class QJNILocalRef +{ +public: + inline QJNILocalRef() : m_obj(0) { } + inline explicit QJNILocalRef(T o) : m_obj(o) { } + inline QJNILocalRef(const QJNILocalRef<T> &other) : m_obj(other.m_obj) + { + if (other.m_obj) + m_obj = static_cast<T>(m_env->NewLocalRef(other.m_obj)); + } + + template <typename X> + inline QJNILocalRef(const QJNILocalRef<X> &other) : m_obj(other.m_obj) + { + if (other.m_obj) + m_obj = static_cast<T>(m_env->NewLocalRef(other.m_obj)); + } + + inline ~QJNILocalRef() { release(); } + + inline QJNILocalRef<T> &operator=(const QJNILocalRef<T> &other) + { + release(); + m_obj = other.m_obj; // for type checking + if (other.m_obj) + m_obj = static_cast<T>(m_env->NewLocalRef(other.m_obj)); + return *this; + } + + template <typename X> + inline QJNILocalRef<T> &operator=(const QJNILocalRef<X> &other) + { + release(); + m_obj = other.m_obj; // for type checking + if (other.m_obj) + m_obj = static_cast<T>(m_env->NewLocalRef(other.m_obj)); + return *this; + } + + inline QJNILocalRef<T> &operator=(T o) + { + release(); + m_obj = o; + return *this; + } + + template <typename X> + inline QJNILocalRef<T> &operator=(X o) + { + release(); + m_obj = o; + return *this; + } + + inline bool operator !() const { return !m_obj; } + inline bool isNull() const { return !m_obj; } + inline T object() const { return m_obj; } + +private: + void release() + { + if (m_obj) { + m_env->DeleteLocalRef(m_obj); + m_obj = 0; + } + } + + QAttachedJNIEnv m_env; + T m_obj; + + template <class X> friend class QJNILocalRef; +}; + +template <class T, class X> +bool operator==(const QJNILocalRef<T> &ptr1, const QJNILocalRef<X> &ptr2) +{ + return ptr1.m_obj == ptr2.m_obj; +} +template <class T, class X> +bool operator!=(const QJNILocalRef<T> &ptr1, const QJNILocalRef<X> &ptr2) +{ + return ptr1.m_obj != ptr2.m_obj; +} + +template <class T, class X> +bool operator==(const QJNILocalRef<T> &ptr1, X ptr2) +{ + return ptr1.m_obj == ptr2; +} +template <class T, class X> +bool operator==(T ptr1, const QJNILocalRef<X> &ptr2) +{ + return ptr1 == ptr2.m_obj; +} +template <class T, class X> +bool operator!=(const QJNILocalRef<T> &ptr1, X ptr2) +{ + return !(ptr1 == ptr2); +} +template <class T, class X> +bool operator!=(const T *ptr1, const QJNILocalRef<X> &ptr2) +{ + return !(ptr2 == ptr1); +} + +QT_END_NAMESPACE + +#endif // QJNIHELPERS_H diff --git a/src/platformsupport/jniconvenience/qjniobject.cpp b/src/platformsupport/jniconvenience/qjniobject.cpp new file mode 100644 index 0000000000..515e82b2f0 --- /dev/null +++ b/src/platformsupport/jniconvenience/qjniobject.cpp @@ -0,0 +1,3098 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part 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 "qjniobject_p.h" + +#include "qjnihelpers_p.h" +#include <qhash.h> + +QT_BEGIN_NAMESPACE + +static QHash<QString, jclass> g_cachedClasses; + +static jclass getCachedClass(JNIEnv *env, const char *className) +{ + jclass clazz = 0; + QString key = QLatin1String(className); + QHash<QString, jclass>::iterator it = g_cachedClasses.find(key); + if (it == g_cachedClasses.end()) { + jclass c = env->FindClass(className); + if (env->ExceptionCheck()) { + c = 0; + env->ExceptionClear(); + } + if (c) + clazz = static_cast<jclass>(env->NewGlobalRef(c)); + g_cachedClasses.insert(key, clazz); + } else { + clazz = it.value(); + } + return clazz; +} + +static QHash<QString, jmethodID> g_cachedMethodIDs; +static QString g_keyBase(QLatin1String("%1%2%3")); + +static jmethodID getCachedMethodID(JNIEnv *env, + jclass clazz, + const char *name, + const char *sig, + bool isStatic = false) +{ + jmethodID id = 0; + QString key = g_keyBase.arg(size_t(clazz)).arg(QLatin1String(name)).arg(QLatin1String(sig)); + QHash<QString, jmethodID>::iterator it = g_cachedMethodIDs.find(key); + if (it == g_cachedMethodIDs.end()) { + if (isStatic) + id = env->GetStaticMethodID(clazz, name, sig); + else + id = env->GetMethodID(clazz, name, sig); + + if (env->ExceptionCheck()) { + id = 0; + env->ExceptionClear(); + } + + g_cachedMethodIDs.insert(key, id); + } else { + id = it.value(); + } + return id; +} + +static QHash<QString, jfieldID> g_cachedFieldIDs; + +static jfieldID getCachedFieldID(JNIEnv *env, + jclass clazz, + const char *name, + const char *sig, + bool isStatic = false) +{ + jfieldID id = 0; + QString key = g_keyBase.arg(size_t(clazz)).arg(QLatin1String(name)).arg(QLatin1String(sig)); + QHash<QString, jfieldID>::iterator it = g_cachedFieldIDs.find(key); + if (it == g_cachedFieldIDs.end()) { + if (isStatic) + id = env->GetStaticFieldID(clazz, name, sig); + else + id = env->GetFieldID(clazz, name, sig); + + if (env->ExceptionCheck()) { + id = 0; + env->ExceptionClear(); + } + + g_cachedFieldIDs.insert(key, id); + } else { + id = it.value(); + } + return id; +} + +QJNIObject::QJNIObject(const char *className) + : m_jobject(0) + , m_jclass(0) + , m_own_jclass(false) +{ + QAttachedJNIEnv env; + m_jclass = getCachedClass(env, className); + if (m_jclass) { + // get default constructor + jmethodID constructorId = getCachedMethodID(env, m_jclass, "<init>", "()V"); + if (constructorId) { + jobject obj = env->NewObject(m_jclass, constructorId); + if (obj) { + m_jobject = env->NewGlobalRef(obj); + env->DeleteLocalRef(obj); + } + } + } +} + +QJNIObject::QJNIObject(const char *className, const char *sig, ...) + : m_jobject(0) + , m_jclass(0) + , m_own_jclass(false) +{ + QAttachedJNIEnv env; + m_jclass = getCachedClass(env, className); + if (m_jclass) { + jmethodID constructorId = getCachedMethodID(env, m_jclass, "<init>", sig); + if (constructorId) { + va_list args; + va_start(args, sig); + jobject obj = env->NewObjectV(m_jclass, constructorId, args); + va_end(args); + if (obj) { + m_jobject = env->NewGlobalRef(obj); + env->DeleteLocalRef(obj); + } + } + } +} + +QJNIObject::QJNIObject(jclass clazz) + : m_jobject(0) + , m_jclass(0) + , m_own_jclass(true) +{ + QAttachedJNIEnv env; + m_jclass = static_cast<jclass>(env->NewGlobalRef(clazz)); + if (m_jclass) { + // get default constructor + jmethodID constructorId = getCachedMethodID(env, m_jclass, "<init>", "()V"); + if (constructorId) { + jobject obj = env->NewObject(m_jclass, constructorId); + if (obj) { + m_jobject = env->NewGlobalRef(obj); + env->DeleteLocalRef(obj); + } + } + } +} + +QJNIObject::QJNIObject(jclass clazz, const char *sig, ...) + : m_jobject(0) + , m_jclass(0) + , m_own_jclass(true) +{ + QAttachedJNIEnv env; + if (clazz) { + m_jclass = static_cast<jclass>(env->NewGlobalRef(clazz)); + if (m_jclass) { + jmethodID constructorId = getCachedMethodID(env, m_jclass, "<init>", sig); + if (constructorId) { + va_list args; + va_start(args, sig); + jobject obj = env->NewObjectV(m_jclass, constructorId, args); + va_end(args); + if (obj) { + m_jobject = env->NewGlobalRef(obj); + env->DeleteLocalRef(obj); + } + } + } + } +} + +QJNIObject::QJNIObject(jobject obj) + : m_jobject(0) + , m_jclass(0) + , m_own_jclass(true) +{ + QAttachedJNIEnv env; + m_jobject = env->NewGlobalRef(obj); + m_jclass = static_cast<jclass>(env->NewGlobalRef(env->GetObjectClass(m_jobject))); +} + +QJNIObject::~QJNIObject() +{ + QAttachedJNIEnv env; + if (m_jobject) + env->DeleteGlobalRef(m_jobject); + if (m_jclass && m_own_jclass) + env->DeleteGlobalRef(m_jclass); +} + +bool QJNIObject::isClassAvailable(const char *className) +{ + QAttachedJNIEnv env; + + if (!env.jniEnv) + return false; + + jclass clazz = getCachedClass(env, className); + + return (clazz != 0); +} + +template <> +void QJNIObject::callMethod<void>(const char *methodName, const char *sig, ...) +{ + QAttachedJNIEnv env; + jmethodID id = getCachedMethodID(env, m_jclass, methodName, sig); + if (id) { + va_list args; + va_start(args, sig); + env->CallVoidMethodV(m_jobject, id, args); + va_end(args); + } +} + +template <> +jboolean QJNIObject::callMethod<jboolean>(const char *methodName, const char *sig, ...) +{ + QAttachedJNIEnv env; + jboolean res = 0; + jmethodID id = getCachedMethodID(env, m_jclass, methodName, sig); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallBooleanMethodV(m_jobject, id, args); + va_end(args); + } + return res; +} + +template <> +jbyte QJNIObject::callMethod<jbyte>(const char *methodName, const char *sig, ...) +{ + QAttachedJNIEnv env; + jbyte res = 0; + jmethodID id = getCachedMethodID(env, m_jclass, methodName, sig); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallByteMethodV(m_jobject, id, args); + va_end(args); + } + return res; +} + +template <> +jchar QJNIObject::callMethod<jchar>(const char *methodName, const char *sig, ...) +{ + QAttachedJNIEnv env; + jchar res = 0; + jmethodID id = getCachedMethodID(env, m_jclass, methodName, sig); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallCharMethodV(m_jobject, id, args); + va_end(args); + } + return res; +} + +template <> +jshort QJNIObject::callMethod<jshort>(const char *methodName, const char *sig, ...) +{ + QAttachedJNIEnv env; + jshort res = 0; + jmethodID id = getCachedMethodID(env, m_jclass, methodName, sig); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallShortMethodV(m_jobject, id, args); + va_end(args); + } + return res; +} + +template <> +jint QJNIObject::callMethod<jint>(const char *methodName, const char *sig, ...) +{ + QAttachedJNIEnv env; + jint res = 0; + jmethodID id = getCachedMethodID(env, m_jclass, methodName, sig); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallIntMethodV(m_jobject, id, args); + va_end(args); + } + return res; +} + +template <> +jlong QJNIObject::callMethod<jlong>(const char *methodName, const char *sig, ...) +{ + QAttachedJNIEnv env; + jlong res = 0; + jmethodID id = getCachedMethodID(env, m_jclass, methodName, sig); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallLongMethodV(m_jobject, id, args); + va_end(args); + } + return res; +} + +template <> +jfloat QJNIObject::callMethod<jfloat>(const char *methodName, const char *sig, ...) +{ + QAttachedJNIEnv env; + jfloat res = 0.f; + jmethodID id = getCachedMethodID(env, m_jclass, methodName, sig); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallFloatMethodV(m_jobject, id, args); + va_end(args); + } + return res; +} + +template <> +jdouble QJNIObject::callMethod<jdouble>(const char *methodName, const char *sig, ...) +{ + QAttachedJNIEnv env; + jdouble res = 0.; + jmethodID id = getCachedMethodID(env, m_jclass, methodName, sig); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallDoubleMethodV(m_jobject, id, args); + va_end(args); + } + return res; +} + +template <> +QJNILocalRef<jobject> QJNIObject::callObjectMethod<jobject>(const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + jobject res = 0; + jmethodID id = getCachedMethodID(env, m_jclass, methodName, sig); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallObjectMethodV(m_jobject, id, args); + va_end(args); + } + return QJNILocalRef<jobject>(res); +} + +template <> +QJNILocalRef<jstring> QJNIObject::callObjectMethod<jstring>(const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + jstring res = 0; + jmethodID id = getCachedMethodID(env, m_jclass, methodName, sig); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jstring>(env->CallObjectMethodV(m_jobject, id, args)); + va_end(args); + } + return QJNILocalRef<jstring>(res); +} + +template <> +QJNILocalRef<jobjectArray> QJNIObject::callObjectMethod<jobjectArray>(const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + jobjectArray res = 0; + jmethodID id = getCachedMethodID(env, m_jclass, methodName, sig); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jobjectArray>(env->CallObjectMethodV(m_jobject, id, args)); + va_end(args); + } + return QJNILocalRef<jobjectArray>(res); +} + +template <> +QJNILocalRef<jbooleanArray> QJNIObject::callObjectMethod<jbooleanArray>(const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + jbooleanArray res = 0; + jmethodID id = getCachedMethodID(env, m_jclass, methodName, sig); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jbooleanArray>(env->CallObjectMethodV(m_jobject, id, args)); + va_end(args); + } + return QJNILocalRef<jbooleanArray>(res); +} + +template <> +QJNILocalRef<jbyteArray> QJNIObject::callObjectMethod<jbyteArray>(const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + jbyteArray res = 0; + jmethodID id = getCachedMethodID(env, m_jclass, methodName, sig); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jbyteArray>(env->CallObjectMethodV(m_jobject, id, args)); + va_end(args); + } + return QJNILocalRef<jbyteArray>(res); +} + +template <> +QJNILocalRef<jcharArray> QJNIObject::callObjectMethod<jcharArray>(const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + jcharArray res = 0; + jmethodID id = getCachedMethodID(env, m_jclass, methodName, sig); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jcharArray>(env->CallObjectMethodV(m_jobject, id, args)); + va_end(args); + } + return QJNILocalRef<jcharArray>(res); +} + +template <> +QJNILocalRef<jshortArray> QJNIObject::callObjectMethod<jshortArray>(const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + jshortArray res = 0; + jmethodID id = getCachedMethodID(env, m_jclass, methodName, sig); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jshortArray>(env->CallObjectMethodV(m_jobject, id, args)); + va_end(args); + } + return QJNILocalRef<jshortArray>(res); +} + +template <> +QJNILocalRef<jintArray> QJNIObject::callObjectMethod<jintArray>(const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + jintArray res = 0; + jmethodID id = getCachedMethodID(env, m_jclass, methodName, sig); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jintArray>(env->CallObjectMethodV(m_jobject, id, args)); + va_end(args); + } + return QJNILocalRef<jintArray>(res); +} + +template <> +QJNILocalRef<jlongArray> QJNIObject::callObjectMethod<jlongArray>(const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + jlongArray res = 0; + jmethodID id = getCachedMethodID(env, m_jclass, methodName, sig); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jlongArray>(env->CallObjectMethodV(m_jobject, id, args)); + va_end(args); + } + return QJNILocalRef<jlongArray>(res); +} + +template <> +QJNILocalRef<jfloatArray> QJNIObject::callObjectMethod<jfloatArray>(const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + jfloatArray res = 0; + jmethodID id = getCachedMethodID(env, m_jclass, methodName, sig); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jfloatArray>(env->CallObjectMethodV(m_jobject, id, args)); + va_end(args); + } + return QJNILocalRef<jfloatArray>(res); +} + +template <> +QJNILocalRef<jdoubleArray> QJNIObject::callObjectMethod<jdoubleArray>(const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + jdoubleArray res = 0; + jmethodID id = getCachedMethodID(env, m_jclass, methodName, sig); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jdoubleArray>(env->CallObjectMethodV(m_jobject, id, args)); + va_end(args); + } + return QJNILocalRef<jdoubleArray>(res); +} + +template <> +void QJNIObject::callMethod<void>(const char *methodName) +{ + callMethod<void>(methodName, "()V"); +} + +template <> +jboolean QJNIObject::callMethod<jboolean>(const char *methodName) +{ + return callMethod<jboolean>(methodName, "()Z"); +} + +template <> +jbyte QJNIObject::callMethod<jbyte>(const char *methodName) +{ + return callMethod<jbyte>(methodName, "()B"); +} + +template <> +jchar QJNIObject::callMethod<jchar>(const char *methodName) +{ + return callMethod<jchar>(methodName, "()C"); +} + +template <> +jshort QJNIObject::callMethod<jshort>(const char *methodName) +{ + return callMethod<jshort>(methodName, "()S"); +} + +template <> +jint QJNIObject::callMethod<jint>(const char *methodName) +{ + return callMethod<jint>(methodName, "()I"); +} + +template <> +jlong QJNIObject::callMethod<jlong>(const char *methodName) +{ + return callMethod<jlong>(methodName, "()J"); +} + +template <> +jfloat QJNIObject::callMethod<jfloat>(const char *methodName) +{ + return callMethod<jfloat>(methodName, "()F"); +} + +template <> +jdouble QJNIObject::callMethod<jdouble>(const char *methodName) +{ + return callMethod<jdouble>(methodName, "()D"); +} + +template <> +QJNILocalRef<jstring> QJNIObject::callObjectMethod<jstring>(const char *methodName) +{ + return callObjectMethod<jstring>(methodName, "()Ljava/lang/String;"); +} + +template <> +QJNILocalRef<jbooleanArray> QJNIObject::callObjectMethod<jbooleanArray>(const char *methodName) +{ + return callObjectMethod<jbooleanArray>(methodName, "()[Z"); +} + +template <> +QJNILocalRef<jbyteArray> QJNIObject::callObjectMethod<jbyteArray>(const char *methodName) +{ + return callObjectMethod<jbyteArray>(methodName, "()[B"); +} + +template <> +QJNILocalRef<jshortArray> QJNIObject::callObjectMethod<jshortArray>(const char *methodName) +{ + return callObjectMethod<jshortArray>(methodName, "()[S"); +} + +template <> +QJNILocalRef<jintArray> QJNIObject::callObjectMethod<jintArray>(const char *methodName) +{ + return callObjectMethod<jintArray>(methodName, "()[I"); +} + +template <> +QJNILocalRef<jlongArray> QJNIObject::callObjectMethod<jlongArray>(const char *methodName) +{ + return callObjectMethod<jlongArray>(methodName, "()[J"); +} + +template <> +QJNILocalRef<jfloatArray> QJNIObject::callObjectMethod<jfloatArray>(const char *methodName) +{ + return callObjectMethod<jfloatArray>(methodName, "()[F"); +} + +template <> +QJNILocalRef<jdoubleArray> QJNIObject::callObjectMethod<jdoubleArray>(const char *methodName) +{ + return callObjectMethod<jdoubleArray>(methodName, "()[D"); +} + +template <> +void QJNIObject::callStaticMethod<void>(const char *className, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + jclass clazz = getCachedClass(env, className); + if (clazz) { + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + env->CallStaticVoidMethodV(clazz, id, args); + va_end(args); + } + } +} + +template <> +void QJNIObject::callStaticMethod<void>(jclass clazz, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + env->CallStaticVoidMethodV(clazz, id, args); + va_end(args); + } +} + +template <> +jboolean QJNIObject::callStaticMethod<jboolean>(const char *className, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jboolean res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) { + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallStaticBooleanMethodV(clazz, id, args); + va_end(args); + } + } + + return res; +} + +template <> +jboolean QJNIObject::callStaticMethod<jboolean>(jclass clazz, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jboolean res = 0; + + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallStaticBooleanMethodV(clazz, id, args); + va_end(args); + } + + return res; +} + +template <> +jbyte QJNIObject::callStaticMethod<jbyte>(const char *className, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jbyte res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) { + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallStaticByteMethodV(clazz, id, args); + va_end(args); + } + } + + return res; +} + +template <> +jbyte QJNIObject::callStaticMethod<jbyte>(jclass clazz, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jbyte res = 0; + + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallStaticByteMethodV(clazz, id, args); + va_end(args); + } + + return res; +} + +template <> +jchar QJNIObject::callStaticMethod<jchar>(const char *className, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jchar res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) { + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallStaticCharMethodV(clazz, id, args); + va_end(args); + } + } + + return res; +} + +template <> +jchar QJNIObject::callStaticMethod<jchar>(jclass clazz, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jchar res = 0; + + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallStaticCharMethodV(clazz, id, args); + va_end(args); + } + + return res; +} + + +template <> +jshort QJNIObject::callStaticMethod<jshort>(const char *className, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jshort res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) { + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallStaticShortMethodV(clazz, id, args); + va_end(args); + } + } + + return res; +} + +template <> +jshort QJNIObject::callStaticMethod<jshort>(jclass clazz, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jshort res = 0; + + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallStaticShortMethodV(clazz, id, args); + va_end(args); + } + + return res; +} + +template <> +jint QJNIObject::callStaticMethod<jint>(const char *className, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jint res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) { + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallStaticIntMethodV(clazz, id, args); + va_end(args); + } + } + + return res; +} + +template <> +jint QJNIObject::callStaticMethod<jint>(jclass clazz, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jint res = 0; + + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallStaticIntMethodV(clazz, id, args); + va_end(args); + } + + return res; +} + +template <> +jlong QJNIObject::callStaticMethod<jlong>(const char *className, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jlong res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) { + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallStaticLongMethodV(clazz, id, args); + va_end(args); + } + } + + return res; +} + +template <> +jlong QJNIObject::callStaticMethod<jlong>(jclass clazz, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jlong res = 0; + + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallStaticLongMethodV(clazz, id, args); + va_end(args); + } + + return res; +} + +template <> +jfloat QJNIObject::callStaticMethod<jfloat>(const char *className, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jfloat res = 0.f; + + jclass clazz = getCachedClass(env, className); + if (clazz) { + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallStaticFloatMethodV(clazz, id, args); + va_end(args); + } + } + + return res; +} + +template <> +jfloat QJNIObject::callStaticMethod<jfloat>(jclass clazz, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jfloat res = 0.f; + + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallStaticFloatMethodV(clazz, id, args); + va_end(args); + } + + return res; +} + +template <> +jdouble QJNIObject::callStaticMethod<jdouble>(const char *className, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jdouble res = 0.; + + jclass clazz = getCachedClass(env, className); + if (clazz) { + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallStaticDoubleMethodV(clazz, id, args); + va_end(args); + } + } + + return res; +} + +template <> +jdouble QJNIObject::callStaticMethod<jdouble>(jclass clazz, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jdouble res = 0.; + + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallStaticDoubleMethodV(clazz, id, args); + va_end(args); + } + + return res; +} + +template <> +QJNILocalRef<jobject> QJNIObject::callStaticObjectMethod<jobject>(const char *className, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jobject res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) { + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallStaticObjectMethodV(clazz, id, args); + va_end(args); + } + } + + return QJNILocalRef<jobject>(res); +} + +template <> +QJNILocalRef<jobject> QJNIObject::callStaticObjectMethod<jobject>(jclass clazz, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jobject res = 0; + + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = env->CallStaticObjectMethodV(clazz, id, args); + va_end(args); + } + + return QJNILocalRef<jobject>(res); +} + +template <> +QJNILocalRef<jstring> QJNIObject::callStaticObjectMethod<jstring>(const char *className, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jstring res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) { + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jstring>(env->CallStaticObjectMethodV(clazz, id, args)); + va_end(args); + } + } + + return QJNILocalRef<jstring>(res); +} + +template <> +QJNILocalRef<jstring> QJNIObject::callStaticObjectMethod<jstring>(jclass clazz, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jstring res = 0; + + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jstring>(env->CallStaticObjectMethodV(clazz, id, args)); + va_end(args); + } + + return QJNILocalRef<jstring>(res); +} + +template <> +QJNILocalRef<jobjectArray> QJNIObject::callStaticObjectMethod<jobjectArray>(const char *className, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jobjectArray res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) { + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jobjectArray>(env->CallStaticObjectMethodV(clazz, id, args)); + va_end(args); + } + } + + return QJNILocalRef<jobjectArray>(res); +} + +template <> +QJNILocalRef<jobjectArray> QJNIObject::callStaticObjectMethod<jobjectArray>(jclass clazz, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jobjectArray res = 0; + + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jobjectArray>(env->CallStaticObjectMethodV(clazz, id, args)); + va_end(args); + } + + return QJNILocalRef<jobjectArray>(res); +} + +template <> +QJNILocalRef<jbooleanArray> QJNIObject::callStaticObjectMethod<jbooleanArray>(const char *className, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jbooleanArray res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) { + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jbooleanArray>(env->CallStaticObjectMethodV(clazz, id, args)); + va_end(args); + } + } + + return QJNILocalRef<jbooleanArray>(res); +} + +template <> +QJNILocalRef<jbooleanArray> QJNIObject::callStaticObjectMethod<jbooleanArray>(jclass clazz, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jbooleanArray res = 0; + + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jbooleanArray>(env->CallStaticObjectMethodV(clazz, id, args)); + va_end(args); + } + + return QJNILocalRef<jbooleanArray>(res); +} + +template <> +QJNILocalRef<jbyteArray> QJNIObject::callStaticObjectMethod<jbyteArray>(const char *className, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jbyteArray res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) { + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jbyteArray>(env->CallStaticObjectMethodV(clazz, id, args)); + va_end(args); + } + } + + return QJNILocalRef<jbyteArray>(res); +} + +template <> +QJNILocalRef<jbyteArray> QJNIObject::callStaticObjectMethod<jbyteArray>(jclass clazz, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jbyteArray res = 0; + + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jbyteArray>(env->CallStaticObjectMethodV(clazz, id, args)); + va_end(args); + } + + return QJNILocalRef<jbyteArray>(res); +} + +template <> +QJNILocalRef<jcharArray> QJNIObject::callStaticObjectMethod<jcharArray>(const char *className, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jcharArray res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) { + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jcharArray>(env->CallStaticObjectMethodV(clazz, id, args)); + va_end(args); + } + } + + return QJNILocalRef<jcharArray>(res); +} + +template <> +QJNILocalRef<jcharArray> QJNIObject::callStaticObjectMethod<jcharArray>(jclass clazz, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jcharArray res = 0; + + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jcharArray>(env->CallStaticObjectMethodV(clazz, id, args)); + va_end(args); + } + + return QJNILocalRef<jcharArray>(res); +} + +template <> +QJNILocalRef<jshortArray> QJNIObject::callStaticObjectMethod<jshortArray>(const char *className, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jshortArray res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) { + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jshortArray>(env->CallStaticObjectMethodV(clazz, id, args)); + va_end(args); + } + } + + return QJNILocalRef<jshortArray>(res); +} + +template <> +QJNILocalRef<jshortArray> QJNIObject::callStaticObjectMethod<jshortArray>(jclass clazz, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jshortArray res = 0; + + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jshortArray>(env->CallStaticObjectMethodV(clazz, id, args)); + va_end(args); + } + + return QJNILocalRef<jshortArray>(res); +} + +template <> +QJNILocalRef<jintArray> QJNIObject::callStaticObjectMethod<jintArray>(const char *className, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jintArray res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) { + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jintArray>(env->CallStaticObjectMethodV(clazz, id, args)); + va_end(args); + } + } + + return QJNILocalRef<jintArray>(res); +} + +template <> +QJNILocalRef<jintArray> QJNIObject::callStaticObjectMethod<jintArray>(jclass clazz, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jintArray res = 0; + + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jintArray>(env->CallStaticObjectMethodV(clazz, id, args)); + va_end(args); + } + + return QJNILocalRef<jintArray>(res); +} + +template <> +QJNILocalRef<jlongArray> QJNIObject::callStaticObjectMethod<jlongArray>(const char *className, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jlongArray res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) { + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jlongArray>(env->CallStaticObjectMethodV(clazz, id, args)); + va_end(args); + } + } + + return QJNILocalRef<jlongArray>(res); +} + +template <> +QJNILocalRef<jlongArray> QJNIObject::callStaticObjectMethod<jlongArray>(jclass clazz, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jlongArray res = 0; + + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jlongArray>(env->CallStaticObjectMethodV(clazz, id, args)); + va_end(args); + } + + return QJNILocalRef<jlongArray>(res); +} + +template <> +QJNILocalRef<jfloatArray> QJNIObject::callStaticObjectMethod<jfloatArray>(const char *className, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jfloatArray res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) { + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jfloatArray>(env->CallStaticObjectMethodV(clazz, id, args)); + va_end(args); + } + } + + return QJNILocalRef<jfloatArray>(res); +} + +template <> +QJNILocalRef<jfloatArray> QJNIObject::callStaticObjectMethod<jfloatArray>(jclass clazz, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jfloatArray res = 0; + + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jfloatArray>(env->CallStaticObjectMethodV(clazz, id, args)); + va_end(args); + } + + return QJNILocalRef<jfloatArray>(res); +} + +template <> +QJNILocalRef<jdoubleArray> QJNIObject::callStaticObjectMethod<jdoubleArray>(const char *className, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jdoubleArray res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) { + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jdoubleArray>(env->CallStaticObjectMethodV(clazz, id, args)); + va_end(args); + } + } + + return QJNILocalRef<jdoubleArray>(res); +} + +template <> +QJNILocalRef<jdoubleArray> QJNIObject::callStaticObjectMethod<jdoubleArray>(jclass clazz, + const char *methodName, + const char *sig, + ...) +{ + QAttachedJNIEnv env; + + jdoubleArray res = 0; + + jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + if (id) { + va_list args; + va_start(args, sig); + res = static_cast<jdoubleArray>(env->CallStaticObjectMethodV(clazz, id, args)); + va_end(args); + } + + return QJNILocalRef<jdoubleArray>(res); +} + +template <> +void QJNIObject::callStaticMethod<void>(const char *className, const char *methodName) +{ + callStaticMethod<void>(className, methodName, "()V"); +} + +template <> +void QJNIObject::callStaticMethod<void>(jclass clazz, const char *methodName) +{ + callStaticMethod<void>(clazz, methodName, "()V"); +} + +template <> +jboolean QJNIObject::callStaticMethod<jboolean>(const char *className, const char *methodName) +{ + return callStaticMethod<jboolean>(className, methodName, "()Z"); +} + +template <> +jboolean QJNIObject::callStaticMethod<jboolean>(jclass clazz, const char *methodName) +{ + return callStaticMethod<jboolean>(clazz, methodName, "()Z"); +} + +template <> +jbyte QJNIObject::callStaticMethod<jbyte>(const char *className, const char *methodName) +{ + return callStaticMethod<jbyte>(className, methodName, "()B"); +} + +template <> +jbyte QJNIObject::callStaticMethod<jbyte>(jclass clazz, const char *methodName) +{ + return callStaticMethod<jbyte>(clazz, methodName, "()B"); +} + +template <> +jchar QJNIObject::callStaticMethod<jchar>(const char *className, const char *methodName) +{ + return callStaticMethod<jchar>(className, methodName, "()C"); +} + +template <> +jchar QJNIObject::callStaticMethod<jchar>(jclass clazz, const char *methodName) +{ + return callStaticMethod<jchar>(clazz, methodName, "()C"); +} + +template <> +jshort QJNIObject::callStaticMethod<jshort>(const char *className, const char *methodName) +{ + return callStaticMethod<jshort>(className, methodName, "()S"); +} + +template <> +jshort QJNIObject::callStaticMethod<jshort>(jclass clazz, const char *methodName) +{ + return callStaticMethod<jshort>(clazz, methodName, "()S"); +} + +template <> +jint QJNIObject::callStaticMethod<jint>(const char *className, const char *methodName) +{ + return callStaticMethod<jint>(className, methodName, "()I"); +} + +template <> +jint QJNIObject::callStaticMethod<jint>(jclass clazz, const char *methodName) +{ + return callStaticMethod<jint>(clazz, methodName, "()I"); +} + +template <> +jlong QJNIObject::callStaticMethod<jlong>(const char *className, const char *methodName) +{ + return callStaticMethod<jlong>(className, methodName, "()J"); +} + +template <> +jlong QJNIObject::callStaticMethod<jlong>(jclass clazz, const char *methodName) +{ + return callStaticMethod<jlong>(clazz, methodName, "()J"); +} + +template <> +jfloat QJNIObject::callStaticMethod<jfloat>(const char *className, const char *methodName) +{ + return callStaticMethod<jfloat>(className, methodName, "()F"); +} + +template <> +jfloat QJNIObject::callStaticMethod<jfloat>(jclass clazz, const char *methodName) +{ + return callStaticMethod<jfloat>(clazz, methodName, "()F"); +} + +template <> +jdouble QJNIObject::callStaticMethod<jdouble>(const char *className, const char *methodName) +{ + return callStaticMethod<jdouble>(className, methodName, "()D"); +} + +template <> +jdouble QJNIObject::callStaticMethod<jdouble>(jclass clazz, const char *methodName) +{ + return callStaticMethod<jdouble>(clazz, methodName, "()D"); +} + +template <> +QJNILocalRef<jstring> QJNIObject::callStaticObjectMethod<jstring>(const char *className, + const char *methodName) +{ + return callStaticObjectMethod<jstring>(className, methodName, "()Ljava/lang/String;"); +} + +template <> +QJNILocalRef<jstring> QJNIObject::callStaticObjectMethod<jstring>(jclass clazz, + const char *methodName) +{ + return callStaticObjectMethod<jstring>(clazz, methodName, "()Ljava/lang/String;"); +} + +template <> +QJNILocalRef<jbooleanArray> QJNIObject::callStaticObjectMethod<jbooleanArray>(const char *className, + const char *methodName) +{ + return callStaticObjectMethod<jbooleanArray>(className, methodName, "()[Z"); +} + +template <> +QJNILocalRef<jbooleanArray> QJNIObject::callStaticObjectMethod<jbooleanArray>(jclass clazz, + const char *methodName) +{ + return callStaticObjectMethod<jbooleanArray>(clazz, methodName, "()[Z"); +} + +template <> +QJNILocalRef<jbyteArray> QJNIObject::callStaticObjectMethod<jbyteArray>(const char *className, + const char *methodName) +{ + return callStaticObjectMethod<jbyteArray>(className, methodName, "()[B"); +} + +template <> +QJNILocalRef<jbyteArray> QJNIObject::callStaticObjectMethod<jbyteArray>(jclass clazz, + const char *methodName) +{ + return callStaticObjectMethod<jbyteArray>(clazz, methodName, "()[B"); +} + +template <> +QJNILocalRef<jcharArray> QJNIObject::callStaticObjectMethod<jcharArray>(const char *className, + const char *methodName) +{ + return callStaticObjectMethod<jcharArray>(className, methodName, "()[C"); +} + +template <> +QJNILocalRef<jcharArray> QJNIObject::callStaticObjectMethod<jcharArray>(jclass clazz, + const char *methodName) +{ + return callStaticObjectMethod<jcharArray>(clazz, methodName, "()[C"); +} + +template <> +QJNILocalRef<jshortArray> QJNIObject::callStaticObjectMethod<jshortArray>(const char *className, + const char *methodName) +{ + return callStaticObjectMethod<jshortArray>(className, methodName, "()[S"); +} + +template <> +QJNILocalRef<jshortArray> QJNIObject::callStaticObjectMethod<jshortArray>(jclass clazz, + const char *methodName) +{ + return callStaticObjectMethod<jshortArray>(clazz, methodName, "()[S"); +} + +template <> +QJNILocalRef<jintArray> QJNIObject::callStaticObjectMethod<jintArray>(const char *className, + const char *methodName) +{ + return callStaticObjectMethod<jintArray>(className, methodName, "()[I"); +} + +template <> +QJNILocalRef<jintArray> QJNIObject::callStaticObjectMethod<jintArray>(jclass clazz, + const char *methodName) +{ + return callStaticObjectMethod<jintArray>(clazz, methodName, "()[I"); +} + +template <> +QJNILocalRef<jlongArray> QJNIObject::callStaticObjectMethod<jlongArray>(const char *className, + const char *methodName) +{ + return callStaticObjectMethod<jlongArray>(className, methodName, "()[J"); +} + +template <> +QJNILocalRef<jlongArray> QJNIObject::callStaticObjectMethod<jlongArray>(jclass clazz, + const char *methodName) +{ + return callStaticObjectMethod<jlongArray>(clazz, methodName, "()[J"); +} + +template <> +QJNILocalRef<jfloatArray> QJNIObject::callStaticObjectMethod<jfloatArray>(const char *className, + const char *methodName) +{ + return callStaticObjectMethod<jfloatArray>(className, methodName, "()[F"); +} + +template <> +QJNILocalRef<jfloatArray> QJNIObject::callStaticObjectMethod<jfloatArray>(jclass clazz, + const char *methodName) +{ + return callStaticObjectMethod<jfloatArray>(clazz, methodName, "()[F"); +} + +template <> +QJNILocalRef<jdoubleArray> QJNIObject::callStaticObjectMethod<jdoubleArray>(const char *className, + const char *methodName) +{ + return callStaticObjectMethod<jdoubleArray>(className, methodName, "()[D"); +} + +template <> +QJNILocalRef<jdoubleArray> QJNIObject::callStaticObjectMethod<jdoubleArray>(jclass clazz, + const char *methodName) +{ + return callStaticObjectMethod<jdoubleArray>(clazz, methodName, "()[D"); +} + +template <> +jboolean QJNIObject::getField<jboolean>(const char *fieldName) +{ + QAttachedJNIEnv env; + jboolean res = 0; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "Z"); + if (id) + res = env->GetBooleanField(m_jobject, id); + + return res; +} + +template <> +jbyte QJNIObject::getField<jbyte>(const char *fieldName) +{ + QAttachedJNIEnv env; + jbyte res = 0; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "B"); + if (id) + res = env->GetByteField(m_jobject, id); + + return res; +} + +template <> +jchar QJNIObject::getField<jchar>(const char *fieldName) +{ + QAttachedJNIEnv env; + jchar res = 0; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "C"); + if (id) + res = env->GetCharField(m_jobject, id); + + return res; +} + +template <> +jshort QJNIObject::getField<jshort>(const char *fieldName) +{ + QAttachedJNIEnv env; + jshort res = 0; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "S"); + if (id) + res = env->GetShortField(m_jobject, id); + + return res; +} + +template <> +jint QJNIObject::getField<jint>(const char *fieldName) +{ + QAttachedJNIEnv env; + jint res = 0; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "I"); + if (id) + res = env->GetIntField(m_jobject, id); + + return res; +} + +template <> +jlong QJNIObject::getField<jlong>(const char *fieldName) +{ + QAttachedJNIEnv env; + jlong res = 0; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "J"); + if (id) + res = env->GetLongField(m_jobject, id); + + return res; +} + +template <> +jfloat QJNIObject::getField<jfloat>(const char *fieldName) +{ + QAttachedJNIEnv env; + jfloat res = 0.f; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "F"); + if (id) + res = env->GetFloatField(m_jobject, id); + + return res; +} + +template <> +jdouble QJNIObject::getField<jdouble>(const char *fieldName) +{ + QAttachedJNIEnv env; + jdouble res = 0.; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "D"); + if (id) + res = env->GetDoubleField(m_jobject, id); + + return res; +} + +template <> +QJNILocalRef<jobject> QJNIObject::getObjectField<jobject>(const char *fieldName, const char *sig) +{ + QAttachedJNIEnv env; + jobject res = 0; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, sig); + if (id) + res = env->GetObjectField(m_jobject, id); + + return QJNILocalRef<jobject>(res); +} + +template <> +QJNILocalRef<jbooleanArray> QJNIObject::getObjectField<jbooleanArray>(const char *fieldName) +{ + QAttachedJNIEnv env; + jbooleanArray res = 0; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "[Z"); + if (id) + res = static_cast<jbooleanArray>(env->GetObjectField(m_jobject, id)); + + return QJNILocalRef<jbooleanArray>(res); +} + +template <> +QJNILocalRef<jbyteArray> QJNIObject::getObjectField<jbyteArray>(const char *fieldName) +{ + QAttachedJNIEnv env; + jbyteArray res = 0; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "[B"); + if (id) + res = static_cast<jbyteArray>(env->GetObjectField(m_jobject, id)); + + return QJNILocalRef<jbyteArray>(res); +} + +template <> +QJNILocalRef<jcharArray> QJNIObject::getObjectField<jcharArray>(const char *fieldName) +{ + QAttachedJNIEnv env; + jcharArray res = 0; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "[C"); + if (id) + res = static_cast<jcharArray>(env->GetObjectField(m_jobject, id)); + + return QJNILocalRef<jcharArray>(res); +} + +template <> +QJNILocalRef<jshortArray> QJNIObject::getObjectField<jshortArray>(const char *fieldName) +{ + QAttachedJNIEnv env; + jshortArray res = 0; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "[S"); + if (id) + res = static_cast<jshortArray>(env->GetObjectField(m_jobject, id)); + + return QJNILocalRef<jshortArray>(res); +} + +template <> +QJNILocalRef<jintArray> QJNIObject::getObjectField<jintArray>(const char *fieldName) +{ + QAttachedJNIEnv env; + jintArray res = 0; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "[I"); + if (id) + res = static_cast<jintArray>(env->GetObjectField(m_jobject, id)); + + return QJNILocalRef<jintArray>(res); +} + +template <> +QJNILocalRef<jlongArray> QJNIObject::getObjectField<jlongArray>(const char *fieldName) +{ + QAttachedJNIEnv env; + jlongArray res = 0; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "[J"); + if (id) + res = static_cast<jlongArray>(env->GetObjectField(m_jobject, id)); + + return QJNILocalRef<jlongArray>(res); +} + +template <> +QJNILocalRef<jfloatArray> QJNIObject::getObjectField<jfloatArray>(const char *fieldName) +{ + QAttachedJNIEnv env; + jfloatArray res = 0; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "[F"); + if (id) + res = static_cast<jfloatArray>(env->GetObjectField(m_jobject, id)); + + return QJNILocalRef<jfloatArray>(res); +} + +template <> +QJNILocalRef<jdoubleArray> QJNIObject::getObjectField<jdoubleArray>(const char *fieldName) +{ + QAttachedJNIEnv env; + jdoubleArray res = 0; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "[D"); + if (id) + res = static_cast<jdoubleArray>(env->GetObjectField(m_jobject, id)); + + return QJNILocalRef<jdoubleArray>(res); +} + +template <> +QJNILocalRef<jstring> QJNIObject::getObjectField<jstring>(const char *fieldName) +{ + QAttachedJNIEnv env; + jstring res = 0; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "Ljava/lang/String;"); + if (id) + res = static_cast<jstring>(env->GetObjectField(m_jobject, id)); + + return QJNILocalRef<jstring>(res); +} + +template <> +QJNILocalRef<jobjectArray> QJNIObject::getObjectField<jobjectArray>(const char *fieldName, + const char *sig) +{ + QAttachedJNIEnv env; + jobjectArray res = 0; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, sig); + if (id) + res = static_cast<jobjectArray>(env->GetObjectField(m_jobject, id)); + + return QJNILocalRef<jobjectArray>(res); +} + +template <> +void QJNIObject::setField<jboolean>(const char *fieldName, jboolean value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "Z"); + if (id) + env->SetBooleanField(m_jobject, id, value); + +} + +template <> +void QJNIObject::setField<jbyte>(const char *fieldName, jbyte value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "B"); + if (id) + env->SetByteField(m_jobject, id, value); + +} + +template <> +void QJNIObject::setField<jchar>(const char *fieldName, jchar value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "C"); + if (id) + env->SetCharField(m_jobject, id, value); + +} + +template <> +void QJNIObject::setField<jshort>(const char *fieldName, jshort value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "S"); + if (id) + env->SetShortField(m_jobject, id, value); + +} + +template <> +void QJNIObject::setField<jint>(const char *fieldName, jint value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "I"); + if (id) + env->SetIntField(m_jobject, id, value); + +} + +template <> +void QJNIObject::setField<jlong>(const char *fieldName, jlong value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "J"); + if (id) + env->SetLongField(m_jobject, id, value); + +} + +template <> +void QJNIObject::setField<jfloat>(const char *fieldName, jfloat value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "F"); + if (id) + env->SetFloatField(m_jobject, id, value); + +} + +template <> +void QJNIObject::setField<jdouble>(const char *fieldName, jdouble value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "D"); + if (id) + env->SetDoubleField(m_jobject, id, value); + +} + +template <> +void QJNIObject::setField<jbooleanArray>(const char *fieldName, jbooleanArray value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "[Z"); + if (id) + env->SetObjectField(m_jobject, id, value); + +} + +template <> +void QJNIObject::setField<jbyteArray>(const char *fieldName, jbyteArray value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "[B"); + if (id) + env->SetObjectField(m_jobject, id, value); + +} + +template <> +void QJNIObject::setField<jcharArray>(const char *fieldName, jcharArray value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "[C"); + if (id) + env->SetObjectField(m_jobject, id, value); + +} + +template <> +void QJNIObject::setField<jshortArray>(const char *fieldName, jshortArray value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "[S"); + if (id) + env->SetObjectField(m_jobject, id, value); + +} + +template <> +void QJNIObject::setField<jintArray>(const char *fieldName, jintArray value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "[I"); + if (id) + env->SetObjectField(m_jobject, id, value); + +} + +template <> +void QJNIObject::setField<jlongArray>(const char *fieldName, jlongArray value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "[J"); + if (id) + env->SetObjectField(m_jobject, id, value); + +} + +template <> +void QJNIObject::setField<jfloatArray>(const char *fieldName, jfloatArray value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "[F"); + if (id) + env->SetObjectField(m_jobject, id, value); + +} + +template <> +void QJNIObject::setField<jdoubleArray>(const char *fieldName, jdoubleArray value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "[D"); + if (id) + env->SetObjectField(m_jobject, id, value); + +} + +template <> +void QJNIObject::setField<jstring>(const char *fieldName, jstring value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, "Ljava/lang/String;"); + if (id) + env->SetObjectField(m_jobject, id, value); + +} + +template <> +void QJNIObject::setField<jobject>(const char *fieldName, const char *sig, jobject value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, sig); + if (id) + env->SetObjectField(m_jobject, id, value); + +} + +template <> +void QJNIObject::setField<jobjectArray>(const char *fieldName, + const char *sig, + jobjectArray value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, m_jclass, fieldName, sig); + if (id) + env->SetObjectField(m_jobject, id, value); + +} + +template <> +jboolean QJNIObject::getStaticField<jboolean>(jclass clazz, const char *fieldName) +{ + QAttachedJNIEnv env; + + jboolean res = 0; + + jfieldID id = getCachedFieldID(env, clazz, fieldName, "Z", true); + if (id) + res = env->GetStaticBooleanField(clazz, id); + + return res; +} + +template <> +jboolean QJNIObject::getStaticField<jboolean>(const char *className, const char *fieldName) +{ + QAttachedJNIEnv env; + + jboolean res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) + res = getStaticField<jboolean>(clazz, fieldName); + + return res; +} + +template <> +jbyte QJNIObject::getStaticField<jbyte>(jclass clazz, const char *fieldName) +{ + QAttachedJNIEnv env; + + jbyte res = 0; + + jfieldID id = getCachedFieldID(env, clazz, fieldName, "B", true); + if (id) + res = env->GetStaticByteField(clazz, id); + + return res; +} + +template <> +jbyte QJNIObject::getStaticField<jbyte>(const char *className, const char *fieldName) +{ + QAttachedJNIEnv env; + + jbyte res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) + res = getStaticField<jbyte>(clazz, fieldName); + + return res; +} + +template <> +jchar QJNIObject::getStaticField<jchar>(jclass clazz, const char *fieldName) +{ + QAttachedJNIEnv env; + + jchar res = 0; + + jfieldID id = getCachedFieldID(env, clazz, fieldName, "C", true); + if (id) + res = env->GetStaticCharField(clazz, id); + + return res; +} + +template <> +jchar QJNIObject::getStaticField<jchar>(const char *className, const char *fieldName) +{ + QAttachedJNIEnv env; + + jchar res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) + res = getStaticField<jchar>(clazz, fieldName); + + return res; +} + +template <> +jshort QJNIObject::getStaticField<jshort>(jclass clazz, const char *fieldName) +{ + QAttachedJNIEnv env; + + jshort res = 0; + + jfieldID id = getCachedFieldID(env, clazz, fieldName, "S", true); + if (id) + res = env->GetStaticShortField(clazz, id); + + return res; +} + +template <> +jshort QJNIObject::getStaticField<jshort>(const char *className, const char *fieldName) +{ + QAttachedJNIEnv env; + + jshort res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) + res = getStaticField<jshort>(clazz, fieldName); + + return res; +} + +template <> +jint QJNIObject::getStaticField<jint>(jclass clazz, const char *fieldName) +{ + QAttachedJNIEnv env; + + jint res = 0; + + jfieldID id = getCachedFieldID(env, clazz, fieldName, "I", true); + if (id) + res = env->GetStaticIntField(clazz, id); + + return res; +} + +template <> +jint QJNIObject::getStaticField<jint>(const char *className, const char *fieldName) +{ + QAttachedJNIEnv env; + + jint res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) + res = getStaticField<jint>(clazz, fieldName); + + return res; +} + +template <> +jlong QJNIObject::getStaticField<jlong>(jclass clazz, const char *fieldName) +{ + QAttachedJNIEnv env; + + jlong res = 0; + + jfieldID id = getCachedFieldID(env, clazz, fieldName, "J", true); + if (id) + res = env->GetStaticLongField(clazz, id); + + return res; +} + +template <> +jlong QJNIObject::getStaticField<jlong>(const char *className, const char *fieldName) +{ + QAttachedJNIEnv env; + + jlong res = 0; + + jclass clazz = getCachedClass(env, className); + if (clazz) + res = getStaticField<jlong>(clazz, fieldName); + + return res; +} + +template <> +jfloat QJNIObject::getStaticField<jfloat>(jclass clazz, const char *fieldName) +{ + QAttachedJNIEnv env; + + jfloat res = 0.f; + + jfieldID id = getCachedFieldID(env, clazz, fieldName, "F", true); + if (id) + res = env->GetStaticFloatField(clazz, id); + + return res; +} + +template <> +jfloat QJNIObject::getStaticField<jfloat>(const char *className, const char *fieldName) +{ + QAttachedJNIEnv env; + + jfloat res = 0.f; + + jclass clazz = getCachedClass(env, className); + if (clazz) + res = getStaticField<jfloat>(clazz, fieldName); + + return res; +} + +template <> +jdouble QJNIObject::getStaticField<jdouble>(jclass clazz, const char *fieldName) +{ + QAttachedJNIEnv env; + + jdouble res = 0.; + + jfieldID id = getCachedFieldID(env, clazz, fieldName, "D", true); + if (id) + res = env->GetStaticDoubleField(clazz, id); + + return res; +} + +template <> +jdouble QJNIObject::getStaticField<jdouble>(const char *className, const char *fieldName) +{ + QAttachedJNIEnv env; + + jdouble res = 0.; + + jclass clazz = getCachedClass(env, className); + if (clazz) + res = getStaticField<jdouble>(clazz, fieldName); + + return res; +} + +template <> +QJNILocalRef<jobject> QJNIObject::getStaticObjectField<jobject>(jclass clazz, + const char *fieldName, + const char *sig) +{ + QAttachedJNIEnv env; + + jobject res = 0; + + jfieldID id = getCachedFieldID(env, clazz, fieldName, sig, true); + if (id) + res = env->GetStaticObjectField(clazz, id); + + return QJNILocalRef<jobject>(res); +} + +template <> +QJNILocalRef<jobject> QJNIObject::getStaticObjectField<jobject>(const char *className, + const char *fieldName, + const char *sig) +{ + QAttachedJNIEnv env; + + QJNILocalRef<jobject> res; + + jclass clazz = getCachedClass(env, className); + if (clazz) + res = getStaticObjectField<jobject>(clazz, fieldName, sig); + + return res; +} + +template <> +QJNILocalRef<jstring> QJNIObject::getStaticObjectField<jstring>(jclass clazz, + const char *fieldName) +{ + QAttachedJNIEnv env; + + jstring res = 0; + + jfieldID id = getCachedFieldID(env, clazz, fieldName, "Ljava/lang/String;", true); + if (id) + res = static_cast<jstring>(env->GetStaticObjectField(clazz, id)); + + return QJNILocalRef<jstring>(res); +} + +template <> +QJNILocalRef<jstring> QJNIObject::getStaticObjectField<jstring>(const char *className, + const char *fieldName) +{ + QAttachedJNIEnv env; + + QJNILocalRef<jstring> res; + + jclass clazz = getCachedClass(env, className); + if (clazz) + res = getStaticObjectField<jstring>(clazz, fieldName); + + return res; +} + +template <> +QJNILocalRef<jbooleanArray> QJNIObject::getStaticObjectField<jbooleanArray>(jclass clazz, + const char *fieldName) +{ + QAttachedJNIEnv env; + + jbooleanArray res = 0; + + jfieldID id = getCachedFieldID(env, clazz, fieldName, "[Z", true); + if (id) + res = static_cast<jbooleanArray>(env->GetStaticObjectField(clazz, id)); + + return QJNILocalRef<jbooleanArray>(res); +} + +template <> +QJNILocalRef<jbooleanArray> QJNIObject::getStaticObjectField<jbooleanArray>(const char *className, + const char *fieldName) +{ + QAttachedJNIEnv env; + + QJNILocalRef<jbooleanArray> res; + + jclass clazz = getCachedClass(env, className); + if (clazz) + res = getStaticObjectField<jbooleanArray>(clazz, fieldName); + + return res; +} + +template <> +QJNILocalRef<jbyteArray> QJNIObject::getStaticObjectField<jbyteArray>(jclass clazz, + const char *fieldName) +{ + QAttachedJNIEnv env; + + jbyteArray res = 0; + + jfieldID id = getCachedFieldID(env, clazz, fieldName, "[B", true); + if (id) + res = static_cast<jbyteArray>(env->GetStaticObjectField(clazz, id)); + + return QJNILocalRef<jbyteArray>(res); +} + +template <> +QJNILocalRef<jbyteArray> QJNIObject::getStaticObjectField<jbyteArray>(const char *className, + const char *fieldName) +{ + QAttachedJNIEnv env; + + QJNILocalRef<jbyteArray> res; + + jclass clazz = getCachedClass(env, className); + if (clazz) + res = getStaticObjectField<jbyteArray>(clazz, fieldName); + + return res; +} + +template <> +QJNILocalRef<jcharArray> QJNIObject::getStaticObjectField<jcharArray>(jclass clazz, + const char *fieldName) +{ + QAttachedJNIEnv env; + + jcharArray res = 0; + + jfieldID id = getCachedFieldID(env, clazz, fieldName, "[C", true); + if (id) + res = static_cast<jcharArray>(env->GetStaticObjectField(clazz, id)); + + return QJNILocalRef<jcharArray>(res); +} + +template <> +QJNILocalRef<jcharArray> QJNIObject::getStaticObjectField<jcharArray>(const char *className, + const char *fieldName) +{ + QAttachedJNIEnv env; + + QJNILocalRef<jcharArray> res; + + jclass clazz = getCachedClass(env, className); + if (clazz) + res = getStaticObjectField<jcharArray>(clazz, fieldName); + + return res; +} + +template <> +QJNILocalRef<jshortArray> QJNIObject::getStaticObjectField<jshortArray>(jclass clazz, + const char *fieldName) +{ + QAttachedJNIEnv env; + + jshortArray res = 0; + + jfieldID id = getCachedFieldID(env, clazz, fieldName, "[S", true); + if (id) + res = static_cast<jshortArray>(env->GetStaticObjectField(clazz, id)); + + return QJNILocalRef<jshortArray>(res); +} + +template <> +QJNILocalRef<jshortArray> QJNIObject::getStaticObjectField<jshortArray>(const char *className, + const char *fieldName) +{ + QAttachedJNIEnv env; + + QJNILocalRef<jshortArray> res; + + jclass clazz = getCachedClass(env, className); + if (clazz) + res = getStaticObjectField<jshortArray>(clazz, fieldName); + + return res; +} + +template <> +QJNILocalRef<jintArray> QJNIObject::getStaticObjectField<jintArray>(jclass clazz, + const char *fieldName) +{ + QAttachedJNIEnv env; + + jintArray res = 0; + + jfieldID id = getCachedFieldID(env, clazz, fieldName, "[I", true); + if (id) + res = static_cast<jintArray>(env->GetStaticObjectField(clazz, id)); + + return QJNILocalRef<jintArray>(res); +} + +template <> +QJNILocalRef<jintArray> QJNIObject::getStaticObjectField<jintArray>(const char *className, + const char *fieldName) +{ + QAttachedJNIEnv env; + + QJNILocalRef<jintArray> res; + + jclass clazz = getCachedClass(env, className); + if (clazz) + res = getStaticObjectField<jintArray>(clazz, fieldName); + + return res; +} + +template <> +QJNILocalRef<jlongArray> QJNIObject::getStaticObjectField<jlongArray>(jclass clazz, + const char *fieldName) +{ + QAttachedJNIEnv env; + + jlongArray res = 0; + + jfieldID id = getCachedFieldID(env, clazz, fieldName, "[J", true); + if (id) + res = static_cast<jlongArray>(env->GetStaticObjectField(clazz, id)); + + return QJNILocalRef<jlongArray>(res); +} + +template <> +QJNILocalRef<jlongArray> QJNIObject::getStaticObjectField<jlongArray>(const char *className, + const char *fieldName) +{ + QAttachedJNIEnv env; + + QJNILocalRef<jlongArray> res; + + jclass clazz = getCachedClass(env, className); + if (clazz) + res = getStaticObjectField<jlongArray>(clazz, fieldName); + + return res; +} + +template <> +QJNILocalRef<jfloatArray> QJNIObject::getStaticObjectField<jfloatArray>(jclass clazz, + const char *fieldName) +{ + QAttachedJNIEnv env; + + jfloatArray res = 0; + + jfieldID id = getCachedFieldID(env, clazz, fieldName, "[F", true); + if (id) + res = static_cast<jfloatArray>(env->GetStaticObjectField(clazz, id)); + + return QJNILocalRef<jfloatArray>(res); +} + +template <> +QJNILocalRef<jfloatArray> QJNIObject::getStaticObjectField<jfloatArray>(const char *className, + const char *fieldName) +{ + QAttachedJNIEnv env; + + QJNILocalRef<jfloatArray> res; + + jclass clazz = getCachedClass(env, className); + if (clazz) + res = getStaticObjectField<jfloatArray>(clazz, fieldName); + + return res; +} + +template <> +QJNILocalRef<jdoubleArray> QJNIObject::getStaticObjectField<jdoubleArray>(jclass clazz, + const char *fieldName) +{ + QAttachedJNIEnv env; + + jdoubleArray res = 0; + + jfieldID id = getCachedFieldID(env, clazz, fieldName, "[D", true); + if (id) + res = static_cast<jdoubleArray>(env->GetStaticObjectField(clazz, id)); + + return QJNILocalRef<jdoubleArray>(res); +} + +template <> +QJNILocalRef<jdoubleArray> QJNIObject::getStaticObjectField<jdoubleArray>(const char *className, + const char *fieldName) +{ + QAttachedJNIEnv env; + + QJNILocalRef<jdoubleArray> res; + + jclass clazz = getCachedClass(env, className); + if (clazz) + res = getStaticObjectField<jdoubleArray>(clazz, fieldName); + + return res; +} + +template <> +QJNILocalRef<jobjectArray> QJNIObject::getStaticObjectField<jobjectArray>(jclass clazz, + const char *fieldName, + const char *sig) +{ + QAttachedJNIEnv env; + + jobjectArray res = 0; + + jfieldID id = getCachedFieldID(env, clazz, fieldName, sig, true); + if (id) + res = static_cast<jobjectArray>(env->GetStaticObjectField(clazz, id)); + + return QJNILocalRef<jobjectArray>(res); +} + +template <> +QJNILocalRef<jobjectArray> QJNIObject::getStaticObjectField<jobjectArray>(const char *className, + const char *fieldName, + const char *sig) +{ + QAttachedJNIEnv env; + + QJNILocalRef<jobjectArray> res; + + jclass clazz = getCachedClass(env, className); + if (clazz) + res = getStaticObjectField<jobjectArray>(clazz, fieldName, sig); + + return res; +} + +template <> +void QJNIObject::setStaticField<jboolean>(jclass clazz, const char *fieldName, jboolean value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, clazz, fieldName, "Z", true); + if (id) + env->SetStaticBooleanField(clazz, id, value); +} + +template <> +void QJNIObject::setStaticField<jboolean>(const char *className, + const char *fieldName, + jboolean value) +{ + QAttachedJNIEnv env; + jclass clazz = getCachedClass(env, className); + if (clazz) + setStaticField<jboolean>(clazz, fieldName, value); +} + +template <> +void QJNIObject::setStaticField<jbyte>(jclass clazz, const char *fieldName, jbyte value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, clazz, fieldName, "B", true); + if (id) + env->SetStaticByteField(clazz, id, value); +} + +template <> +void QJNIObject::setStaticField<jbyte>(const char *className, + const char *fieldName, + jbyte value) +{ + QAttachedJNIEnv env; + jclass clazz = getCachedClass(env, className); + if (clazz) + setStaticField<jbyte>(clazz, fieldName, value); +} + +template <> +void QJNIObject::setStaticField<jchar>(jclass clazz, const char *fieldName, jchar value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, clazz, fieldName, "C", true); + if (id) + env->SetStaticCharField(clazz, id, value); +} + +template <> +void QJNIObject::setStaticField<jchar>(const char *className, + const char *fieldName, + jchar value) +{ + QAttachedJNIEnv env; + jclass clazz = getCachedClass(env, className); + if (clazz) + setStaticField<jchar>(clazz, fieldName, value); +} + +template <> +void QJNIObject::setStaticField<jshort>(jclass clazz, const char *fieldName, jshort value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, clazz, fieldName, "S", true); + if (id) + env->SetStaticShortField(clazz, id, value); +} + +template <> +void QJNIObject::setStaticField<jshort>(const char *className, + const char *fieldName, + jshort value) +{ + QAttachedJNIEnv env; + jclass clazz = getCachedClass(env, className); + if (clazz) + setStaticField<jshort>(clazz, fieldName, value); +} + +template <> +void QJNIObject::setStaticField<jint>(jclass clazz, const char *fieldName, jint value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, clazz, fieldName, "I", true); + if (id) + env->SetStaticIntField(clazz, id, value); +} + +template <> +void QJNIObject::setStaticField<jint>(const char *className, const char *fieldName, jint value) +{ + QAttachedJNIEnv env; + jclass clazz = getCachedClass(env, className); + if (clazz) + setStaticField<jint>(clazz, fieldName, value); +} + +template <> +void QJNIObject::setStaticField<jlong>(jclass clazz, const char *fieldName, jlong value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, clazz, fieldName, "J", true); + if (id) + env->SetStaticLongField(clazz, id, value); +} + +template <> +void QJNIObject::setStaticField<jlong>(const char *className, + const char *fieldName, + jlong value) +{ + QAttachedJNIEnv env; + jclass clazz = getCachedClass(env, className); + if (clazz) + setStaticField<jlong>(clazz, fieldName, value); +} + +template <> +void QJNIObject::setStaticField<jfloat>(jclass clazz, const char *fieldName, jfloat value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, clazz, fieldName, "F", true); + if (id) + env->SetStaticFloatField(clazz, id, value); +} + +template <> +void QJNIObject::setStaticField<jfloat>(const char *className, + const char *fieldName, + jfloat value) +{ + QAttachedJNIEnv env; + jclass clazz = getCachedClass(env, className); + if (clazz) + setStaticField<jfloat>(clazz, fieldName, value); +} + +template <> +void QJNIObject::setStaticField<jdouble>(jclass clazz, const char *fieldName, jdouble value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, clazz, fieldName, "D", true); + if (id) + env->SetStaticDoubleField(clazz, id, value); +} + +template <> +void QJNIObject::setStaticField<jdouble>(const char *className, + const char *fieldName, + jdouble value) +{ + QAttachedJNIEnv env; + jclass clazz = getCachedClass(env, className); + if (clazz) + setStaticField<jdouble>(clazz, fieldName, value); +} + +template <> +void QJNIObject::setStaticField<jobject>(jclass clazz, + const char *fieldName, + const char *sig, + jobject value) +{ + QAttachedJNIEnv env; + jfieldID id = getCachedFieldID(env, clazz, fieldName, sig, true); + if (id) + env->SetStaticObjectField(clazz, id, value); +} + +template <> +void QJNIObject::setStaticField<jobject>(const char *className, + const char *fieldName, + const char *sig, + jobject value) +{ + QAttachedJNIEnv env; + jclass clazz = getCachedClass(env, className); + if (clazz) + setStaticField<jobject>(clazz, fieldName, sig, value); +} + +template <> +void QJNIObject::setStaticField<jstring>(const char *className, + const char *fieldName, + jstring value) +{ + setStaticField<jobject>(className, fieldName, "Ljava/lang/String;", value); +} + +template <> +void QJNIObject::setStaticField<jstring>(jclass clazz, const char *fieldName, jstring value) +{ + setStaticField<jobject>(clazz, fieldName, "Ljava/lang/String;", value); +} + +template <> +void QJNIObject::setStaticField<jbooleanArray>(const char *className, + const char *fieldName, + jbooleanArray value) +{ + setStaticField<jobject>(className, fieldName, "[Z", value); +} + +template <> +void QJNIObject::setStaticField<jbooleanArray>(jclass clazz, + const char *fieldName, + jbooleanArray value) +{ + setStaticField<jobject>(clazz, fieldName, "[Z", value); +} + +template <> +void QJNIObject::setStaticField<jbyteArray>(const char *className, + const char *fieldName, + jbyteArray value) +{ + setStaticField<jobject>(className, fieldName, "[B", value); +} + +template <> +void QJNIObject::setStaticField<jbyteArray>(jclass clazz, + const char *fieldName, + jbyteArray value) +{ + setStaticField<jobject>(clazz, fieldName, "[B", value); +} + +template <> +void QJNIObject::setStaticField<jcharArray>(const char *className, + const char *fieldName, + jcharArray value) +{ + setStaticField<jobject>(className, fieldName, "[C", value); +} + +template <> +void QJNIObject::setStaticField<jcharArray>(jclass clazz, + const char *fieldName, + jcharArray value) +{ + setStaticField<jobject>(clazz, fieldName, "[C", value); +} + +template <> +void QJNIObject::setStaticField<jshortArray>(const char *className, + const char *fieldName, + jshortArray value) +{ + setStaticField<jobject>(className, fieldName, "[S", value); +} + +template <> +void QJNIObject::setStaticField<jshortArray>(jclass clazz, + const char *fieldName, + jshortArray value) +{ + setStaticField<jobject>(clazz, fieldName, "[S", value); +} + +template <> +void QJNIObject::setStaticField<jintArray>(const char *className, + const char *fieldName, + jintArray value) +{ + setStaticField<jobject>(className, fieldName, "[I", value); +} + +template <> +void QJNIObject::setStaticField<jintArray>(jclass clazz, + const char *fieldName, + jintArray value) +{ + setStaticField<jobject>(clazz, fieldName, "[I", value); +} + +template <> +void QJNIObject::setStaticField<jlongArray>(const char *className, + const char *fieldName, + jlongArray value) +{ + setStaticField<jobject>(className, fieldName, "[J", value); +} + +template <> +void QJNIObject::setStaticField<jlongArray>(jclass clazz, + const char *fieldName, + jlongArray value) +{ + setStaticField<jobject>(clazz, fieldName, "[J", value); +} + +template <> +void QJNIObject::setStaticField<jfloatArray>(const char *className, + const char *fieldName, + jfloatArray value) +{ + setStaticField<jobject>(className, fieldName, "[F", value); +} + +template <> +void QJNIObject::setStaticField<jfloatArray>(jclass clazz, + const char *fieldName, + jfloatArray value) +{ + setStaticField<jobject>(clazz, fieldName, "[F", value); +} + +template <> +void QJNIObject::setStaticField<jdoubleArray>(const char *className, + const char *fieldName, + jdoubleArray value) +{ + setStaticField<jobject>(className, fieldName, "[D", value); +} + +template <> +void QJNIObject::setStaticField<jdoubleArray>(jclass clazz, + const char *fieldName, + jdoubleArray value) +{ + setStaticField<jobject>(clazz, fieldName, "[D", value); +} + + +QT_END_NAMESPACE diff --git a/src/platformsupport/jniconvenience/qjniobject_p.h b/src/platformsupport/jniconvenience/qjniobject_p.h new file mode 100644 index 0000000000..6874765f06 --- /dev/null +++ b/src/platformsupport/jniconvenience/qjniobject_p.h @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part 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 QJNIOBJECT_H +#define QJNIOBJECT_H + +#include <qglobal.h> +#include <jni.h> + +QT_BEGIN_NAMESPACE + +template <typename T> +class QJNILocalRef; + +/** + * Allows to wrap any Java class and partially hide some of the jni calls. + * + * Usage example: + * + * QJNIObject javaString("java/lang/String"); + * jchar char = javaString.callMethod<jchar>("charAt", "(I)C", 0); + * + * ---- + * + * jstring string = QJNIObject::callStaticMethod<jstring>("java/lang/String", + * "valueOf", + * "(I)Ljava/lang/String;", 2); + * + * ---- + * + * // Constructor with argument + * jstring someString; + * QJNIObject someObject("java/some/Class", "(Ljava/lang/String;)V", someString); + * someObject.setField<jint>("fieldName", 10); + * someObject.callMethod<void>("doStuff"); + */ +class QJNIObject +{ +public: + QJNIObject(const char *className); + QJNIObject(const char *className, const char *sig, ...); + QJNIObject(jclass clazz); + QJNIObject(jclass clazz, const char *sig, ...); + QJNIObject(jobject obj); + virtual ~QJNIObject(); + + static bool isClassAvailable(const char *className); + + bool isValid() const { return m_jobject != 0; } + jobject object() const { return m_jobject; } + + template <typename T> + T callMethod(const char *methodName); + template <typename T> + T callMethod(const char *methodName, const char *sig, ...); + template <typename T> + QJNILocalRef<T> callObjectMethod(const char *methodName); + template <typename T> + QJNILocalRef<T> callObjectMethod(const char *methodName, const char *sig, ...); + + template <typename T> + static T callStaticMethod(const char *className, const char *methodName); + template <typename T> + static T callStaticMethod(const char *className, const char *methodName, const char *sig, ...); + template <typename T> + static QJNILocalRef<T> callStaticObjectMethod(const char *className, const char *methodName); + template <typename T> + static QJNILocalRef<T> callStaticObjectMethod(const char *className, + const char *methodName, + const char *sig, ...); + template <typename T> + static T callStaticMethod(jclass clazz, const char *methodName); + template <typename T> + static T callStaticMethod(jclass clazz, const char *methodName, const char *sig, ...); + template <typename T> + static QJNILocalRef<T> callStaticObjectMethod(jclass clazz, const char *methodName); + template <typename T> + static QJNILocalRef<T> callStaticObjectMethod(jclass clazz, + const char *methodName, + const char *sig, ...); + + template <typename T> + T getField(const char *fieldName); + template <typename T> + T getField(const char *fieldName, const char *sig); + template <typename T> + QJNILocalRef<T> getObjectField(const char *fieldName); + template <typename T> + QJNILocalRef<T> getObjectField(const char *fieldName, const char *sig); + + template <typename T> + void setField(const char *fieldName, T value); + template <typename T> + void setField(const char *fieldName, const char *sig, T value); + + template <typename T> + static QJNILocalRef<T> getStaticObjectField(const char *className, const char *fieldName); + template <typename T> + static QJNILocalRef<T> getStaticObjectField(const char *className, + const char *fieldName, + const char *sig); + template <typename T> + static T getStaticField(const char *className, const char *fieldName); + template <typename T> + static QJNILocalRef<T> getStaticObjectField(jclass clazz, const char *fieldName); + template <typename T> + static QJNILocalRef<T> getStaticObjectField(jclass clazz, const char *fieldName, const char *sig); + template <typename T> + static T getStaticField(jclass clazz, const char *fieldName); + + template <typename T> + static void setStaticField(const char *className, + const char *fieldName, + const char *sig, + T value); + template <typename T> + static void setStaticField(const char *className, const char *fieldName, T value); + template <typename T> + static void setStaticField(jclass clazz, const char *fieldName, const char *sig, T value); + template <typename T> + static void setStaticField(jclass clazz, const char *fieldName, T value); + +protected: + jobject m_jobject; + jclass m_jclass; + bool m_own_jclass; +}; + +QT_END_NAMESPACE + +#endif // QJNIOBJECT_H diff --git a/src/platformsupport/linuxaccessibility/application_p.h b/src/platformsupport/linuxaccessibility/application_p.h index 754d98495a..e8684ab2b5 100644 --- a/src/platformsupport/linuxaccessibility/application_p.h +++ b/src/platformsupport/linuxaccessibility/application_p.h @@ -47,7 +47,6 @@ #include <QtDBus/QDBusConnection> #include <QtGui/QAccessibleInterface> -QT_BEGIN_HEADER QT_BEGIN_NAMESPACE /* @@ -82,6 +81,5 @@ private: }; QT_END_NAMESPACE -QT_END_HEADER #endif diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor_p.h b/src/platformsupport/linuxaccessibility/atspiadaptor_p.h index b7a29fdc15..1c79cc75c8 100644 --- a/src/platformsupport/linuxaccessibility/atspiadaptor_p.h +++ b/src/platformsupport/linuxaccessibility/atspiadaptor_p.h @@ -53,7 +53,6 @@ #include "dbusconnection_p.h" #include "struct_marshallers_p.h" -QT_BEGIN_HEADER QT_BEGIN_NAMESPACE class QAccessibleInterface; @@ -216,6 +215,5 @@ private: }; QT_END_NAMESPACE -QT_END_HEADER #endif diff --git a/src/platformsupport/linuxaccessibility/bridge_p.h b/src/platformsupport/linuxaccessibility/bridge_p.h index aed437b1e2..8a02847d3d 100644 --- a/src/platformsupport/linuxaccessibility/bridge_p.h +++ b/src/platformsupport/linuxaccessibility/bridge_p.h @@ -48,7 +48,6 @@ class DeviceEventControllerAdaptor; -QT_BEGIN_HEADER QT_BEGIN_NAMESPACE class DBusConnection; @@ -81,6 +80,5 @@ private: }; QT_END_NAMESPACE -QT_END_HEADER #endif diff --git a/src/platformsupport/linuxaccessibility/cache_p.h b/src/platformsupport/linuxaccessibility/cache_p.h index 25680cd8e8..a8128d9320 100644 --- a/src/platformsupport/linuxaccessibility/cache_p.h +++ b/src/platformsupport/linuxaccessibility/cache_p.h @@ -46,7 +46,6 @@ #include <QtCore/QObject> #include "struct_marshallers_p.h" -QT_BEGIN_HEADER QT_BEGIN_NAMESPACE class QSpiDBusCache : public QObject @@ -67,6 +66,5 @@ public Q_SLOTS: }; QT_END_NAMESPACE -QT_END_HEADER #endif /* Q_SPI_CACHE_H */ diff --git a/src/platformsupport/linuxaccessibility/constant_mappings_p.h b/src/platformsupport/linuxaccessibility/constant_mappings_p.h index 7410f5f94f..a0287a910b 100644 --- a/src/platformsupport/linuxaccessibility/constant_mappings_p.h +++ b/src/platformsupport/linuxaccessibility/constant_mappings_p.h @@ -95,7 +95,6 @@ #define QSPI_REGISTRY_NAME "org.a11y.atspi.Registry" -QT_BEGIN_HEADER QT_BEGIN_NAMESPACE struct RoleNames { @@ -133,6 +132,5 @@ QSpiUIntList spiStateSetFromSpiStates(quint64 states); AtspiRelationType qAccessibleRelationToAtSpiRelation(QAccessible::Relation relation); QT_END_NAMESPACE -QT_END_HEADER #endif /* Q_SPI_CONSTANT_MAPPINGS_H */ diff --git a/src/platformsupport/linuxaccessibility/dbusconnection_p.h b/src/platformsupport/linuxaccessibility/dbusconnection_p.h index 2875dd89d8..2d55ccb547 100644 --- a/src/platformsupport/linuxaccessibility/dbusconnection_p.h +++ b/src/platformsupport/linuxaccessibility/dbusconnection_p.h @@ -47,7 +47,6 @@ #include <QtDBus/QDBusConnection> #include <QtDBus/QDBusVariant> -QT_BEGIN_HEADER QT_BEGIN_NAMESPACE class QDBusServiceWatcher; @@ -83,6 +82,5 @@ private: }; QT_END_NAMESPACE -QT_END_HEADER #endif // DBUSCONNECTION_H diff --git a/src/platformsupport/linuxaccessibility/struct_marshallers_p.h b/src/platformsupport/linuxaccessibility/struct_marshallers_p.h index 60d06cebb4..0b775d5521 100644 --- a/src/platformsupport/linuxaccessibility/struct_marshallers_p.h +++ b/src/platformsupport/linuxaccessibility/struct_marshallers_p.h @@ -49,7 +49,6 @@ #include <QtDBus/QDBusConnection> #include <QtDBus/QDBusObjectPath> -QT_BEGIN_HEADER QT_BEGIN_NAMESPACE typedef QList <int> QSpiIntList; @@ -173,5 +172,4 @@ Q_DECLARE_METATYPE(QSpiAttributeSet) Q_DECLARE_METATYPE(QSpiAppUpdate) Q_DECLARE_METATYPE(QSpiDeviceEvent) -QT_END_HEADER #endif /* Q_SPI_STRUCT_MARSHALLERS_H */ diff --git a/src/platformsupport/platformsupport.pro b/src/platformsupport/platformsupport.pro index 57d9b422f4..0566e9d3ec 100644 --- a/src/platformsupport/platformsupport.pro +++ b/src/platformsupport/platformsupport.pro @@ -2,13 +2,14 @@ TARGET = QtPlatformSupport QT = core-private gui-private CONFIG += static internal_module -mac:LIBS += -lz -framework CoreFoundation -framework Carbon +mac:LIBS += -lz load(qt_module) DEFINES += QT_NO_CAST_FROM_ASCII PRECOMPILED_HEADER = ../corelib/global/qt_pch.h +include(cfsocketnotifier/cfsocketnotifier.pri) include(cglconvenience/cglconvenience.pri) include(dnd/dnd.pri) include(eglconvenience/eglconvenience.pri) @@ -21,3 +22,4 @@ include(devicediscovery/devicediscovery.pri) include(services/services.pri) include(themes/themes.pri) include(linuxaccessibility/linuxaccessibility.pri) +include(jniconvenience/jniconvenience.pri) diff --git a/src/platformsupport/services/genericunix/qgenericunixservices_p.h b/src/platformsupport/services/genericunix/qgenericunixservices_p.h index 13cf79de01..92166caf7b 100644 --- a/src/platformsupport/services/genericunix/qgenericunixservices_p.h +++ b/src/platformsupport/services/genericunix/qgenericunixservices_p.h @@ -45,8 +45,6 @@ #include <qpa/qplatformservices.h> #include <QtCore/QString> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE class QGenericUnixServices : public QPlatformServices @@ -66,6 +64,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QGENERICUNIXDESKTOPSERVICES_H diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp index 6e40bbfa15..6ea68397b6 100644 --- a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp +++ b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp @@ -426,6 +426,9 @@ QStringList QGenericUnixTheme::themeNames() result.push_back(QLatin1String(QKdeTheme::name)); #endif } else { // Gnome, Unity, other Gtk-based desktops like XFCE. + // prefer the GTK2 theme implementation with native dialogs etc. + result.push_back(QStringLiteral("gtk2")); + // fallback to the generic Gnome theme if loading the GTK2 theme fails result.push_back(QLatin1String(QGnomeTheme::name)); } const QString session = QString::fromLocal8Bit(qgetenv("DESKTOP_SESSION")); diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h b/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h index 370b703204..b0ac13efe4 100644 --- a/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h +++ b/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h @@ -47,8 +47,6 @@ #include <QtCore/QStringList> #include <QtGui/QFont> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE class ResourceHelper @@ -132,6 +130,4 @@ QPlatformTheme *qt_createUnixTheme(); QT_END_NAMESPACE -QT_END_HEADER - #endif // QGENERICUNIXTHEMES_H |