summaryrefslogtreecommitdiffstats
path: root/src/platformsupport
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@digia.com>2014-02-19 10:06:25 +0100
committerOswald Buddenhagen <oswald.buddenhagen@digia.com>2014-02-19 10:06:25 +0100
commit30fd22b9574def54726e7b193127cc0c901c1b4c (patch)
tree96dfc923044db0515064ba39d052d9ed577e3e40 /src/platformsupport
parentd7b0581c1c2ef60c08d238dae39298af6904918f (diff)
parent6aa09bbce59828d028f6d1e81d2bfc6ba537aae1 (diff)
Merge remote-tracking branch 'origin/dev' into stable
Diffstat (limited to 'src/platformsupport')
-rw-r--r--src/platformsupport/cglconvenience/cglconvenience.mm1
-rw-r--r--src/platformsupport/devicediscovery/devicediscovery.pri13
-rw-r--r--src/platformsupport/devicediscovery/qdevicediscovery_dummy.cpp72
-rw-r--r--src/platformsupport/devicediscovery/qdevicediscovery_p.h9
-rw-r--r--src/platformsupport/eglconvenience/eglconvenience.pri34
-rw-r--r--src/platformsupport/eglconvenience/qeglcompositor.cpp150
-rw-r--r--src/platformsupport/eglconvenience/qeglcompositor_p.h80
-rw-r--r--src/platformsupport/eglconvenience/qeglconvenience.cpp134
-rw-r--r--src/platformsupport/eglconvenience/qeglconvenience_p.h10
-rw-r--r--src/platformsupport/eglconvenience/qeglpbuffer.cpp12
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp242
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h92
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcontext.cpp77
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcontext_p.h7
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcursor.cpp391
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcursor_p.h137
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformintegration.cpp299
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformintegration_p.h111
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformscreen.cpp110
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformscreen_p.h81
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformwindow.cpp130
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformwindow_p.h78
-rw-r--r--src/platformsupport/fbconvenience/fbconvenience.pri7
-rw-r--r--src/platformsupport/fbconvenience/qfbvthandler.cpp111
-rw-r--r--src/platformsupport/fbconvenience/qfbvthandler_p.h68
-rw-r--r--src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp17
-rw-r--r--src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h2
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp310
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h2
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm204
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h25
-rw-r--r--src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm20
-rw-r--r--src/platformsupport/glxconvenience/qglxconvenience.cpp29
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboard_defaultmap_p.h4
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h2
-rw-r--r--src/platformsupport/themes/genericunix/qgenericunixthemes.cpp24
-rw-r--r--src/platformsupport/themes/genericunix/qgenericunixthemes_p.h3
37 files changed, 2788 insertions, 310 deletions
diff --git a/src/platformsupport/cglconvenience/cglconvenience.mm b/src/platformsupport/cglconvenience/cglconvenience.mm
index 12ae5965df..50c39a12e0 100644
--- a/src/platformsupport/cglconvenience/cglconvenience.mm
+++ b/src/platformsupport/cglconvenience/cglconvenience.mm
@@ -121,6 +121,7 @@ void *qcgl_createNSOpenGLPixelFormat(const QSurfaceFormat &format)
<< NSOpenGLPFASamples << (NSOpenGLPixelFormatAttribute) format.samples();
}
+ attrs << NSOpenGLPFAAllowOfflineRenderers;
attrs << 0;
NSOpenGLPixelFormat* pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs.constData()];
diff --git a/src/platformsupport/devicediscovery/devicediscovery.pri b/src/platformsupport/devicediscovery/devicediscovery.pri
index 9a58eeedfe..9748129225 100644
--- a/src/platformsupport/devicediscovery/devicediscovery.pri
+++ b/src/platformsupport/devicediscovery/devicediscovery.pri
@@ -1,12 +1,17 @@
-linux:contains(QT_CONFIG, evdev) {
- HEADERS += $$PWD/qdevicediscovery_p.h
+HEADERS += $$PWD/qdevicediscovery_p.h
+linux {
contains(QT_CONFIG, libudev) {
SOURCES += $$PWD/qdevicediscovery_udev.cpp
-
INCLUDEPATH += $$QMAKE_INCDIR_LIBUDEV
LIBS_PRIVATE += $$QMAKE_LIBS_LIBUDEV
- } else {
+ # Use our own define. QT_NO_LIBUDEV may not be set on non-Linux systems.
+ DEFINES += QDEVICEDISCOVERY_UDEV
+ } else: contains(QT_CONFIG, evdev) {
SOURCES += $$PWD/qdevicediscovery_static.cpp
+ } else {
+ SOURCES += $$PWD/qdevicediscovery_dummy.cpp
}
+} else {
+ SOURCES += $$PWD/qdevicediscovery_dummy.cpp
}
diff --git a/src/platformsupport/devicediscovery/qdevicediscovery_dummy.cpp b/src/platformsupport/devicediscovery/qdevicediscovery_dummy.cpp
new file mode 100644
index 0000000000..53e042272b
--- /dev/null
+++ b/src/platformsupport/devicediscovery/qdevicediscovery_dummy.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** 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 "qdevicediscovery_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QDeviceDiscovery *QDeviceDiscovery::create(QDeviceTypes types, QObject *parent)
+{
+ return new QDeviceDiscovery(types, parent);
+}
+
+QDeviceDiscovery::QDeviceDiscovery(QDeviceTypes types, QObject *parent)
+ : QObject(parent),
+ m_types(types)
+{
+}
+
+QDeviceDiscovery::~QDeviceDiscovery()
+{
+}
+
+QStringList QDeviceDiscovery::scanConnectedDevices()
+{
+ return QStringList();
+}
+
+bool QDeviceDiscovery::checkDeviceType(const QString &device)
+{
+ Q_UNUSED(device);
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/devicediscovery/qdevicediscovery_p.h b/src/platformsupport/devicediscovery/qdevicediscovery_p.h
index 5485b73fd7..0e21118324 100644
--- a/src/platformsupport/devicediscovery/qdevicediscovery_p.h
+++ b/src/platformsupport/devicediscovery/qdevicediscovery_p.h
@@ -44,8 +44,9 @@
#include <QObject>
#include <QSocketNotifier>
+#include <QStringList>
-#ifndef QT_NO_LIBUDEV
+#ifdef QDEVICEDISCOVERY_UDEV
#include <libudev.h>
#endif
@@ -88,13 +89,13 @@ signals:
void deviceDetected(const QString &deviceNode);
void deviceRemoved(const QString &deviceNode);
-#ifndef QT_NO_LIBUDEV
+#ifdef QDEVICEDISCOVERY_UDEV
private slots:
void handleUDevNotification();
#endif
private:
-#ifndef QT_NO_LIBUDEV
+#ifdef QDEVICEDISCOVERY_UDEV
QDeviceDiscovery(QDeviceTypes types, struct udev *udev, QObject *parent = 0);
bool checkDeviceType(struct udev_device *dev);
#else
@@ -104,7 +105,7 @@ private:
QDeviceTypes m_types;
-#ifndef QT_NO_LIBUDEV
+#ifdef QDEVICEDISCOVERY_UDEV
void startWatching();
void stopWatching();
diff --git a/src/platformsupport/eglconvenience/eglconvenience.pri b/src/platformsupport/eglconvenience/eglconvenience.pri
index 506f4ab4ea..c026ff5a4b 100644
--- a/src/platformsupport/eglconvenience/eglconvenience.pri
+++ b/src/platformsupport/eglconvenience/eglconvenience.pri
@@ -3,11 +3,33 @@ contains(QT_CONFIG,egl) {
$$PWD/qeglconvenience_p.h \
$$PWD/qeglplatformcontext_p.h \
$$PWD/qeglpbuffer_p.h
+
SOURCES += \
$$PWD/qeglconvenience.cpp \
$$PWD/qeglplatformcontext.cpp \
$$PWD/qeglpbuffer.cpp
+ unix {
+ HEADERS += \
+ $$PWD/qeglplatformcursor_p.h \
+ $$PWD/qeglplatformwindow_p.h \
+ $$PWD/qeglplatformscreen_p.h \
+ $$PWD/qeglcompositor_p.h \
+ $$PWD/qeglplatformbackingstore_p.h \
+ $$PWD/qeglplatformintegration_p.h
+
+ SOURCES += \
+ $$PWD/qeglplatformcursor.cpp \
+ $$PWD/qeglplatformwindow.cpp \
+ $$PWD/qeglplatformscreen.cpp \
+ $$PWD/qeglcompositor.cpp \
+ $$PWD/qeglplatformbackingstore.cpp \
+ $$PWD/qeglplatformintegration.cpp
+ }
+
+ # Avoid X11 header collision
+ DEFINES += MESA_EGL_NO_X11_HEADERS
+
contains(QT_CONFIG,xlib) {
HEADERS += \
$$PWD/qxlibeglintegration_p.h
@@ -15,5 +37,15 @@ contains(QT_CONFIG,egl) {
$$PWD/qxlibeglintegration.cpp
}
CONFIG += egl
-}
+} else: contains(QT_CONFIG,dynamicgl) {
+ HEADERS += \
+ $$PWD/qeglconvenience_p.h \
+ $$PWD/qeglplatformcontext_p.h \
+ $$PWD/qeglpbuffer_p.h
+
+ SOURCES += \
+ $$PWD/qeglconvenience.cpp \
+ $$PWD/qeglplatformcontext.cpp \
+ $$PWD/qeglpbuffer.cpp
+}
diff --git a/src/platformsupport/eglconvenience/qeglcompositor.cpp b/src/platformsupport/eglconvenience/qeglcompositor.cpp
new file mode 100644
index 0000000000..a38f00d4f6
--- /dev/null
+++ b/src/platformsupport/eglconvenience/qeglcompositor.cpp
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** 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/QOpenGLContext>
+#include <QtGui/QOpenGLShaderProgram>
+#include <QtGui/QOpenGLFramebufferObject>
+#include <QtGui/private/qopengltextureblitter_p.h>
+#include <qpa/qplatformbackingstore.h>
+
+#include "qeglcompositor_p.h"
+#include "qeglplatformwindow_p.h"
+#include "qeglplatformscreen_p.h"
+
+QT_BEGIN_NAMESPACE
+
+static QEGLCompositor *compositor = 0;
+
+QEGLCompositor::QEGLCompositor()
+ : m_context(0),
+ m_window(0),
+ m_blitter(0)
+{
+ Q_ASSERT(!compositor);
+ m_updateTimer.setSingleShot(true);
+ m_updateTimer.setInterval(0);
+ connect(&m_updateTimer, SIGNAL(timeout()), SLOT(renderAll()));
+}
+
+QEGLCompositor::~QEGLCompositor()
+{
+ Q_ASSERT(compositor == this);
+ if (m_blitter) {
+ m_blitter->destroy();
+ delete m_blitter;
+ }
+ compositor = 0;
+}
+
+void QEGLCompositor::schedule(QOpenGLContext *context, QEGLPlatformWindow *window)
+{
+ m_context = context;
+ m_window = window;
+ if (!m_updateTimer.isActive())
+ m_updateTimer.start();
+}
+
+void QEGLCompositor::renderAll()
+{
+ Q_ASSERT(m_context && m_window);
+ m_context->makeCurrent(m_window->window());
+
+ if (!m_blitter) {
+ m_blitter = new QOpenGLTextureBlitter;
+ m_blitter->create();
+ }
+ m_blitter->bind();
+
+ QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen());
+ QList<QEGLPlatformWindow *> windows = screen->windows();
+ for (int i = 0; i < windows.size(); ++i)
+ render(windows.at(i));
+
+ m_blitter->release();
+ m_context->swapBuffers(m_window->window());
+
+ for (int i = 0; i < windows.size(); ++i)
+ windows.at(i)->composited();
+}
+
+void QEGLCompositor::render(QEGLPlatformWindow *window)
+{
+ const QPlatformTextureList *textures = window->textures();
+ if (!textures)
+ return;
+
+ const QRect targetWindowRect(QPoint(0, 0), window->screen()->geometry().size());
+ glViewport(0, 0, targetWindowRect.width(), targetWindowRect.height());
+
+ for (int i = 0; i < textures->count(); ++i) {
+ uint textureId = textures->textureId(i);
+ glBindTexture(GL_TEXTURE_2D, textureId);
+ QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i),
+ targetWindowRect);
+ m_blitter->setSwizzleRB(window->isRaster());
+
+ if (textures->count() > 1 && i == textures->count() - 1) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
+ glDisable(GL_BLEND);
+ } else if (textures->count() == 1) {
+ m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
+ } else {
+ m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginBottomLeft);
+ }
+ }
+}
+
+QEGLCompositor *QEGLCompositor::instance()
+{
+ if (!compositor)
+ compositor = new QEGLCompositor;
+ return compositor;
+}
+
+void QEGLCompositor::destroy()
+{
+ delete compositor;
+ compositor = 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/eglconvenience/qeglcompositor_p.h b/src/platformsupport/eglconvenience/qeglcompositor_p.h
new file mode 100644
index 0000000000..370345ada6
--- /dev/null
+++ b/src/platformsupport/eglconvenience/qeglcompositor_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** 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 QEGLCOMPOSITOR_H
+#define QEGLCOMPOSITOR_H
+
+#include <QtCore/QTimer>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLContext;
+class QOpenGLTextureBlitter;
+class QEGLPlatformWindow;
+
+class QEGLCompositor : public QObject
+{
+ Q_OBJECT
+
+public:
+ void schedule(QOpenGLContext *context, QEGLPlatformWindow *window);
+
+ static QEGLCompositor *instance();
+ static void destroy();
+
+private slots:
+ void renderAll();
+
+private:
+ QEGLCompositor();
+ ~QEGLCompositor();
+
+ void render(QEGLPlatformWindow *window);
+
+ QOpenGLContext *m_context;
+ QEGLPlatformWindow *m_window;
+ QTimer m_updateTimer;
+ QOpenGLTextureBlitter *m_blitter;
+};
+
+QT_END_NAMESPACE
+
+#endif // QEGLCOMPOSITOR_H
diff --git a/src/platformsupport/eglconvenience/qeglconvenience.cpp b/src/platformsupport/eglconvenience/qeglconvenience.cpp
index 32f553a3f5..a36d0b83d4 100644
--- a/src/platformsupport/eglconvenience/qeglconvenience.cpp
+++ b/src/platformsupport/eglconvenience/qeglconvenience.cpp
@@ -40,6 +40,13 @@
****************************************************************************/
#include <QByteArray>
+#include <QOpenGLFunctions>
+
+#ifdef Q_OS_LINUX
+#include <sys/ioctl.h>
+#include <linux/fb.h>
+#include <private/qmath_p.h>
+#endif
#include "qeglconvenience_p.h"
@@ -237,12 +244,15 @@ EGLConfig QEglConfigChooser::chooseConfig()
configureAttributes.append(EGL_OPENVG_BIT);
break;
#ifdef EGL_VERSION_1_4
-# if !defined(QT_OPENGL_ES_2)
case QSurfaceFormat::DefaultRenderableType:
-# endif
- case QSurfaceFormat::OpenGL:
- configureAttributes.append(EGL_OPENGL_BIT);
+ if (!QOpenGLFunctions::isES())
+ configureAttributes.append(EGL_OPENGL_BIT);
+ else
+ configureAttributes.append(EGL_OPENGL_ES2_BIT);
break;
+ case QSurfaceFormat::OpenGL:
+ configureAttributes.append(EGL_OPENGL_BIT);
+ break;
#endif
case QSurfaceFormat::OpenGLES:
if (m_format.majorVersion() == 1) {
@@ -347,11 +357,12 @@ QSurfaceFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config,
if (referenceFormat.renderableType() == QSurfaceFormat::OpenVG && (renderableType & EGL_OPENVG_BIT))
format.setRenderableType(QSurfaceFormat::OpenVG);
#ifdef EGL_VERSION_1_4
- else if ((referenceFormat.renderableType() == QSurfaceFormat::OpenGL
-# if !defined(QT_OPENGL_ES_2)
- || referenceFormat.renderableType() == QSurfaceFormat::DefaultRenderableType
-# endif
- ) && (renderableType & EGL_OPENGL_BIT))
+ else if (referenceFormat.renderableType() == QSurfaceFormat::OpenGL
+ && (renderableType & EGL_OPENGL_BIT))
+ format.setRenderableType(QSurfaceFormat::OpenGL);
+ else if (referenceFormat.renderableType() == QSurfaceFormat::DefaultRenderableType
+ && !QOpenGLFunctions::isES()
+ && (renderableType & EGL_OPENGL_BIT))
format.setRenderableType(QSurfaceFormat::OpenGL);
#endif
else
@@ -365,6 +376,7 @@ QSurfaceFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config,
format.setStencilBufferSize(stencilSize);
format.setSamples(sampleCount);
format.setStereo(false); // EGL doesn't support stereo buffers
+ format.setSwapInterval(referenceFormat.swapInterval());
// Clear the EGL error state because some of the above may
// have errored out because the attribute is not applicable
@@ -426,4 +438,108 @@ void q_printEglConfig(EGLDisplay display, EGLConfig config)
qWarning("\n");
}
+#ifdef Q_OS_LINUX
+
+QSizeF q_physicalScreenSizeFromFb(int framebufferDevice, const QSize &screenSize)
+{
+ const int defaultPhysicalDpi = 100;
+ static QSizeF size;
+
+ if (size.isEmpty()) {
+ // Note: in millimeters
+ int width = qgetenv("QT_QPA_EGLFS_PHYSICAL_WIDTH").toInt();
+ int height = qgetenv("QT_QPA_EGLFS_PHYSICAL_HEIGHT").toInt();
+
+ if (width && height) {
+ size.setWidth(width);
+ size.setHeight(height);
+ return size;
+ }
+
+ struct fb_var_screeninfo vinfo;
+ int w = -1;
+ int h = -1;
+ QSize screenResolution;
+
+ if (framebufferDevice != -1) {
+ if (ioctl(framebufferDevice, FBIOGET_VSCREENINFO, &vinfo) == -1) {
+ qWarning("eglconvenience: Could not query screen info");
+ } else {
+ w = vinfo.width;
+ h = vinfo.height;
+ screenResolution = QSize(vinfo.xres, vinfo.yres);
+ }
+ } else {
+ // Use the provided screen size, when available, since some platforms may have their own
+ // specific way to query it. Otherwise try querying it from the framebuffer.
+ screenResolution = screenSize.isEmpty() ? q_screenSizeFromFb(framebufferDevice) : screenSize;
+ }
+
+ size.setWidth(w <= 0 ? screenResolution.width() * Q_MM_PER_INCH / defaultPhysicalDpi : qreal(w));
+ size.setHeight(h <= 0 ? screenResolution.height() * Q_MM_PER_INCH / defaultPhysicalDpi : qreal(h));
+ }
+
+ return size;
+}
+
+QSize q_screenSizeFromFb(int framebufferDevice)
+{
+ const int defaultWidth = 800;
+ const int defaultHeight = 600;
+ static QSize size;
+
+ if (size.isEmpty()) {
+ int width = qgetenv("QT_QPA_EGLFS_WIDTH").toInt();
+ int height = qgetenv("QT_QPA_EGLFS_HEIGHT").toInt();
+
+ if (width && height) {
+ size.setWidth(width);
+ size.setHeight(height);
+ return size;
+ }
+
+ struct fb_var_screeninfo vinfo;
+ int xres = -1;
+ int yres = -1;
+
+ if (framebufferDevice != -1) {
+ if (ioctl(framebufferDevice, FBIOGET_VSCREENINFO, &vinfo) == -1) {
+ qWarning("eglconvenience: Could not read screen info");
+ } else {
+ xres = vinfo.xres;
+ yres = vinfo.yres;
+ }
+ }
+
+ size.setWidth(xres <= 0 ? defaultWidth : xres);
+ size.setHeight(yres <= 0 ? defaultHeight : yres);
+ }
+
+ return size;
+}
+
+int q_screenDepthFromFb(int framebufferDevice)
+{
+ const int defaultDepth = 32;
+ static int depth = qgetenv("QT_QPA_EGLFS_DEPTH").toInt();
+
+ if (depth == 0) {
+ struct fb_var_screeninfo vinfo;
+
+ if (framebufferDevice != -1) {
+ if (ioctl(framebufferDevice, FBIOGET_VSCREENINFO, &vinfo) == -1)
+ qWarning("eglconvenience: Could not query screen info");
+ else
+ depth = vinfo.bits_per_pixel;
+ }
+
+ if (depth <= 0)
+ depth = defaultDepth;
+ }
+
+ return depth;
+}
+
+#endif // Q_OS_LINUX
+
QT_END_NAMESPACE
diff --git a/src/platformsupport/eglconvenience/qeglconvenience_p.h b/src/platformsupport/eglconvenience/qeglconvenience_p.h
index 35c225cc2f..8616275e53 100644
--- a/src/platformsupport/eglconvenience/qeglconvenience_p.h
+++ b/src/platformsupport/eglconvenience/qeglconvenience_p.h
@@ -42,11 +42,11 @@
#ifndef QEGLCONVENIENCE_H
#define QEGLCONVENIENCE_H
-
#include <QtGui/QSurfaceFormat>
#include <QtCore/QVector>
-
+#include <QtCore/QSizeF>
#include <EGL/egl.h>
+
QT_BEGIN_NAMESPACE
QVector<EGLint> q_createConfigAttributesFromFormat(const QSurfaceFormat &format);
@@ -56,6 +56,12 @@ QSurfaceFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config,
bool q_hasEglExtension(EGLDisplay display,const char* extensionName);
void q_printEglConfig(EGLDisplay display, EGLConfig config);
+#ifdef Q_OS_UNIX
+QSizeF q_physicalScreenSizeFromFb(int framebufferDevice, const QSize &screenSize = QSize());
+QSize q_screenSizeFromFb(int framebufferDevice);
+int q_screenDepthFromFb(int framebufferDevice);
+#endif
+
class QEglConfigChooser
{
public:
diff --git a/src/platformsupport/eglconvenience/qeglpbuffer.cpp b/src/platformsupport/eglconvenience/qeglpbuffer.cpp
index 919314e9aa..295f8756c4 100644
--- a/src/platformsupport/eglconvenience/qeglpbuffer.cpp
+++ b/src/platformsupport/eglconvenience/qeglpbuffer.cpp
@@ -45,6 +45,18 @@
QT_BEGIN_NAMESPACE
+/*!
+ \class QEGLPbuffer
+ \brief A pbuffer-based implementation of QPlatformOffscreenSurface for EGL.
+ \since 5.2
+ \internal
+ \ingroup qpa
+
+ To use this implementation in the platform plugin simply
+ reimplement QPlatformIntegration::createPlatformOffscreenSurface()
+ and return a new instance of this class.
+*/
+
QEGLPbuffer::QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface)
: QPlatformOffscreenSurface(offscreenSurface)
, m_format(format)
diff --git a/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp b/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp
new file mode 100644
index 0000000000..24e9ccd39f
--- /dev/null
+++ b/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp
@@ -0,0 +1,242 @@
+/****************************************************************************
+**
+** 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/QOpenGLShaderProgram>
+#include <QtGui/QOpenGLContext>
+
+#include "qeglplatformbackingstore_p.h"
+#include "qeglcompositor_p.h"
+#include "qeglplatformwindow_p.h"
+#include "qeglplatformscreen_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QEGLPlatformBackingStore
+ \brief A backing store implementation for EGL and GLES.
+ \since 5.2
+ \internal
+ \ingroup qpa
+
+ This implementation uploads raster-rendered widget windows into
+ textures and composites them onto a single native window using
+ QEGLCompositor. This means that multiple top-level widgets are
+ supported without creating actual native windows for each of them.
+
+ The class is ready to be used as-is, the default
+ QEGLPlatformIntegration::createPlatformBackingStore()
+ implementation creates an instance which is ready to be used
+ without further customization.
+
+ If QEGLCompositor is not suitable, this backing store
+ implementation can also be used without it. In this case a
+ subclass must reimplement composite() and schedule an update in
+ its custom compositor when this function is called. The textures
+ are accessible via QEGLPlatformWindow::texture().
+*/
+
+QEGLPlatformBackingStore::QEGLPlatformBackingStore(QWindow *window)
+ : QPlatformBackingStore(window),
+ m_window(static_cast<QEGLPlatformWindow *>(window->handle())),
+ m_bsTexture(0),
+ m_textures(new QPlatformTextureList),
+ m_lockedWidgetTextures(0)
+{
+ m_window->setBackingStore(this);
+}
+
+QEGLPlatformBackingStore::~QEGLPlatformBackingStore()
+{
+ delete m_textures;
+}
+
+QPaintDevice *QEGLPlatformBackingStore::paintDevice()
+{
+ return &m_image;
+}
+
+void QEGLPlatformBackingStore::updateTexture()
+{
+ if (!m_bsTexture) {
+ glGenTextures(1, &m_bsTexture);
+ glBindTexture(GL_TEXTURE_2D, m_bsTexture);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ // QOpenGLTextureBlitter requires GL_REPEAT for the time being
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_image.width(), m_image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ } else {
+ glBindTexture(GL_TEXTURE_2D, m_bsTexture);
+ }
+
+ if (!m_dirty.isNull()) {
+ QRegion fixed;
+ QRect imageRect = m_image.rect();
+
+ foreach (const QRect &rect, m_dirty.rects()) {
+ // intersect with image rect to be sure
+ QRect r = imageRect & rect;
+
+ // if the rect is wide enough it's cheaper to just
+ // extend it instead of doing an image copy
+ if (r.width() >= imageRect.width() / 2) {
+ r.setX(0);
+ r.setWidth(imageRect.width());
+ }
+
+ fixed |= r;
+ }
+
+ foreach (const QRect &rect, fixed.rects()) {
+ // if the sub-rect is full-width we can pass the image data directly to
+ // OpenGL instead of copying, since there's no gap between scanlines
+ if (rect.width() == imageRect.width()) {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
+ m_image.constScanLine(rect.y()));
+ } else {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
+ m_image.copy(rect).constBits());
+ }
+ }
+
+ m_dirty = QRegion();
+ }
+}
+
+void QEGLPlatformBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
+{
+ // Called for ordinary raster windows. This is rare since RasterGLSurface
+ // support is claimed which leads to having all QWidget windows marked as
+ // RasterGLSurface instead of just Raster. These go through
+ // compositeAndFlush() instead of this function.
+
+ Q_UNUSED(region);
+ Q_UNUSED(offset);
+
+ QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen());
+ QEGLPlatformWindow *dstWin = screen->compositingWindow();
+ if (!dstWin || !dstWin->isRaster())
+ return;
+
+ screen->compositingContext()->makeCurrent(dstWin->window());
+ updateTexture();
+ m_textures->clear();
+ m_textures->appendTexture(m_bsTexture, window->geometry());
+ composite(screen->compositingContext(), dstWin);
+}
+
+void QEGLPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &region, const QPoint &offset,
+ QPlatformTextureList *textures, QOpenGLContext *context)
+{
+ // QOpenGLWidget content provided as textures. The raster content should go on top.
+
+ Q_UNUSED(region);
+ Q_UNUSED(offset);
+ Q_UNUSED(context);
+
+ QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen());
+ QEGLPlatformWindow *dstWin = screen->compositingWindow();
+ if (!dstWin || !dstWin->isRaster())
+ return;
+
+ screen->compositingContext()->makeCurrent(dstWin->window());
+
+ m_textures->clear();
+ for (int i = 0; i < textures->count(); ++i) {
+ uint textureId = textures->textureId(i);
+ QRect geom = textures->geometry(i);
+ m_textures->appendTexture(textureId, geom);
+ }
+
+ updateTexture();
+ m_textures->appendTexture(m_bsTexture, window->geometry());
+
+ textures->lock(true);
+ m_lockedWidgetTextures = textures;
+
+ composite(screen->compositingContext(), dstWin);
+}
+
+void QEGLPlatformBackingStore::composite(QOpenGLContext *context, QEGLPlatformWindow *window)
+{
+ QEGLCompositor::instance()->schedule(context, window);
+}
+
+void QEGLPlatformBackingStore::composited()
+{
+ if (m_lockedWidgetTextures) {
+ QPlatformTextureList *textureList = m_lockedWidgetTextures;
+ m_lockedWidgetTextures = 0; // may reenter so null before unlocking
+ textureList->lock(false);
+ }
+}
+
+void QEGLPlatformBackingStore::beginPaint(const QRegion &rgn)
+{
+ m_dirty |= rgn;
+}
+
+void QEGLPlatformBackingStore::resize(const QSize &size, const QRegion &staticContents)
+{
+ Q_UNUSED(staticContents);
+
+ QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen());
+ QEGLPlatformWindow *dstWin = screen->compositingWindow();
+ if (!dstWin || (!dstWin->isRaster() && dstWin->window()->surfaceType() != QSurface::RasterGLSurface))
+ return;
+
+ m_image = QImage(size, QImage::Format_RGB32);
+ m_window->create();
+
+ screen->compositingContext()->makeCurrent(dstWin->window());
+ if (m_bsTexture) {
+ glDeleteTextures(1, &m_bsTexture);
+ m_bsTexture = 0;
+ }
+}
+
+QImage QEGLPlatformBackingStore::toImage() const
+{
+ return m_image;
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h b/src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h
new file mode 100644
index 0000000000..cb1e5999b0
--- /dev/null
+++ b/src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** 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 QEGLPLATFORMBACKINGSTORE_H
+#define QEGLPLATFORMBACKINGSTORE_H
+
+#include <qpa/qplatformbackingstore.h>
+
+#include <QImage>
+#include <QRegion>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLContext;
+class QPlatformTextureList;
+class QEGLPlatformWindow;
+
+class QEGLPlatformBackingStore : public QPlatformBackingStore
+{
+public:
+ QEGLPlatformBackingStore(QWindow *window);
+ ~QEGLPlatformBackingStore();
+
+ QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
+
+ void beginPaint(const QRegion &) Q_DECL_OVERRIDE;
+
+ void flush(QWindow *window, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE;
+ void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE;
+
+ QImage toImage() const Q_DECL_OVERRIDE;
+ void composeAndFlush(QWindow *window, const QRegion &region, const QPoint &offset,
+ QPlatformTextureList *textures, QOpenGLContext *context) Q_DECL_OVERRIDE;
+
+ const QPlatformTextureList *textures() const { return m_textures; }
+
+ virtual void composite(QOpenGLContext *context, QEGLPlatformWindow *window);
+
+ void composited();
+
+private:
+ void updateTexture();
+
+ QEGLPlatformWindow *m_window;
+ QImage m_image;
+ QRegion m_dirty;
+ uint m_bsTexture;
+ QPlatformTextureList *m_textures;
+ QPlatformTextureList *m_lockedWidgetTextures;
+};
+
+QT_END_NAMESPACE
+
+#endif // QEGLPLATFORMBACKINGSTORE_H
diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
index 716b01b4d9..3a34748fc7 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
+++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
@@ -40,12 +40,28 @@
****************************************************************************/
#include "qeglplatformcontext_p.h"
-
#include "qeglconvenience_p.h"
-
#include <qpa/qplatformwindow.h>
-
-#include <EGL/egl.h>
+#include <QtGui/QOpenGLFunctions>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QEGLPlatformContext
+ \brief An EGL context implementation.
+ \since 5.2
+ \internal
+ \ingroup qpa
+
+ Implement QPlatformOpenGLContext using EGL. To use it in platform
+ plugins a subclass must be created since
+ eglSurfaceForPlatformSurface() has to be reimplemented. This
+ function is used for mapping platform surfaces (windows) to EGL
+ surfaces and is necessary since different platform plugins may
+ have different ways of handling native windows (for example, a
+ plugin may choose not to back every platform window by a real EGL
+ surface). Other than that, no further customization is necessary.
+ */
static inline void bindApi(const QSurfaceFormat &format)
{
@@ -54,9 +70,12 @@ static inline void bindApi(const QSurfaceFormat &format)
eglBindAPI(EGL_OPENVG_API);
break;
#ifdef EGL_VERSION_1_4
-# if !defined(QT_OPENGL_ES_2)
case QSurfaceFormat::DefaultRenderableType:
-# endif
+ if (!QOpenGLFunctions::isES())
+ eglBindAPI(EGL_OPENGL_API);
+ else
+ eglBindAPI(EGL_OPENGL_ES_API);
+ break;
case QSurfaceFormat::OpenGL:
eglBindAPI(EGL_OPENGL_API);
break;
@@ -72,6 +91,9 @@ QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatform
EGLenum eglApi)
: m_eglDisplay(display)
, m_eglConfig(q_configFromGLFormat(display, format))
+ , m_swapInterval(-1)
+ , m_swapIntervalEnvChecked(false)
+ , m_swapIntervalFromEnv(-1)
{
init(format, share);
Q_UNUSED(eglApi);
@@ -81,6 +103,9 @@ QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatform
EGLConfig config, EGLenum eglApi)
: m_eglDisplay(display)
, m_eglConfig(config)
+ , m_swapInterval(-1)
+ , m_swapIntervalEnvChecked(false)
+ , m_swapIntervalFromEnv(-1)
{
init(format, share);
Q_UNUSED(eglApi);
@@ -106,11 +131,8 @@ void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLCont
bool QEGLPlatformContext::makeCurrent(QPlatformSurface *surface)
{
- Q_ASSERT(surface->surface()->surfaceType() == QSurface::OpenGLSurface);
+ Q_ASSERT(surface->surface()->supportsOpenGL());
-#ifdef QEGL_EXTRA_DEBUG
- qWarning("QEglContext::makeCurrent: %p\n",this);
-#endif
bindApi(m_format);
EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface);
@@ -145,14 +167,32 @@ bool QEGLPlatformContext::makeCurrent(QPlatformSurface *surface)
}
#endif
+
+ if (ok) {
+ if (!m_swapIntervalEnvChecked) {
+ m_swapIntervalEnvChecked = true;
+ if (qEnvironmentVariableIsSet("QT_QPA_EGLFS_SWAPINTERVAL")) {
+ QByteArray swapIntervalString = qgetenv("QT_QPA_EGLFS_SWAPINTERVAL");
+ bool ok;
+ const int swapInterval = swapIntervalString.toInt(&ok);
+ if (ok)
+ m_swapIntervalFromEnv = swapInterval;
+ }
+ }
+ const int requestedSwapInterval = m_swapIntervalFromEnv >= 0
+ ? m_swapIntervalFromEnv
+ : surface->format().swapInterval();
+ if (requestedSwapInterval >= 0 && m_swapInterval != requestedSwapInterval) {
+ m_swapInterval = requestedSwapInterval;
+ eglSwapInterval(eglDisplay(), m_swapInterval);
+ }
+ }
+
return ok;
}
QEGLPlatformContext::~QEGLPlatformContext()
{
-#ifdef QEGL_EXTRA_DEBUG
- qWarning("QEglContext::~QEglContext(): %p\n",this);
-#endif
if (m_eglContext != EGL_NO_CONTEXT) {
eglDestroyContext(m_eglDisplay, m_eglContext);
m_eglContext = EGL_NO_CONTEXT;
@@ -161,9 +201,6 @@ QEGLPlatformContext::~QEGLPlatformContext()
void QEGLPlatformContext::doneCurrent()
{
-#ifdef QEGL_EXTRA_DEBUG
- qWarning("QEglContext::doneCurrent:%p\n",this);
-#endif
bindApi(m_format);
bool ok = eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (!ok)
@@ -172,9 +209,6 @@ void QEGLPlatformContext::doneCurrent()
void QEGLPlatformContext::swapBuffers(QPlatformSurface *surface)
{
-#ifdef QEGL_EXTRA_DEBUG
- qWarning("QEglContext::swapBuffers:%p\n",this);
-#endif
bindApi(m_format);
EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface);
bool ok = eglSwapBuffers(m_eglDisplay, eglSurface);
@@ -184,9 +218,6 @@ void QEGLPlatformContext::swapBuffers(QPlatformSurface *surface)
void (*QEGLPlatformContext::getProcAddress(const QByteArray &procName)) ()
{
-#ifdef QEGL_EXTRA_DEBUG
- qWarning("QEglContext::getProcAddress%p\n",this);
-#endif
bindApi(m_format);
return eglGetProcAddress(procName.constData());
}
@@ -210,3 +241,5 @@ EGLConfig QEGLPlatformContext::eglConfig() const
{
return m_eglConfig;
}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h
index 7c05894246..d62082faa2 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h
+++ b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h
@@ -46,6 +46,8 @@
#include <qpa/qplatformopenglcontext.h>
#include <EGL/egl.h>
+QT_BEGIN_NAMESPACE
+
class QEGLPlatformContext : public QPlatformOpenGLContext
{
public:
@@ -79,6 +81,11 @@ private:
EGLDisplay m_eglDisplay;
EGLConfig m_eglConfig;
QSurfaceFormat m_format;
+ int m_swapInterval;
+ bool m_swapIntervalEnvChecked;
+ int m_swapIntervalFromEnv;
};
+QT_END_NAMESPACE
+
#endif //QEGLPLATFORMCONTEXT_H
diff --git a/src/platformsupport/eglconvenience/qeglplatformcursor.cpp b/src/platformsupport/eglconvenience/qeglplatformcursor.cpp
new file mode 100644
index 0000000000..1c87e1d27d
--- /dev/null
+++ b/src/platformsupport/eglconvenience/qeglplatformcursor.cpp
@@ -0,0 +1,391 @@
+/****************************************************************************
+**
+** 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 <qpa/qwindowsysteminterface.h>
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLShaderProgram>
+#include <QtCore/QJsonDocument>
+#include <QtCore/QJsonArray>
+#include <QtCore/QJsonObject>
+#include <QtDebug>
+
+#include <QtPlatformSupport/private/qdevicediscovery_p.h>
+
+#include "qeglplatformcursor_p.h"
+#include "qeglplatformintegration_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QEGLPlatformCursor
+ \brief Mouse cursor implementation using OpenGL.
+ \since 5.2
+ \internal
+ \ingroup qpa
+ */
+
+QEGLPlatformCursor::QEGLPlatformCursor(QPlatformScreen *screen)
+ : m_visible(true),
+ m_screen(screen),
+ m_program(0),
+ m_vertexCoordEntry(0),
+ m_textureCoordEntry(0),
+ m_textureEntry(0),
+ m_deviceListener(0)
+{
+ QByteArray hideCursorVal = qgetenv("QT_QPA_EGLFS_HIDECURSOR");
+ if (!hideCursorVal.isEmpty())
+ m_visible = hideCursorVal.toInt() == 0;
+ if (!m_visible)
+ return;
+
+ // Try to load the cursor atlas. If this fails, m_visible is set to false and
+ // paintOnScreen() and setCurrentCursor() become no-ops.
+ initCursorAtlas();
+
+ // initialize the cursor
+#ifndef QT_NO_CURSOR
+ QCursor cursor(Qt::ArrowCursor);
+ setCurrentCursor(&cursor);
+#endif
+}
+
+QEGLPlatformCursor::~QEGLPlatformCursor()
+{
+ resetResources();
+ delete m_deviceListener;
+}
+
+void QEGLPlatformCursor::setMouseDeviceDiscovery(QDeviceDiscovery *dd)
+{
+ if (m_visible && dd) {
+ m_deviceListener = new QEGLPlatformCursorDeviceListener(dd, this);
+ updateMouseStatus();
+ }
+}
+
+void QEGLPlatformCursor::updateMouseStatus()
+{
+ m_visible = m_deviceListener->hasMouse();
+}
+
+QEGLPlatformCursorDeviceListener::QEGLPlatformCursorDeviceListener(QDeviceDiscovery *dd, QEGLPlatformCursor *cursor)
+ : m_cursor(cursor)
+{
+ m_mouseCount = dd->scanConnectedDevices().count();
+ connect(dd, SIGNAL(deviceDetected(QString)), SLOT(onDeviceAdded()));
+ connect(dd, SIGNAL(deviceRemoved(QString)), SLOT(onDeviceRemoved()));
+}
+
+bool QEGLPlatformCursorDeviceListener::hasMouse() const
+{
+ return m_mouseCount > 0;
+}
+
+void QEGLPlatformCursorDeviceListener::onDeviceAdded()
+{
+ ++m_mouseCount;
+ m_cursor->updateMouseStatus();
+}
+
+void QEGLPlatformCursorDeviceListener::onDeviceRemoved()
+{
+ --m_mouseCount;
+ m_cursor->updateMouseStatus();
+}
+
+void QEGLPlatformCursor::resetResources()
+{
+ if (QOpenGLContext::currentContext()) {
+ delete m_program;
+ glDeleteTextures(1, &m_cursor.customCursorTexture);
+ glDeleteTextures(1, &m_cursorAtlas.texture);
+ }
+ m_program = 0;
+ m_cursor.customCursorTexture = 0;
+ m_cursor.customCursorPending = !m_cursor.customCursorImage.isNull();
+ m_cursorAtlas.texture = 0;
+}
+
+void QEGLPlatformCursor::createShaderPrograms()
+{
+ static const char *textureVertexProgram =
+ "attribute highp vec2 vertexCoordEntry;\n"
+ "attribute highp vec2 textureCoordEntry;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main() {\n"
+ " textureCoord = textureCoordEntry;\n"
+ " gl_Position = vec4(vertexCoordEntry, 1.0, 1.0);\n"
+ "}\n";
+
+ static const char *textureFragmentProgram =
+ "uniform sampler2D texture;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main() {\n"
+ " gl_FragColor = texture2D(texture, textureCoord).bgra;\n"
+ "}\n";
+
+ m_program = new QOpenGLShaderProgram;
+ m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram);
+ m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram);
+ m_program->link();
+
+ m_vertexCoordEntry = m_program->attributeLocation("vertexCoordEntry");
+ m_textureCoordEntry = m_program->attributeLocation("textureCoordEntry");
+ m_textureEntry = m_program->attributeLocation("texture");
+}
+
+void QEGLPlatformCursor::createCursorTexture(uint *texture, const QImage &image)
+{
+ if (!*texture)
+ glGenTextures(1, texture);
+ glBindTexture(GL_TEXTURE_2D, *texture);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA, image.width(), image.height(), 0 /* border */,
+ GL_RGBA, GL_UNSIGNED_BYTE, image.constBits());
+}
+
+void QEGLPlatformCursor::initCursorAtlas()
+{
+ static QByteArray json = qgetenv("QT_QPA_EGLFS_CURSOR");
+ if (json.isEmpty())
+ json = ":/cursor.json";
+
+ QFile file(QString::fromUtf8(json));
+ if (!file.open(QFile::ReadOnly)) {
+ m_visible = false;
+ return;
+ }
+
+ QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
+ QJsonObject object = doc.object();
+
+ QString atlas = object.value(QLatin1String("image")).toString();
+ Q_ASSERT(!atlas.isEmpty());
+
+ const int cursorsPerRow = object.value(QLatin1String("cursorsPerRow")).toDouble();
+ Q_ASSERT(cursorsPerRow);
+ m_cursorAtlas.cursorsPerRow = cursorsPerRow;
+
+ const QJsonArray hotSpots = object.value(QLatin1String("hotSpots")).toArray();
+ Q_ASSERT(hotSpots.count() == Qt::LastCursor);
+ for (int i = 0; i < hotSpots.count(); i++) {
+ QPoint hotSpot(hotSpots[i].toArray()[0].toDouble(), hotSpots[i].toArray()[1].toDouble());
+ m_cursorAtlas.hotSpots << hotSpot;
+ }
+
+ QImage image = QImage(atlas).convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ m_cursorAtlas.cursorWidth = image.width() / m_cursorAtlas.cursorsPerRow;
+ m_cursorAtlas.cursorHeight = image.height() / ((Qt::LastCursor + cursorsPerRow - 1) / cursorsPerRow);
+ m_cursorAtlas.width = image.width();
+ m_cursorAtlas.height = image.height();
+ m_cursorAtlas.image = image;
+}
+
+#ifndef QT_NO_CURSOR
+void QEGLPlatformCursor::changeCursor(QCursor *cursor, QWindow *window)
+{
+ Q_UNUSED(window);
+ const QRect oldCursorRect = cursorRect();
+ if (setCurrentCursor(cursor))
+ update(oldCursorRect | cursorRect());
+}
+
+bool QEGLPlatformCursor::setCurrentCursor(QCursor *cursor)
+{
+ if (!m_visible)
+ return false;
+
+ const Qt::CursorShape newShape = cursor ? cursor->shape() : Qt::ArrowCursor;
+ if (m_cursor.shape == newShape && newShape != Qt::BitmapCursor)
+ return false;
+
+ if (m_cursor.shape == Qt::BitmapCursor) {
+ m_cursor.customCursorImage = QImage();
+ m_cursor.customCursorPending = false;
+ }
+ m_cursor.shape = newShape;
+ if (newShape != Qt::BitmapCursor) { // standard cursor
+ const float ws = (float)m_cursorAtlas.cursorWidth / m_cursorAtlas.width,
+ hs = (float)m_cursorAtlas.cursorHeight / m_cursorAtlas.height;
+ m_cursor.textureRect = QRectF(ws * (m_cursor.shape % m_cursorAtlas.cursorsPerRow),
+ hs * (m_cursor.shape / m_cursorAtlas.cursorsPerRow),
+ ws, hs);
+ m_cursor.hotSpot = m_cursorAtlas.hotSpots[m_cursor.shape];
+ m_cursor.texture = m_cursorAtlas.texture;
+ m_cursor.size = QSize(m_cursorAtlas.cursorWidth, m_cursorAtlas.cursorHeight);
+ } else {
+ QImage image = cursor->pixmap().toImage();
+ m_cursor.textureRect = QRectF(0, 0, 1, 1);
+ m_cursor.hotSpot = cursor->hotSpot();
+ m_cursor.texture = 0; // will get updated in the next render()
+ m_cursor.size = image.size();
+ m_cursor.customCursorImage = image;
+ m_cursor.customCursorPending = true;
+ }
+
+ return true;
+}
+#endif
+
+void QEGLPlatformCursor::update(const QRegion &rgn)
+{
+ QWindowSystemInterface::handleExposeEvent(m_screen->topLevelAt(m_cursor.pos), rgn);
+ QWindowSystemInterface::flushWindowSystemEvents();
+}
+
+QRect QEGLPlatformCursor::cursorRect() const
+{
+ return QRect(m_cursor.pos - m_cursor.hotSpot, m_cursor.size);
+}
+
+QPoint QEGLPlatformCursor::pos() const
+{
+ return m_cursor.pos;
+}
+
+void QEGLPlatformCursor::setPos(const QPoint &pos)
+{
+ const QRect oldCursorRect = cursorRect();
+ m_cursor.pos = pos;
+ update(oldCursorRect | cursorRect());
+}
+
+void QEGLPlatformCursor::pointerEvent(const QMouseEvent &event)
+{
+ if (event.type() != QEvent::MouseMove)
+ return;
+ const QRect oldCursorRect = cursorRect();
+ m_cursor.pos = event.screenPos().toPoint();
+ update(oldCursorRect | cursorRect());
+}
+
+void QEGLPlatformCursor::paintOnScreen()
+{
+ if (!m_visible)
+ return;
+
+ const QRectF cr = cursorRect();
+ const QRect screenRect(m_screen->geometry());
+ const GLfloat x1 = 2 * (cr.left() / screenRect.width()) - 1;
+ const GLfloat x2 = 2 * (cr.right() / screenRect.width()) - 1;
+ const GLfloat y1 = 1 - (cr.top() / screenRect.height()) * 2;
+ const GLfloat y2 = 1 - (cr.bottom() / screenRect.height()) * 2;
+ QRectF r(QPointF(x1, y1), QPointF(x2, y2));
+
+ draw(r);
+}
+
+void QEGLPlatformCursor::draw(const QRectF &r)
+{
+ if (!m_program) {
+ // one time initialization
+ createShaderPrograms();
+
+ if (!m_cursorAtlas.texture) {
+ createCursorTexture(&m_cursorAtlas.texture, m_cursorAtlas.image);
+
+ if (m_cursor.shape != Qt::BitmapCursor)
+ m_cursor.texture = m_cursorAtlas.texture;
+ }
+ }
+
+ if (m_cursor.shape == Qt::BitmapCursor && m_cursor.customCursorPending) {
+ // upload the custom cursor
+ createCursorTexture(&m_cursor.customCursorTexture, m_cursor.customCursorImage);
+ m_cursor.texture = m_cursor.customCursorTexture;
+ m_cursor.customCursorPending = false;
+ }
+
+ Q_ASSERT(m_cursor.texture);
+
+ m_program->bind();
+
+ const GLfloat x1 = r.left();
+ const GLfloat x2 = r.right();
+ const GLfloat y1 = r.top();
+ const GLfloat y2 = r.bottom();
+ const GLfloat cursorCoordinates[] = {
+ x1, y2,
+ x2, y2,
+ x1, y1,
+ x2, y1
+ };
+
+ const GLfloat s1 = m_cursor.textureRect.left();
+ const GLfloat s2 = m_cursor.textureRect.right();
+ const GLfloat t1 = m_cursor.textureRect.top();
+ const GLfloat t2 = m_cursor.textureRect.bottom();
+ const GLfloat textureCoordinates[] = {
+ s1, t2,
+ s2, t2,
+ s1, t1,
+ s2, t1
+ };
+
+ glBindTexture(GL_TEXTURE_2D, m_cursor.texture);
+
+ m_program->enableAttributeArray(m_vertexCoordEntry);
+ m_program->enableAttributeArray(m_textureCoordEntry);
+
+ m_program->setAttributeArray(m_vertexCoordEntry, cursorCoordinates, 2);
+ m_program->setAttributeArray(m_textureCoordEntry, textureCoordinates, 2);
+
+ m_program->setUniformValue(m_textureEntry, 0);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_DEPTH_TEST); // disable depth testing to make sure cursor is always on top
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ glDisable(GL_BLEND);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ m_program->disableAttributeArray(m_textureCoordEntry);
+ m_program->disableAttributeArray(m_vertexCoordEntry);
+
+ m_program->release();
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/eglconvenience/qeglplatformcursor_p.h b/src/platformsupport/eglconvenience/qeglplatformcursor_p.h
new file mode 100644
index 0000000000..d1402d1457
--- /dev/null
+++ b/src/platformsupport/eglconvenience/qeglplatformcursor_p.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** 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 QEGLPLATFORMCURSOR_H
+#define QEGLPLATFORMCURSOR_H
+
+#include <qpa/qplatformcursor.h>
+#include <qpa/qplatformscreen.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLShaderProgram;
+class QDeviceDiscovery;
+class QEGLPlatformCursor;
+
+class QEGLPlatformCursorDeviceListener : public QObject
+{
+ Q_OBJECT
+
+public:
+ QEGLPlatformCursorDeviceListener(QDeviceDiscovery *dd, QEGLPlatformCursor *cursor);
+ bool hasMouse() const;
+
+private slots:
+ void onDeviceAdded();
+ void onDeviceRemoved();
+
+private:
+ QEGLPlatformCursor *m_cursor;
+ int m_mouseCount;
+};
+
+class QEGLPlatformCursor : public QPlatformCursor
+{
+public:
+ QEGLPlatformCursor(QPlatformScreen *screen);
+ ~QEGLPlatformCursor();
+
+#ifndef QT_NO_CURSOR
+ void changeCursor(QCursor *cursor, QWindow *widget) Q_DECL_OVERRIDE;
+#endif
+ void pointerEvent(const QMouseEvent &event) Q_DECL_OVERRIDE;
+ QPoint pos() const Q_DECL_OVERRIDE;
+ void setPos(const QPoint &pos) Q_DECL_OVERRIDE;
+
+ QRect cursorRect() const;
+ void paintOnScreen();
+ void resetResources();
+
+ void setMouseDeviceDiscovery(QDeviceDiscovery *dd);
+ void updateMouseStatus();
+
+private:
+#ifndef QT_NO_CURSOR
+ bool setCurrentCursor(QCursor *cursor);
+#endif
+ void draw(const QRectF &rect);
+ void update(const QRegion &region);
+ void createShaderPrograms();
+ static void createCursorTexture(uint *texture, const QImage &image);
+ void initCursorAtlas();
+
+ // current cursor information
+ struct Cursor {
+ Cursor() : texture(0), shape(Qt::BlankCursor), customCursorTexture(0), customCursorPending(false) { }
+ uint texture; // a texture from 'image' or the atlas
+ Qt::CursorShape shape;
+ QRectF textureRect; // normalized rect inside texture
+ QSize size; // size of the cursor
+ QPoint hotSpot;
+ QImage customCursorImage;
+ QPoint pos; // current cursor position
+ uint customCursorTexture;
+ bool customCursorPending;
+ } m_cursor;
+
+ // cursor atlas information
+ struct CursorAtlas {
+ CursorAtlas() : cursorsPerRow(0), texture(0), cursorWidth(0), cursorHeight(0) { }
+ int cursorsPerRow;
+ uint texture;
+ int width, height; // width and height of the the atlas
+ int cursorWidth, cursorHeight; // width and height of cursors inside the atlas
+ QList<QPoint> hotSpots;
+ QImage image; // valid until it's uploaded
+ } m_cursorAtlas;
+
+ bool m_visible;
+ QPlatformScreen *m_screen;
+ QOpenGLShaderProgram *m_program;
+ int m_vertexCoordEntry;
+ int m_textureCoordEntry;
+ int m_textureEntry;
+ QEGLPlatformCursorDeviceListener *m_deviceListener;
+};
+
+QT_END_NAMESPACE
+
+#endif // QEGLPLATFORMCURSOR_H
diff --git a/src/platformsupport/eglconvenience/qeglplatformintegration.cpp b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp
new file mode 100644
index 0000000000..a961035e22
--- /dev/null
+++ b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp
@@ -0,0 +1,299 @@
+/****************************************************************************
+**
+** 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/QWindow>
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOffscreenSurface>
+#include <QtGui/QGuiApplication>
+#include <qpa/qwindowsysteminterface.h>
+#include <qpa/qplatforminputcontextfactory_p.h>
+
+#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
+#include <QtPlatformSupport/private/qgenericunixservices_p.h>
+#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
+#include <QtPlatformSupport/private/qfbvthandler_p.h>
+
+#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
+#include <QtPlatformSupport/private/qevdevmousemanager_p.h>
+#include <QtPlatformSupport/private/qevdevkeyboardmanager_p.h>
+#include <QtPlatformSupport/private/qevdevtouch_p.h>
+#endif
+
+#include "qeglplatformintegration_p.h"
+#include "qeglplatformcontext_p.h"
+#include "qeglplatformwindow_p.h"
+#include "qeglplatformbackingstore_p.h"
+#include "qeglplatformscreen_p.h"
+#include "qeglplatformcursor_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QEGLPlatformIntegration
+ \brief Base class for EGL-based QPlatformIntegration implementations.
+ \since 5.2
+ \internal
+ \ingroup qpa
+
+ This class provides most of the necessary platform integration for
+ an EGL-based Unix system. Platform plugins must subclass this and
+ reimplement the virtuals for creating platform screens and windows
+ since they will most likely wish to use a subclass for these.
+
+ The backing store, native interface accessors, font database,
+ basic capability flags, etc. are provided out of the box, no
+ further customization is needed.
+
+ \note It is critical that this class' implementation of
+ initialize() is called. Therefore subclasses should either avoid
+ to reimplement this function or call the base class
+ implementation.
+ */
+
+QEGLPlatformIntegration::QEGLPlatformIntegration()
+ : m_screen(0),
+ m_display(EGL_NO_DISPLAY),
+ m_inputContext(0),
+ m_fontDb(new QGenericUnixFontDatabase),
+ m_services(new QGenericUnixServices)
+{
+}
+
+QEGLPlatformIntegration::~QEGLPlatformIntegration()
+{
+ delete m_screen;
+ if (m_display != EGL_NO_DISPLAY)
+ eglTerminate(m_display);
+}
+
+void QEGLPlatformIntegration::initialize()
+{
+ if (!eglBindAPI(EGL_OPENGL_ES_API))
+ qFatal("Could not bind GL_ES API");
+
+ m_display = eglGetDisplay(nativeDisplay());
+ if (m_display == EGL_NO_DISPLAY)
+ qFatal("Could not open egl display");
+
+ EGLint major, minor;
+ if (!eglInitialize(m_display, &major, &minor))
+ qFatal("Could not initialize egl display");
+
+ m_screen = createScreen();
+ screenAdded(m_screen);
+
+ m_inputContext = QPlatformInputContextFactory::create();
+
+ m_vtHandler.reset(new QFbVtHandler);
+}
+
+QAbstractEventDispatcher *QEGLPlatformIntegration::createEventDispatcher() const
+{
+ return createUnixEventDispatcher();
+}
+
+QPlatformServices *QEGLPlatformIntegration::services() const
+{
+ return m_services.data();
+}
+
+QPlatformFontDatabase *QEGLPlatformIntegration::fontDatabase() const
+{
+ return m_fontDb.data();
+}
+
+QPlatformBackingStore *QEGLPlatformIntegration::createPlatformBackingStore(QWindow *window) const
+{
+ return new QEGLPlatformBackingStore(window);
+}
+
+QPlatformWindow *QEGLPlatformIntegration::createPlatformWindow(QWindow *window) const
+{
+ QWindowSystemInterface::flushWindowSystemEvents();
+ QEGLPlatformWindow *w = createWindow(window);
+ w->create();
+ if (window->type() != Qt::ToolTip)
+ w->requestActivateWindow();
+ return w;
+}
+
+QPlatformOpenGLContext *QEGLPlatformIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
+{
+ QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(context->screen()->handle());
+ // If there is a "root" window into which raster and QOpenGLWidget content is
+ // composited, all other contexts must share with its context.
+ QOpenGLContext *compositingContext = screen ? screen->compositingContext() : 0;
+ return createContext(context->format(),
+ compositingContext ? compositingContext->handle() : context->shareHandle(),
+ display());
+}
+
+QPlatformOffscreenSurface *QEGLPlatformIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
+{
+ QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(surface->screen()->handle());
+ return createOffscreenSurface(screen->display(), surface->requestedFormat(), surface);
+}
+
+bool QEGLPlatformIntegration::hasCapability(QPlatformIntegration::Capability cap) const
+{
+ switch (cap) {
+ case ThreadedPixmaps: return true;
+ case OpenGL: return true;
+ case ThreadedOpenGL: return true;
+ case WindowManagement: return false;
+ case RasterGLSurface: return true;
+ default: return QPlatformIntegration::hasCapability(cap);
+ }
+}
+
+QPlatformNativeInterface *QEGLPlatformIntegration::nativeInterface() const
+{
+ return const_cast<QEGLPlatformIntegration *>(this);
+}
+
+enum ResourceType {
+ EglDisplay,
+ EglWindow,
+ EglContext
+};
+
+static int resourceType(const QByteArray &key)
+{
+ static const QByteArray names[] = { // match ResourceType
+ QByteArrayLiteral("egldisplay"),
+ QByteArrayLiteral("eglwindow"),
+ QByteArrayLiteral("eglcontext")
+ };
+ const QByteArray *end = names + sizeof(names) / sizeof(names[0]);
+ const QByteArray *result = std::find(names, end, key);
+ if (result == end)
+ result = std::find(names, end, key.toLower());
+ return int(result - names);
+}
+
+void *QEGLPlatformIntegration::nativeResourceForIntegration(const QByteArray &resource)
+{
+ void *result = 0;
+
+ switch (resourceType(resource)) {
+ case EglDisplay:
+ result = m_screen->display();
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+void *QEGLPlatformIntegration::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
+{
+ void *result = 0;
+
+ switch (resourceType(resource)) {
+ case EglDisplay:
+ if (window && window->handle())
+ result = static_cast<QEGLPlatformScreen *>(window->handle()->screen())->display();
+ else
+ result = m_screen->display();
+ break;
+ case EglWindow:
+ if (window && window->handle())
+ result = reinterpret_cast<void*>(static_cast<QEGLPlatformWindow *>(window->handle())->eglWindow());
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+void *QEGLPlatformIntegration::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context)
+{
+ void *result = 0;
+
+ switch (resourceType(resource)) {
+ case EglContext:
+ if (context->handle())
+ result = static_cast<QEGLPlatformContext *>(context->handle())->eglContext();
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+static void *eglContextForContext(QOpenGLContext *context)
+{
+ Q_ASSERT(context);
+
+ QEGLPlatformContext *handle = static_cast<QEGLPlatformContext *>(context->handle());
+ if (!handle)
+ return 0;
+
+ return handle->eglContext();
+}
+
+QPlatformNativeInterface::NativeResourceForContextFunction QEGLPlatformIntegration::nativeResourceFunctionForContext(const QByteArray &resource)
+{
+ QByteArray lowerCaseResource = resource.toLower();
+ if (lowerCaseResource == "get_egl_context")
+ return NativeResourceForContextFunction(eglContextForContext);
+
+ return 0;
+}
+
+void QEGLPlatformIntegration::createInputHandlers()
+{
+#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
+ new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString() /* spec */, this);
+ QEvdevMouseManager *mouseMgr = new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString() /* spec */, this);
+ Q_FOREACH (QScreen *screen, QGuiApplication::screens()) {
+ QEGLPlatformCursor *cursor = static_cast<QEGLPlatformCursor *>(screen->handle()->cursor());
+ if (cursor)
+ cursor->setMouseDeviceDiscovery(mouseMgr->deviceDiscovery());
+ }
+ new QEvdevTouchScreenHandlerThread(QString() /* spec */, this);
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/eglconvenience/qeglplatformintegration_p.h b/src/platformsupport/eglconvenience/qeglplatformintegration_p.h
new file mode 100644
index 0000000000..f665455383
--- /dev/null
+++ b/src/platformsupport/eglconvenience/qeglplatformintegration_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** 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 QEGLPLATFORMINTEGRATION_H
+#define QEGLPLATFORMINTEGRATION_H
+
+#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformnativeinterface.h>
+#include <EGL/egl.h>
+
+QT_BEGIN_NAMESPACE
+
+class QEGLPlatformScreen;
+class QEGLPlatformWindow;
+class QEGLPlatformContext;
+class QFbVtHandler;
+
+class QEGLPlatformIntegration : public QPlatformIntegration, public QPlatformNativeInterface
+{
+public:
+ QEGLPlatformIntegration();
+ ~QEGLPlatformIntegration();
+
+ void initialize() Q_DECL_OVERRIDE;
+
+ QEGLPlatformScreen *screen() const { return m_screen; }
+ EGLDisplay display() const { return m_display; }
+
+ QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
+ QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
+ QPlatformServices *services() const Q_DECL_OVERRIDE;
+ QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE { return m_inputContext; }
+
+ QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
+ QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
+ QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE;
+
+ bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
+
+ QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE;
+ // QPlatformNativeInterface
+ void *nativeResourceForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE;
+ void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) Q_DECL_OVERRIDE;
+ void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) Q_DECL_OVERRIDE;
+ NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource) Q_DECL_OVERRIDE;
+
+protected:
+ virtual QEGLPlatformScreen *createScreen() const = 0;
+ virtual QEGLPlatformWindow *createWindow(QWindow *window) const = 0;
+ virtual QEGLPlatformContext *createContext(const QSurfaceFormat &format,
+ QPlatformOpenGLContext *shareContext,
+ EGLDisplay display) const = 0;
+ virtual QPlatformOffscreenSurface *createOffscreenSurface(EGLDisplay display,
+ const QSurfaceFormat &format,
+ QOffscreenSurface *surface) const = 0;
+
+ virtual EGLNativeDisplayType nativeDisplay() const { return EGL_DEFAULT_DISPLAY; }
+
+ void createInputHandlers();
+
+private:
+ QEGLPlatformScreen *m_screen;
+ EGLDisplay m_display;
+ QPlatformInputContext *m_inputContext;
+ QScopedPointer<QPlatformFontDatabase> m_fontDb;
+ QScopedPointer<QPlatformServices> m_services;
+ QScopedPointer<QFbVtHandler> m_vtHandler;
+};
+
+QT_END_NAMESPACE
+
+#endif // QEGLPLATFORMINTEGRATION_H
diff --git a/src/platformsupport/eglconvenience/qeglplatformscreen.cpp b/src/platformsupport/eglconvenience/qeglplatformscreen.cpp
new file mode 100644
index 0000000000..72e7f6a6df
--- /dev/null
+++ b/src/platformsupport/eglconvenience/qeglplatformscreen.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** 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 "qeglcompositor_p.h"
+#include "qeglplatformscreen_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QEGLPlatformScreen
+ \brief Base class for EGL-based platform screen implementations.
+ \since 5.2
+ \internal
+ \ingroup qpa
+
+ This class provides a lightweight base for QPlatformScreen
+ implementations. It covers basic window stack management which is
+ necessary when compositing multiple raster (widget-based) windows
+ together into one single native surface.
+
+ Reimplementing the virtuals are essential when using
+ QEGLPlatformBackingStore. The context and the window returned from
+ these are the ones that are used when compositing the textures
+ generated from the raster (widget) based windows.
+
+ \note It is up to the QEGLPlatformWindow subclasses to use the
+ functions, like addWindow(), removeWindow(), etc., provided here.
+ */
+
+QEGLPlatformScreen::QEGLPlatformScreen(EGLDisplay dpy)
+ : m_dpy(dpy)
+{
+}
+
+QEGLPlatformScreen::~QEGLPlatformScreen()
+{
+ QEGLCompositor::destroy();
+}
+
+void QEGLPlatformScreen::addWindow(QEGLPlatformWindow *window)
+{
+ if (!m_windows.contains(window)) {
+ m_windows.append(window);
+ topWindowChanged(window);
+ }
+}
+
+void QEGLPlatformScreen::removeWindow(QEGLPlatformWindow *window)
+{
+ m_windows.removeOne(window);
+ if (!m_windows.isEmpty())
+ topWindowChanged(m_windows.last());
+}
+
+void QEGLPlatformScreen::moveToTop(QEGLPlatformWindow *window)
+{
+ m_windows.removeOne(window);
+ m_windows.append(window);
+ topWindowChanged(window);
+}
+
+void QEGLPlatformScreen::changeWindowIndex(QEGLPlatformWindow *window, int newIdx)
+{
+ int idx = m_windows.indexOf(window);
+ if (idx != -1 && idx != newIdx) {
+ m_windows.move(idx, newIdx);
+ if (newIdx == m_windows.size() - 1)
+ topWindowChanged(m_windows.last());
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/eglconvenience/qeglplatformscreen_p.h b/src/platformsupport/eglconvenience/qeglplatformscreen_p.h
new file mode 100644
index 0000000000..d0d8a52a87
--- /dev/null
+++ b/src/platformsupport/eglconvenience/qeglplatformscreen_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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 QEGLPLATFORMSCREEN_H
+#define QEGLPLATFORMSCREEN_H
+
+#include <QtCore/QList>
+#include <qpa/qplatformscreen.h>
+#include <EGL/egl.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLContext;
+class QEGLPlatformWindow;
+
+class QEGLPlatformScreen : public QPlatformScreen
+{
+public:
+ QEGLPlatformScreen(EGLDisplay dpy);
+ ~QEGLPlatformScreen();
+
+ QList<QEGLPlatformWindow *> windows() const { return m_windows; }
+
+ void addWindow(QEGLPlatformWindow *window);
+ void removeWindow(QEGLPlatformWindow *window);
+ void moveToTop(QEGLPlatformWindow *window);
+ void changeWindowIndex(QEGLPlatformWindow *window, int newIdx);
+
+ virtual void topWindowChanged(QEGLPlatformWindow *window) { Q_UNUSED(window); }
+
+ EGLDisplay display() const { return m_dpy; }
+
+ virtual QEGLPlatformWindow *compositingWindow() = 0;
+ virtual QOpenGLContext *compositingContext() = 0;
+
+private:
+ QList<QEGLPlatformWindow *> m_windows;
+ EGLDisplay m_dpy;
+};
+
+QT_END_NAMESPACE
+
+#endif // QEGLPLATFORMSCREEN_H
diff --git a/src/platformsupport/eglconvenience/qeglplatformwindow.cpp b/src/platformsupport/eglconvenience/qeglplatformwindow.cpp
new file mode 100644
index 0000000000..e9b79512ba
--- /dev/null
+++ b/src/platformsupport/eglconvenience/qeglplatformwindow.cpp
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** 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 <qpa/qwindowsysteminterface.h>
+
+#include "qeglplatformwindow_p.h"
+#include "qeglplatformbackingstore_p.h"
+#include "qeglplatformscreen_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QEGLPlatformWindow
+ \brief Base class for EGL-based platform window implementations.
+ \since 5.2
+ \internal
+ \ingroup qpa
+
+ Lightweight class providing some basic platform window operations
+ and interfacing with QEGLPlatformBackingStore.
+
+ Almost no QPlatformWindow functions are implemented here. This is
+ intentional because different platform plugins may use different
+ strategies for their window management (some may force fullscreen
+ windows, some may not, some may share the underlying native
+ surface, some may not, etc.) and therefore it is not sensible to
+ enforce anything for these functions.
+
+ \note Subclasses are responsible for invoking this class'
+ implementation of create(). When using QEGLPlatformScreen, the
+ subclasses of this class are expected to utilize the window stack
+ management functions (addWindow() etc.) provided there.
+ */
+
+QEGLPlatformWindow::QEGLPlatformWindow(QWindow *w)
+ : QPlatformWindow(w),
+ m_winId(0)
+{
+}
+
+static WId newWId()
+{
+ static WId id = 0;
+
+ if (id == std::numeric_limits<WId>::max())
+ qWarning("QEGLPlatformWindow: Out of window IDs");
+
+ return ++id;
+}
+
+void QEGLPlatformWindow::create()
+{
+ m_winId = newWId();
+
+ // Save the original surface type before changing to OpenGLSurface.
+ m_raster = (window()->surfaceType() == QSurface::RasterSurface);
+ if (m_raster) // change to OpenGL, but not for RasterGLSurface
+ window()->setSurfaceType(QSurface::OpenGLSurface);
+
+ if (window()->type() == Qt::Desktop) {
+ QRect fullscreenRect(QPoint(), screen()->availableGeometry().size());
+ QPlatformWindow::setGeometry(fullscreenRect);
+ QWindowSystemInterface::handleGeometryChange(window(), fullscreenRect);
+ return;
+ }
+}
+
+bool QEGLPlatformWindow::isRaster() const
+{
+ return m_raster || window()->surfaceType() == QSurface::RasterGLSurface;
+}
+
+const QPlatformTextureList *QEGLPlatformWindow::textures() const
+{
+ if (m_backingStore)
+ return m_backingStore->textures();
+
+ return 0;
+}
+
+void QEGLPlatformWindow::composited()
+{
+ if (m_backingStore)
+ m_backingStore->composited();
+}
+
+WId QEGLPlatformWindow::winId() const
+{
+ return m_winId;
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/eglconvenience/qeglplatformwindow_p.h b/src/platformsupport/eglconvenience/qeglplatformwindow_p.h
new file mode 100644
index 0000000000..17a1d07a79
--- /dev/null
+++ b/src/platformsupport/eglconvenience/qeglplatformwindow_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** 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 QEGLPLATFORMWINDOW_H
+#define QEGLPLATFORMWINDOW_H
+
+#include <qpa/qplatformwindow.h>
+#include <EGL/egl.h>
+
+QT_BEGIN_NAMESPACE
+
+class QEGLPlatformBackingStore;
+class QPlatformTextureList;
+
+class QEGLPlatformWindow : public QPlatformWindow
+{
+public:
+ QEGLPlatformWindow(QWindow *w);
+
+ virtual void create();
+
+ QEGLPlatformBackingStore *backingStore() { return m_backingStore; }
+ void setBackingStore(QEGLPlatformBackingStore *backingStore) { m_backingStore = backingStore; }
+ const QPlatformTextureList *textures() const;
+ void composited();
+ bool isRaster() const;
+
+ WId winId() const Q_DECL_OVERRIDE;
+
+ virtual EGLNativeWindowType eglWindow() const = 0;
+
+private:
+ QEGLPlatformBackingStore *m_backingStore;
+ bool m_raster;
+ WId m_winId;
+};
+
+QT_END_NAMESPACE
+
+#endif // QEGLPLATFORMWINDOW_H
diff --git a/src/platformsupport/fbconvenience/fbconvenience.pri b/src/platformsupport/fbconvenience/fbconvenience.pri
index 6ccaa50af5..4634f57fb4 100644
--- a/src/platformsupport/fbconvenience/fbconvenience.pri
+++ b/src/platformsupport/fbconvenience/fbconvenience.pri
@@ -1,10 +1,11 @@
SOURCES += $$PWD/qfbscreen.cpp \
$$PWD/qfbbackingstore.cpp \
$$PWD/qfbwindow.cpp \
- $$PWD/qfbcursor.cpp
+ $$PWD/qfbcursor.cpp \
+ $$PWD/qfbvthandler.cpp
HEADERS += $$PWD/qfbscreen_p.h \
$$PWD/qfbbackingstore_p.h \
$$PWD/qfbwindow_p.h \
- $$PWD/qfbcursor_p.h
-
+ $$PWD/qfbcursor_p.h \
+ $$PWD/qfbvthandler_p.h
diff --git a/src/platformsupport/fbconvenience/qfbvthandler.cpp b/src/platformsupport/fbconvenience/qfbvthandler.cpp
new file mode 100644
index 0000000000..edfd13d9bf
--- /dev/null
+++ b/src/platformsupport/fbconvenience/qfbvthandler.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfbvthandler_p.h"
+#include <QtCore/private/qcrashhandler_p.h>
+#include <QtGui/private/qguiapplication_p.h>
+
+#if defined(Q_OS_LINUX) && !defined(QT_NO_EVDEV)
+#define HAS_VT
+#endif
+
+#ifdef HAS_VT
+
+#include <sys/ioctl.h>
+#include <linux/kd.h>
+
+#ifdef K_OFF
+#define KBD_OFF_MODE K_OFF
+#else
+#define KBD_OFF_MODE K_RAW
+#endif
+
+#endif // HAS_VT
+
+QT_BEGIN_NAMESPACE
+
+QFbVtHandler *QFbVtHandler::self = 0;
+
+QFbVtHandler::QFbVtHandler(QObject *parent)
+ : QObject(parent), m_tty(-1)
+{
+ Q_ASSERT(!self);
+ self = this;
+
+#ifdef HAS_VT
+ if (!isatty(0))
+ return;
+
+ m_tty = 0;
+ ::ioctl(m_tty, KDGKBMODE, &m_oldKbdMode);
+ if (!qgetenv("QT_QPA_ENABLE_TERMINAL_KEYBOARD").toInt()) {
+ ::ioctl(m_tty, KDSKBMODE, KBD_OFF_MODE);
+ QGuiApplicationPrivate *appd = QGuiApplicationPrivate::instance();
+ Q_ASSERT(appd);
+ QSegfaultHandler::initialize(appd->argv, appd->argc);
+ QSegfaultHandler::installCrashHandler(crashHandler);
+ }
+#endif
+}
+
+QFbVtHandler::~QFbVtHandler()
+{
+ self->cleanup();
+ self = 0;
+}
+
+void QFbVtHandler::cleanup()
+{
+ if (m_tty == -1)
+ return;
+
+#ifdef HAS_VT
+ ::ioctl(m_tty, KDSKBMODE, m_oldKbdMode);
+#endif
+}
+
+void QFbVtHandler::crashHandler()
+{
+ Q_ASSERT(self);
+ self->cleanup();
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/fbconvenience/qfbvthandler_p.h b/src/platformsupport/fbconvenience/qfbvthandler_p.h
new file mode 100644
index 0000000000..d98cd5a9d1
--- /dev/null
+++ b/src/platformsupport/fbconvenience/qfbvthandler_p.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFBVTHANDLER_H
+#define QFBVTHANDLER_H
+
+#include <QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QFbVtHandler : public QObject
+{
+ Q_OBJECT
+
+public:
+ QFbVtHandler(QObject *parent = 0);
+ ~QFbVtHandler();
+
+private:
+ void cleanup();
+ static void crashHandler();
+
+ static QFbVtHandler *self;
+ int m_tty;
+ int m_oldKbdMode;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp
index 33f3601b97..1ed5ede3e8 100644
--- a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp
+++ b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp
@@ -113,27 +113,18 @@ void QBasicFontDatabase::populateFontDatabase()
}
}
-QFontEngine *QBasicFontDatabase::fontEngine(const QFontDef &fontDef, QChar::Script script, void *usrPtr)
+QFontEngine *QBasicFontDatabase::fontEngine(const QFontDef &fontDef, void *usrPtr)
{
- QFontEngineFT *engine;
FontFile *fontfile = static_cast<FontFile *> (usrPtr);
QFontEngine::FaceId fid;
fid.filename = QFile::encodeName(fontfile->fileName);
fid.index = fontfile->indexValue;
- engine = new QFontEngineFT(fontDef);
bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias);
QFontEngineFT::GlyphFormat format = antialias? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono;
- if (!engine->init(fid,antialias,format)) {
- delete engine;
- engine = 0;
- return engine;
- }
- if (engine->invalid()) {
- delete engine;
- engine = 0;
- } else if (!engine->supportsScript(script)) {
- qWarning(" OpenType support missing for script %d", int(script));
+
+ QFontEngineFT *engine = new QFontEngineFT(fontDef);
+ if (!engine->init(fid, antialias, format) || engine->invalid()) {
delete engine;
engine = 0;
}
diff --git a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h
index 4d6fd2ceeb..45d7218ece 100644
--- a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h
+++ b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h
@@ -58,7 +58,7 @@ class QBasicFontDatabase : public QPlatformFontDatabase
{
public:
void populateFontDatabase();
- QFontEngine *fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle);
+ QFontEngine *fontEngine(const QFontDef &fontDef, void *handle);
QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference);
QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const;
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName);
diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
index 8c3ca2d229..8b16e7520a 100644
--- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
+++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
@@ -69,21 +69,52 @@ static inline bool requiresOpenType(int writingSystem)
|| writingSystem == QFontDatabase::Khmer || writingSystem == QFontDatabase::Nko);
}
-static int getFCWeight(int fc_weight)
+static inline int weightFromFcWeight(int fcweight)
{
- int qtweight = QFont::Black;
- if (fc_weight <= (FC_WEIGHT_LIGHT + FC_WEIGHT_REGULAR) / 2)
- qtweight = QFont::Light;
- else if (fc_weight <= (FC_WEIGHT_REGULAR + FC_WEIGHT_MEDIUM) / 2)
- qtweight = QFont::Normal;
- else if (fc_weight <= (FC_WEIGHT_MEDIUM + FC_WEIGHT_BOLD) / 2)
- qtweight = QFont::DemiBold;
- else if (fc_weight <= (FC_WEIGHT_BOLD + FC_WEIGHT_BLACK) / 2)
- qtweight = QFont::Bold;
+ // Font Config uses weights from 0 to 215 (the highest enum value) while QFont ranges from
+ // 0 to 99. The spacing between the values for the enums are uneven so a linear mapping from
+ // Font Config values to Qt would give surprising results. So, we do a piecewise linear
+ // mapping. This ensures that where there is a corresponding enum on both sides (for example
+ // FC_WEIGHT_DEMIBOLD and QFont::DemiBold) we map one to the other but other values map
+ // to intermediate Qt weights.
+ const int maxWeight = 99;
+ int qtweight;
+ if (fcweight < 0)
+ qtweight = 0;
+ else if (fcweight <= FC_WEIGHT_LIGHT)
+ qtweight = (fcweight * QFont::Light) / FC_WEIGHT_LIGHT;
+ else if (fcweight <= FC_WEIGHT_NORMAL)
+ qtweight = QFont::Light + ((fcweight - FC_WEIGHT_LIGHT) * (QFont::Normal - QFont::Light)) / (FC_WEIGHT_NORMAL - FC_WEIGHT_LIGHT);
+ else if (fcweight <= FC_WEIGHT_DEMIBOLD)
+ qtweight = QFont::Normal + ((fcweight - FC_WEIGHT_NORMAL) * (QFont::DemiBold - QFont::Normal)) / (FC_WEIGHT_DEMIBOLD - FC_WEIGHT_NORMAL);
+ else if (fcweight <= FC_WEIGHT_BOLD)
+ qtweight = QFont::DemiBold + ((fcweight - FC_WEIGHT_DEMIBOLD) * (QFont::Bold - QFont::DemiBold)) / (FC_WEIGHT_BOLD - FC_WEIGHT_DEMIBOLD);
+ else if (fcweight <= FC_WEIGHT_BLACK)
+ qtweight = QFont::Bold + ((fcweight - FC_WEIGHT_BOLD) * (QFont::Black - QFont::Bold)) / (FC_WEIGHT_BLACK - FC_WEIGHT_BOLD);
+ else if (fcweight <= FC_WEIGHT_ULTRABLACK)
+ qtweight = QFont::Black + ((fcweight - FC_WEIGHT_BLACK) * (maxWeight - QFont::Black)) / (FC_WEIGHT_ULTRABLACK - FC_WEIGHT_BLACK);
+ else
+ qtweight = maxWeight;
return qtweight;
}
+static inline int stretchFromFcWidth(int fcwidth)
+{
+ // Font Config enums for width match pretty closely with those used by Qt so just use
+ // Font Config values directly while enforcing the same limits imposed by QFont.
+ const int maxStretch = 4000;
+ int qtstretch;
+ if (fcwidth < 1)
+ qtstretch = 1;
+ else if (fcwidth > maxStretch)
+ qtstretch = maxStretch;
+ else
+ qtstretch = fcwidth;
+
+ return qtstretch;
+}
+
static const char *specialLanguages[] = {
"", // Unknown
"", // Inherited
@@ -300,15 +331,14 @@ static const char *getFcFamilyForStyleHint(const QFont::StyleHint style)
return stylehint;
}
-void QFontconfigDatabase::populateFontDatabase()
+static void populateFromPattern(FcPattern *pattern)
{
- FcFontSet *fonts;
-
QString familyName;
FcChar8 *value = 0;
int weight_value;
int slant_value;
int spacing_value;
+ int width_value;
FcChar8 *file_value;
int indexValue;
FcChar8 *foundry_value;
@@ -316,13 +346,117 @@ void QFontconfigDatabase::populateFontDatabase()
FcBool scalable;
FcBool antialias;
+ if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) != FcResultMatch)
+ return;
+
+ familyName = QString::fromUtf8((const char *)value);
+
+ slant_value = FC_SLANT_ROMAN;
+ weight_value = FC_WEIGHT_REGULAR;
+ spacing_value = FC_PROPORTIONAL;
+ file_value = 0;
+ indexValue = 0;
+ scalable = FcTrue;
+
+
+ if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant_value) != FcResultMatch)
+ slant_value = FC_SLANT_ROMAN;
+ if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight_value) != FcResultMatch)
+ weight_value = FC_WEIGHT_REGULAR;
+ if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &width_value) != FcResultMatch)
+ width_value = FC_WIDTH_NORMAL;
+ if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing_value) != FcResultMatch)
+ spacing_value = FC_PROPORTIONAL;
+ if (FcPatternGetString(pattern, FC_FILE, 0, &file_value) != FcResultMatch)
+ file_value = 0;
+ if (FcPatternGetInteger(pattern, FC_INDEX, 0, &indexValue) != FcResultMatch)
+ indexValue = 0;
+ if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &scalable) != FcResultMatch)
+ scalable = FcTrue;
+ if (FcPatternGetString(pattern, FC_FOUNDRY, 0, &foundry_value) != FcResultMatch)
+ foundry_value = 0;
+ if (FcPatternGetString(pattern, FC_STYLE, 0, &style_value) != FcResultMatch)
+ style_value = 0;
+ if (FcPatternGetBool(pattern,FC_ANTIALIAS,0,&antialias) != FcResultMatch)
+ antialias = true;
+
+ QSupportedWritingSystems writingSystems;
+ FcLangSet *langset = 0;
+ FcResult res = FcPatternGetLangSet(pattern, FC_LANG, 0, &langset);
+ if (res == FcResultMatch) {
+ bool hasLang = false;
+ for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) {
+ const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[j];
+ if (lang) {
+ FcLangResult langRes = FcLangSetHasLang(langset, lang);
+ if (langRes != FcLangDifferentLang) {
+ writingSystems.setSupported(QFontDatabase::WritingSystem(j));
+ hasLang = true;
+ }
+ }
+ }
+ if (!hasLang)
+ // none of our known languages, add it to the other set
+ writingSystems.setSupported(QFontDatabase::Other);
+ } else {
+ // we set Other to supported for symbol fonts. It makes no
+ // sense to merge these with other ones, as they are
+ // special in a way.
+ writingSystems.setSupported(QFontDatabase::Other);
+ }
+
+#if FC_VERSION >= 20297
+ for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) {
+ if (writingSystems.supported(QFontDatabase::WritingSystem(j))
+ && requiresOpenType(j) && openType[j]) {
+ FcChar8 *cap;
+ res = FcPatternGetString (pattern, FC_CAPABILITY, 0, &cap);
+ if (res != FcResultMatch || !strstr((const char *)cap, openType[j]))
+ writingSystems.setSupported(QFontDatabase::WritingSystem(j),false);
+ }
+ }
+#endif
+
+ FontFile *fontFile = new FontFile;
+ fontFile->fileName = QLatin1String((const char *)file_value);
+ fontFile->indexValue = indexValue;
+
+ QFont::Style style = (slant_value == FC_SLANT_ITALIC)
+ ? QFont::StyleItalic
+ : ((slant_value == FC_SLANT_OBLIQUE)
+ ? QFont::StyleOblique
+ : QFont::StyleNormal);
+ // Note: weight should really be an int but registerFont incorrectly uses an enum
+ QFont::Weight weight = QFont::Weight(weightFromFcWeight(weight_value));
+
+ double pixel_size = 0;
+ if (!scalable)
+ FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &pixel_size);
+
+ bool fixedPitch = spacing_value >= FC_MONO;
+ // Note: stretch should really be an int but registerFont incorrectly uses an enum
+ QFont::Stretch stretch = QFont::Stretch(stretchFromFcWidth(width_value));
+ QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString();
+ QPlatformFontDatabase::registerFont(familyName,styleName,QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,fontFile);
+// qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size;
+
+ for (int k = 1; FcPatternGetString(pattern, FC_FAMILY, k, &value) == FcResultMatch; ++k)
+ QPlatformFontDatabase::registerAliasToFontFamily(familyName, QString::fromUtf8((const char *)value));
+
+}
+
+void QFontconfigDatabase::populateFontDatabase()
+{
+ FcInitReinitialize();
+ FcFontSet *fonts;
+
{
FcObjectSet *os = FcObjectSetCreate();
FcPattern *pattern = FcPatternCreate();
const char *properties [] = {
FC_FAMILY, FC_STYLE, FC_WEIGHT, FC_SLANT,
FC_SPACING, FC_FILE, FC_INDEX,
- FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE, FC_WEIGHT,
+ FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE,
FC_WIDTH,
#if FC_VERSION >= 20297
FC_CAPABILITY,
@@ -339,102 +473,8 @@ void QFontconfigDatabase::populateFontDatabase()
FcPatternDestroy(pattern);
}
- for (int i = 0; i < fonts->nfont; i++) {
- if (FcPatternGetString(fonts->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch)
- continue;
- // capitalize(value);
- familyName = QString::fromUtf8((const char *)value);
- slant_value = FC_SLANT_ROMAN;
- weight_value = FC_WEIGHT_REGULAR;
- spacing_value = FC_PROPORTIONAL;
- file_value = 0;
- indexValue = 0;
- scalable = FcTrue;
-
-
- if (FcPatternGetInteger (fonts->fonts[i], FC_SLANT, 0, &slant_value) != FcResultMatch)
- slant_value = FC_SLANT_ROMAN;
- if (FcPatternGetInteger (fonts->fonts[i], FC_WEIGHT, 0, &weight_value) != FcResultMatch)
- weight_value = FC_WEIGHT_REGULAR;
- if (FcPatternGetInteger (fonts->fonts[i], FC_SPACING, 0, &spacing_value) != FcResultMatch)
- spacing_value = FC_PROPORTIONAL;
- if (FcPatternGetString (fonts->fonts[i], FC_FILE, 0, &file_value) != FcResultMatch)
- file_value = 0;
- if (FcPatternGetInteger (fonts->fonts[i], FC_INDEX, 0, &indexValue) != FcResultMatch)
- indexValue = 0;
- if (FcPatternGetBool(fonts->fonts[i], FC_SCALABLE, 0, &scalable) != FcResultMatch)
- scalable = FcTrue;
- if (FcPatternGetString(fonts->fonts[i], FC_FOUNDRY, 0, &foundry_value) != FcResultMatch)
- foundry_value = 0;
- if (FcPatternGetString(fonts->fonts[i], FC_STYLE, 0, &style_value) != FcResultMatch)
- style_value = 0;
- if(FcPatternGetBool(fonts->fonts[i],FC_ANTIALIAS,0,&antialias) != FcResultMatch)
- antialias = true;
-
- QSupportedWritingSystems writingSystems;
- FcLangSet *langset = 0;
- FcResult res = FcPatternGetLangSet(fonts->fonts[i], FC_LANG, 0, &langset);
- if (res == FcResultMatch) {
- bool hasLang = false;
- for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) {
- const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[j];
- if (lang) {
- FcLangResult langRes = FcLangSetHasLang(langset, lang);
- if (langRes != FcLangDifferentLang) {
- writingSystems.setSupported(QFontDatabase::WritingSystem(j));
- hasLang = true;
- }
- }
- }
- if (!hasLang)
- // none of our known languages, add it to the other set
- writingSystems.setSupported(QFontDatabase::Other);
- } else {
- // we set Other to supported for symbol fonts. It makes no
- // sense to merge these with other ones, as they are
- // special in a way.
- writingSystems.setSupported(QFontDatabase::Other);
- }
-
-#if FC_VERSION >= 20297
- for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) {
- if (writingSystems.supported(QFontDatabase::WritingSystem(j))
- && requiresOpenType(j) && openType[j]) {
- FcChar8 *cap;
- res = FcPatternGetString (fonts->fonts[i], FC_CAPABILITY, 0, &cap);
- if (res != FcResultMatch || !strstr((const char *)cap, openType[j]))
- writingSystems.setSupported(QFontDatabase::WritingSystem(j),false);
- }
- }
-#endif
-
- FontFile *fontFile = new FontFile;
- fontFile->fileName = QLatin1String((const char *)file_value);
- fontFile->indexValue = indexValue;
-
- QFont::Style style = (slant_value == FC_SLANT_ITALIC)
- ? QFont::StyleItalic
- : ((slant_value == FC_SLANT_OBLIQUE)
- ? QFont::StyleOblique
- : QFont::StyleNormal);
- QFont::Weight weight = QFont::Weight(getFCWeight(weight_value));
-
- double pixel_size = 0;
- if (!scalable) {
- int width = 100;
- FcPatternGetInteger (fonts->fonts[i], FC_WIDTH, 0, &width);
- FcPatternGetDouble (fonts->fonts[i], FC_PIXEL_SIZE, 0, &pixel_size);
- }
-
- bool fixedPitch = spacing_value >= FC_MONO;
- QFont::Stretch stretch = QFont::Unstretched;
- QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString();
- QPlatformFontDatabase::registerFont(familyName,styleName,QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,fontFile);
-// qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size;
-
- for (int k = 1; FcPatternGetString(fonts->fonts[i], FC_FAMILY, k, &value) == FcResultMatch; ++k)
- QPlatformFontDatabase::registerAliasToFontFamily(familyName, QString::fromUtf8((const char *)value));
- }
+ for (int i = 0; i < fonts->nfont; i++)
+ populateFromPattern(fonts->fonts[i]);
FcFontSetDestroy (fonts);
@@ -476,20 +516,18 @@ QFontEngineMulti *QFontconfigDatabase::fontEngineMulti(QFontEngine *fontEngine,
return new QFontEngineMultiFontConfig(fontEngine, script);
}
-QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QChar::Script script, void *usrPtr)
+QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr)
{
if (!usrPtr)
return 0;
QFontDef fontDef = f;
- QFontEngineFT *engine;
FontFile *fontfile = static_cast<FontFile *> (usrPtr);
QFontEngine::FaceId fid;
fid.filename = QFile::encodeName(fontfile->fileName);
fid.index = fontfile->indexValue;
bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias);
- engine = new QFontEngineFT(fontDef);
QFontEngineFT::GlyphFormat format;
// try and get the pattern
@@ -509,8 +547,24 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QChar::Script sc
FcPatternAdd(pattern,FC_INDEX,value,true);
FcResult result;
+
+ FcConfigSubstitute(0, pattern, FcMatchPattern);
+ FcDefaultSubstitute(pattern);
+
FcPattern *match = FcFontMatch(0, pattern, &result);
+
+ QFontEngineFT *engine = new QFontEngineFT(fontDef);
+
if (match) {
+ //Respect the file and index of the font config match
+ FcChar8 *file_value;
+ int indexValue;
+
+ if (FcPatternGetString(match, FC_FILE, 0, &file_value) == FcResultMatch)
+ fid.filename = (const char *)file_value;
+ if (FcPatternGetInteger(match, FC_INDEX, 0, &indexValue) == FcResultMatch)
+ fid.index = indexValue;
+
QFontEngineFT::HintStyle default_hint_style;
if (f.hintingPreference != QFont::PreferDefaultHinting) {
switch (f.hintingPreference) {
@@ -587,25 +641,18 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QChar::Script sc
format = subpixelType == QFontEngineFT::Subpixel_None
? QFontEngineFT::Format_A8 : QFontEngineFT::Format_A32;
engine->subpixelType = subpixelType;
- } else
+ } else {
format = QFontEngineFT::Format_Mono;
+ }
FcPatternDestroy(match);
- } else
+ } else {
format = antialias ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono;
+ }
FcPatternDestroy(pattern);
- if (!engine->init(fid,antialias,format)) {
- delete engine;
- engine = 0;
- return engine;
- }
- if (engine->invalid()) {
- delete engine;
- engine = 0;
- } else if (!engine->supportsScript(script)) {
- qWarning(" OpenType support missing for script %d", int(script));
+ if (!engine->init(fid, antialias, format) || engine->invalid()) {
delete engine;
engine = 0;
}
@@ -715,6 +762,7 @@ static FcPattern *queryFont(const FcChar8 *file, const QByteArray &data, int id,
QStringList QFontconfigDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName)
{
QStringList families;
+
FcFontSet *set = FcConfigGetFonts(0, FcSetApplication);
if (!set) {
FcConfigAppFontAddFile(0, (const FcChar8 *)":/non-existent");
@@ -727,28 +775,24 @@ QStringList QFontconfigDatabase::addApplicationFont(const QByteArray &fontData,
FcBlanks *blanks = FcConfigGetBlanks(0);
int count = 0;
- FcPattern *pattern = 0;
+ FcPattern *pattern;
do {
pattern = queryFont((const FcChar8 *)QFile::encodeName(fileName).constData(),
fontData, id, blanks, &count);
if (!pattern)
return families;
- FcPatternDel(pattern, FC_FILE);
- QByteArray cs = fileName.toUtf8();
- FcPatternAddString(pattern, FC_FILE, (const FcChar8 *) cs.constData());
-
FcChar8 *fam = 0;
if (FcPatternGetString(pattern, FC_FAMILY, 0, &fam) == FcResultMatch) {
QString family = QString::fromUtf8(reinterpret_cast<const char *>(fam));
families << family;
}
+ populateFromPattern(pattern);
- if (!FcFontSetAdd(set, pattern))
- return families;
+ FcFontSetAdd(set, pattern);
++id;
- } while (pattern && id < count);
+ } while (id < count);
return families;
}
diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h
index 6d6dae680e..9f1fd28144 100644
--- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h
+++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h
@@ -52,7 +52,7 @@ class QFontconfigDatabase : public QBasicFontDatabase
public:
void populateFontDatabase();
QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script);
- QFontEngine *fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle);
+ QFontEngine *fontEngine(const QFontDef &fontDef, 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;
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
index 38c44e3f35..ab2e9c1f1a 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
@@ -278,10 +278,8 @@ void QCoreTextFontDatabase::releaseHandle(void *handle)
CFRelease(CTFontDescriptorRef(handle));
}
-QFontEngine *QCoreTextFontDatabase::fontEngine(const QFontDef &f, QChar::Script script, void *usrPtr)
+QFontEngine *QCoreTextFontDatabase::fontEngine(const QFontDef &f, void *usrPtr)
{
- Q_UNUSED(script);
-
qreal scaledPointSize = f.pixelSize;
// When 96 DPI is forced, the Mac plugin will use DPI 72 for some
@@ -474,104 +472,120 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo
return fallbackLists[styleLookupKey.arg(styleHint)];
}
-#ifdef Q_OS_MACX
+#if HAVE_CORETEXT
+static CFArrayRef createDescriptorArrayForFont(CTFontRef font)
+{
+ CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
+ CFArrayAppendValue(array, QCFType<CTFontDescriptorRef>(CTFontCopyFontDescriptor(font)));
+ return array;
+}
+#endif
+
QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName)
{
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
- if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) {
- CTFontRef font = NULL;
+ QCFType<CFArrayRef> fonts;
+ QStringList families;
+#if HAVE_CORETEXT
+ if (&CTFontManagerRegisterGraphicsFont) {
+ CFErrorRef error = 0;
if (!fontData.isEmpty()) {
QByteArray* fontDataCopy = new QByteArray(fontData);
QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(fontDataCopy,
fontDataCopy->constData(), fontDataCopy->size(), releaseFontData);
- CGFontRef cgFont = CGFontCreateWithDataProvider(dataProvider);
+ QCFType<CGFontRef> cgFont = CGFontCreateWithDataProvider(dataProvider);
if (cgFont) {
- CFErrorRef error;
- bool success = CTFontManagerRegisterGraphicsFont(cgFont, &error);
- if (success) {
- font = CTFontCreateWithGraphicsFont(cgFont, 0.0, NULL, NULL);
- m_applicationGraphicsFonts.append(QCFType<CGFontRef>::constructFromGet(cgFont));
- } else {
- NSLog(@"Unable to register font: %@", error);
- CFRelease(error);
+ if (CTFontManagerRegisterGraphicsFont(cgFont, &error)) {
+ QCFType<CTFontRef> font = CTFontCreateWithGraphicsFont(cgFont, 0.0, NULL, NULL);
+ fonts = createDescriptorArrayForFont(font);
+ m_applicationFonts.append(QVariant::fromValue(QCFType<CGFontRef>::constructFromGet(cgFont)));
}
- CGFontRelease(cgFont);
}
} else {
- CFErrorRef error;
QCFType<CFURLRef> fontURL = CFURLCreateWithFileSystemPath(NULL, QCFString(fileName), kCFURLPOSIXPathStyle, false);
- bool success = CTFontManagerRegisterFontsForURL(fontURL, kCTFontManagerScopeProcess, &error);
- if (success) {
- const void *keys[] = { kCTFontURLAttribute };
- const void *values[] = { fontURL };
- QCFType<CFDictionaryRef> attributes = CFDictionaryCreate(NULL, keys, values, 1,
- &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- QCFType<CTFontDescriptorRef> descriptor = CTFontDescriptorCreateWithAttributes(attributes);
- font = CTFontCreateWithFontDescriptor(descriptor, 0.0, NULL);
- m_applicationURLFonts.append(QCFType<CFURLRef>::constructFromGet(fontURL));
- } else {
- NSLog(@"Unable to register font: %@", error);
- CFRelease(error);
+ if (CTFontManagerRegisterFontsForURL(fontURL, kCTFontManagerScopeProcess, &error)) {
+#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_6, __IPHONE_7_0)
+ if (&CTFontManagerCreateFontDescriptorsFromURL)
+ fonts = CTFontManagerCreateFontDescriptorsFromURL(fontURL);
+ else
+#endif
+ {
+ // We're limited to a single font per file, unless we dive into the font tables
+ QCFType<CFMutableDictionaryRef> attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 1,
+ &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ CFDictionaryAddValue(attributes, kCTFontURLAttribute, fontURL);
+ QCFType<CTFontDescriptorRef> descriptor = CTFontDescriptorCreateWithAttributes(attributes);
+ QCFType<CTFontRef> font = CTFontCreateWithFontDescriptor(descriptor, 0.0, NULL);
+ fonts = createDescriptorArrayForFont(font);
+ }
+
+ m_applicationFonts.append(QVariant::fromValue(QCFType<CFURLRef>::constructFromGet(fontURL)));
}
}
- if (font) {
- QStringList families;
- families.append(QCFString(CTFontCopyFamilyName(font)));
-
- QCFType<CTFontDescriptorRef> descriptor = CTFontCopyFontDescriptor(font);
- populateFromDescriptor(descriptor);
-
- CFRelease(font);
- return families;
+ if (error) {
+ NSLog(@"Unable to register font: %@", error);
+ CFRelease(error);
}
- } else
+ }
+#endif
+#if HAVE_CORETEXT && HAVE_ATS
+ else
#endif
+#if HAVE_ATS
{
- ATSFontContainerRef fontContainer;
- OSStatus e;
+ ATSFontContainerRef fontContainer;
+ OSStatus e;
- if (!fontData.isEmpty()) {
- e = ATSFontActivateFromMemory((void *) fontData.constData(), fontData.size(),
- kATSFontContextLocal, kATSFontFormatUnspecified, NULL,
- kATSOptionFlagsDefault, &fontContainer);
- } else {
- FSRef ref;
- OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref);
- if (qt_mac_create_fsref(fileName, &ref) != noErr)
- return QStringList();
- e = ATSFontActivateFromFileReference(&ref, kATSFontContextLocal, kATSFontFormatUnspecified, 0,
- kATSOptionFlagsDefault, &fontContainer);
- }
-
- if (e == noErr) {
- ItemCount fontCount = 0;
- e = ATSFontFindFromContainer(fontContainer, kATSOptionFlagsDefault, 0, 0, &fontCount);
- if (e != noErr)
- return QStringList();
-
- QVarLengthArray<ATSFontRef> containedFonts(fontCount);
- e = ATSFontFindFromContainer(fontContainer, kATSOptionFlagsDefault, fontCount, containedFonts.data(), &fontCount);
- if (e != noErr)
- return QStringList();
-
- QStringList families;
- for (int i = 0; i < containedFonts.size(); ++i) {
- QCFType<CTFontRef> font = CTFontCreateWithPlatformFont(containedFonts[i], 12.0, NULL, NULL);
- QCFType<CTFontDescriptorRef> descriptor = CTFontCopyFontDescriptor(font);
- populateFromDescriptor(descriptor);
- families.append(QCFString(CTFontCopyFamilyName(font)));
+ if (!fontData.isEmpty()) {
+ e = ATSFontActivateFromMemory((void *) fontData.constData(), fontData.size(),
+ kATSFontContextLocal, kATSFontFormatUnspecified, NULL,
+ kATSOptionFlagsDefault, &fontContainer);
+ } else {
+ FSRef ref;
+ OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref);
+ if (qt_mac_create_fsref(fileName, &ref) != noErr)
+ return QStringList();
+ e = ATSFontActivateFromFileReference(&ref, kATSFontContextLocal, kATSFontFormatUnspecified, 0,
+ kATSOptionFlagsDefault, &fontContainer);
}
- m_applicationFonts.append(fontContainer);
- return families;
+ if (e == noErr) {
+ ItemCount fontCount = 0;
+ e = ATSFontFindFromContainer(fontContainer, kATSOptionFlagsDefault, 0, 0, &fontCount);
+ if (e != noErr)
+ return QStringList();
+
+ QVarLengthArray<ATSFontRef> containedFonts(fontCount);
+ e = ATSFontFindFromContainer(fontContainer, kATSOptionFlagsDefault, fontCount, containedFonts.data(), &fontCount);
+ if (e != noErr)
+ return QStringList();
+
+ CFMutableArrayRef fontsArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ for (int i = 0; i < containedFonts.size(); ++i) {
+ QCFType<CTFontRef> font = CTFontCreateWithPlatformFont(containedFonts[i], 12.0, NULL, NULL);
+ CFArrayAppendValue(fontsArray, QCFType<CTFontDescriptorRef>(CTFontCopyFontDescriptor(font)));
+ }
+
+ fonts = fontsArray;
+
+ m_applicationFonts.append(QVariant::fromValue(fontContainer));
+ }
}
+#endif
+
+ if (fonts) {
+ const int numFonts = CFArrayGetCount(fonts);
+ for (int i = 0; i < numFonts; ++i) {
+ CTFontDescriptorRef fontDescriptor = CTFontDescriptorRef(CFArrayGetValueAtIndex(fonts, i));
+ populateFromDescriptor(fontDescriptor);
+ QCFType<CFStringRef> familyName = CFStringRef(CTFontDescriptorCopyLocalizedAttribute(fontDescriptor, kCTFontFamilyNameAttribute, NULL));
+ families.append(QCFString(familyName));
+ }
}
- return QStringList();
+ return families;
}
-#endif
QFont QCoreTextFontDatabase::defaultFont() const
{
@@ -596,25 +610,31 @@ QList<int> QCoreTextFontDatabase::standardSizes() const
void QCoreTextFontDatabase::removeApplicationFonts()
{
-#ifdef Q_OS_MACX
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
- if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) {
- CFErrorRef error;
- for (int i = 0; i < m_applicationGraphicsFonts.count(); ++i)
- CTFontManagerUnregisterGraphicsFont(m_applicationGraphicsFonts[i], &error);
- m_applicationGraphicsFonts.clear();
-
- for (int i = 0; i < m_applicationURLFonts.count(); ++i)
- CTFontManagerUnregisterFontsForURL(m_applicationURLFonts[i], kCTFontManagerScopeProcess, &error);
- m_applicationURLFonts.clear();
- } else
+ foreach (const QVariant &font, m_applicationFonts) {
+#if HAVE_CORETEXT
+ if (&CTFontManagerUnregisterGraphicsFont && &CTFontManagerUnregisterFontsForURL) {
+ CFErrorRef error;
+ if (font.canConvert(qMetaTypeId<QCFType<CGFontRef> >())) {
+ CTFontManagerUnregisterGraphicsFont(font.value<QCFType<CGFontRef> >(), &error);
+ } else if (font.canConvert(qMetaTypeId<QCFType<CFURLRef> >())) {
+ CTFontManagerUnregisterFontsForURL(font.value<QCFType<CFURLRef> >(), kCTFontManagerScopeProcess, &error);
+ }
+ }
#endif
- {
- for (int i = 0; i < m_applicationFonts.count(); ++i)
- ATSFontDeactivate(m_applicationFonts[i], 0, kATSOptionFlagsDoNotNotify);
+#if HAVE_CORETEXT && HAVE_ATS
+ else
+#endif
+#if HAVE_ATS
+ if (font.canConvert(qMetaTypeId<ATSFontContainerRef>())) {
+ ATSFontDeactivate(font.value<ATSFontContainerRef>(), 0, kATSOptionFlagsDoNotNotify);
+ }
+#endif
+ }
+
m_applicationFonts.clear();
+
+#if HAVE_ATS
ATSFontNotify(kATSFontNotifyActionFontsChanged, 0);
- }
#endif
}
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
index ee1016509b..1560d36644 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
@@ -42,6 +42,10 @@
#ifndef QCORETEXTFONTDATABASE_H
#define QCORETEXTFONTDATABASE_H
+#include <qglobal.h>
+#define HAVE_CORETEXT QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_8, __IPHONE_4_1)
+#define HAVE_ATS QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_5, __IPHONE_NA)
+
#include <qpa/qplatformfontdatabase.h>
#include <private/qcore_mac_p.h>
@@ -52,6 +56,14 @@
#include <CoreGraphics/CoreGraphics.h>
#endif
+#if HAVE_CORETEXT
+Q_DECLARE_METATYPE(QCFType<CGFontRef>);
+Q_DECLARE_METATYPE(QCFType<CFURLRef>);
+#endif
+#if HAVE_ATS
+Q_DECLARE_METATYPE(ATSFontContainerRef);
+#endif
+
QT_BEGIN_NAMESPACE
class QCoreTextFontDatabase : public QPlatformFontDatabase
@@ -60,12 +72,10 @@ public:
QCoreTextFontDatabase();
~QCoreTextFontDatabase();
void populateFontDatabase();
- QFontEngine *fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle);
+ QFontEngine *fontEngine(const QFontDef &fontDef, void *handle);
QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference);
QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const;
-#ifdef Q_OS_MACX
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName);
-#endif
void releaseHandle(void *handle);
QFont defaultFont() const;
QList<int> standardSizes() const;
@@ -78,13 +88,8 @@ private:
mutable QHash<QString, QString> familyNameToPsName;
void removeApplicationFonts();
-#ifdef Q_OS_MACX
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
- QVector<QCFType<CGFontRef> > m_applicationGraphicsFonts;
- QVector<QCFType<CFURLRef> > m_applicationURLFonts;
-#endif
- QVector<ATSFontContainerRef> m_applicationFonts;
-#endif
+
+ QVector<QVariant> m_applicationFonts;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
index 9b8f10f588..31a015ae9f 100644
--- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
+++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
@@ -63,15 +63,12 @@ static void loadAdvancesForGlyphs(CTFontRef ctfont,
for (int i = 0; i < len; ++i) {
if (glyphs->glyphs[i] & 0xff000000)
continue;
- glyphs->advances_x[i] = QFixed::fromReal(advances[i].width);
- glyphs->advances_y[i] = QFixed::fromReal(advances[i].height);
+ glyphs->advances[i] = QFixed::fromReal(advances[i].width);
}
if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
- for (int i = 0; i < len; ++i) {
- glyphs->advances_x[i] = glyphs->advances_x[i].round();
- glyphs->advances_y[i] = glyphs->advances_y[i].round();
- }
+ for (int i = 0; i < len; ++i)
+ glyphs->advances[i] = glyphs->advances[i].round();
}
}
@@ -191,6 +188,8 @@ void QCoreTextFontEngine::init()
avgCharWidth = QFontEngine::averageCharWidth();
cache_cost = (CTFontGetAscent(ctfont) + CTFontGetDescent(ctfont)) * avgCharWidth.toInt() * 2000;
+
+ setUserData(QVariant::fromValue((void *)cgFont));
}
bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs,
@@ -228,15 +227,12 @@ bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *
for (int i = 0; i < glyph_pos; ++i) {
if (glyphs->glyphs[i] & 0xff000000)
continue;
- glyphs->advances_x[i] = QFixed::fromReal(advances[i].width);
- glyphs->advances_y[i] = QFixed::fromReal(advances[i].height);
+ glyphs->advances[i] = QFixed::fromReal(advances[i].width);
}
if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
- for (int i = 0; i < glyph_pos; ++i) {
- glyphs->advances_x[i] = glyphs->advances_x[i].round();
- glyphs->advances_y[i] = glyphs->advances_y[i].round();
- }
+ for (int i = 0; i < glyph_pos; ++i)
+ glyphs->advances[i] = glyphs->advances[i].round();
}
return true;
}
diff --git a/src/platformsupport/glxconvenience/qglxconvenience.cpp b/src/platformsupport/glxconvenience/qglxconvenience.cpp
index 11d9377db7..4630b12a57 100644
--- a/src/platformsupport/glxconvenience/qglxconvenience.cpp
+++ b/src/platformsupport/glxconvenience/qglxconvenience.cpp
@@ -39,6 +39,10 @@
**
****************************************************************************/
+// We have to include this before the X11 headers dragged in by
+// qglxconvenience_p.h.
+#include <QtCore/QByteArray>
+
#include "qglxconvenience_p.h"
#include <QtCore/QVector>
@@ -116,6 +120,27 @@ QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit)
GLXFBConfig qglx_findConfig(Display *display, int screen , const QSurfaceFormat &format, int drawableBit)
{
+ // Allow forcing LIBGL_ALWAYS_SOFTWARE for Qt 5 applications only.
+ // This is most useful with drivers that only support OpenGL 1.
+ // We need OpenGL 2, but the user probably doesn't want
+ // LIBGL_ALWAYS_SOFTWARE in OpenGL 1 apps.
+ static bool checkedForceSoftwareOpenGL = false;
+ static bool forceSoftwareOpenGL = false;
+ if (!checkedForceSoftwareOpenGL) {
+ // If LIBGL_ALWAYS_SOFTWARE is already set, don't mess with it.
+ // We want to unset LIBGL_ALWAYS_SOFTWARE at the end so it does not
+ // get inherited by other processes, of course only if it wasn't
+ // already set before.
+ if (!qEnvironmentVariableIsEmpty("QT_XCB_FORCE_SOFTWARE_OPENGL")
+ && !qEnvironmentVariableIsSet("LIBGL_ALWAYS_SOFTWARE"))
+ forceSoftwareOpenGL = true;
+
+ checkedForceSoftwareOpenGL = true;
+ }
+
+ if (forceSoftwareOpenGL)
+ qputenv("LIBGL_ALWAYS_SOFTWARE", QByteArrayLiteral("1"));
+
bool reduced = true;
GLXFBConfig chosenConfig = 0;
QSurfaceFormat reducedFormat = format;
@@ -159,6 +184,10 @@ GLXFBConfig qglx_findConfig(Display *display, int screen , const QSurfaceFormat
reducedFormat = qglx_reduceSurfaceFormat(reducedFormat,&reduced);
}
+ // unset LIBGL_ALWAYS_SOFTWARE now so other processes don't inherit it
+ if (forceSoftwareOpenGL)
+ qunsetenv("LIBGL_ALWAYS_SOFTWARE");
+
return chosenConfig;
}
diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboard_defaultmap_p.h b/src/platformsupport/input/evdevkeyboard/qevdevkeyboard_defaultmap_p.h
index 225b3d41ef..3f656668aa 100644
--- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboard_defaultmap_p.h
+++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboard_defaultmap_p.h
@@ -641,6 +641,7 @@ const QEvdevKeyboardMap::Mapping QEvdevKeyboardHandler::s_keymap_default[] = {
{ KEY_VOLUMEUP, 0xffff, Qt::Key_VolumeUp, 0x00, 0x00, 0x0000 },
{ KEY_PAUSE, 0xffff, Qt::Key_Pause, 0x00, 0x00, 0x0000 },
{ KEY_STOP, 0xffff, Qt::Key_Stop, 0x00, 0x00, 0x0000 },
+ { KEY_SETUP, 0xffff, Qt::Key_Settings, 0x00, 0x00, 0x0000 },
{ KEY_RECORD, 0xffff, Qt::Key_MediaRecord, 0x00, 0x00, 0x0000 },
{ KEY_REWIND, 0xffff, Qt::Key_AudioRewind, 0x00, 0x00, 0x0000 },
{ KEY_PLAYPAUSE, 0xffff, Qt::Key_MediaTogglePlayPause, 0x00, 0x00, 0x0000 },
@@ -651,6 +652,9 @@ const QEvdevKeyboardMap::Mapping QEvdevKeyboardHandler::s_keymap_default[] = {
// 0x160 ->
{ KEY_SELECT, 0xffff, Qt::Key_Select, 0x00, 0x00, 0x0000 },
{ KEY_CLEAR, 0xffff, Qt::Key_Clear, 0x00, 0x00, 0x0000 },
+ { KEY_EXIT, 0xffff, Qt::Key_Exit, 0x00, 0x00, 0x0000 },
+ { KEY_INFO, 0xffff, Qt::Key_Info, 0x00, 0x00, 0x0000 },
+ { KEY_PROGRAM, 0xffff, Qt::Key_Guide, 0x00, 0x00, 0x0000 },
{ KEY_CALENDAR, 0xffff, Qt::Key_Calendar, 0x00, 0x00, 0x0000 },
{ KEY_RED, 0xffff, Qt::Key_Red, 0x00, 0x00, 0x0000 },
{ KEY_GREEN, 0xffff, Qt::Key_Green, 0x00, 0x00, 0x0000 },
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h b/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h
index 6abe933371..d52a16ea75 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h
+++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h
@@ -59,6 +59,8 @@ public:
QEvdevMouseManager(const QString &key, const QString &specification, QObject *parent = 0);
~QEvdevMouseManager();
+ QDeviceDiscovery *deviceDiscovery() { return m_deviceDiscovery; }
+
public slots:
void handleMouseEvent(int x, int y, Qt::MouseButtons buttons);
void handleWheelEvent(int delta, Qt::Orientation orientation);
diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
index f44d53a00e..4a1d67f4b5 100644
--- a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
+++ b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
@@ -57,6 +57,7 @@
#include <private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformservices.h>
+#include <qpa/qplatformdialoghelper.h>
#include <algorithm>
@@ -407,7 +408,7 @@ QVariant QKdeTheme::themeHint(QPlatformTheme::ThemeHint hint) const
case QPlatformTheme::DialogButtonBoxButtonsHaveIcons:
return QVariant(true);
case QPlatformTheme::DialogButtonBoxLayout:
- return QVariant(2); // QDialogButtonBox::KdeLayout
+ return QVariant(QPlatformDialogHelper::KdeLayout);
case QPlatformTheme::ToolButtonStyle:
return QVariant(d->toolButtonStyle);
case QPlatformTheme::ToolBarIconSize:
@@ -503,7 +504,7 @@ QVariant QGnomeTheme::themeHint(QPlatformTheme::ThemeHint hint) const
case QPlatformTheme::DialogButtonBoxButtonsHaveIcons:
return QVariant(true);
case QPlatformTheme::DialogButtonBoxLayout:
- return QVariant(3); // QDialogButtonBox::GnomeLayout
+ return QVariant(QPlatformDialogHelper::GnomeLayout);
case QPlatformTheme::SystemIconThemeName:
case QPlatformTheme::SystemIconFallbackThemeName:
return QVariant(QString(QStringLiteral("gnome")));
@@ -537,6 +538,25 @@ const QFont *QGnomeTheme::font(Font type) const
}
}
+QString QGnomeTheme::standardButtonText(int button) const
+{
+ switch (button) {
+ case QPlatformDialogHelper::Ok:
+ return QCoreApplication::translate("QGnomeTheme", "&OK");
+ case QPlatformDialogHelper::Save:
+ return QCoreApplication::translate("QGnomeTheme", "&Save");
+ case QPlatformDialogHelper::Cancel:
+ return QCoreApplication::translate("QGnomeTheme", "&Cancel");
+ case QPlatformDialogHelper::Close:
+ return QCoreApplication::translate("QGnomeTheme", "&Close");
+ case QPlatformDialogHelper::Discard:
+ return QCoreApplication::translate("QGnomeTheme", "Close without Saving");
+ default:
+ break;
+ }
+ return QPlatformTheme::standardButtonText(button);
+}
+
/*!
\brief Creates a UNIX theme according to the detected desktop environment.
*/
diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h b/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h
index 03445776f4..36fcdd8dce 100644
--- a/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h
+++ b/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h
@@ -86,8 +86,8 @@ class QKdeThemePrivate;
class QKdeTheme : public QPlatformTheme
{
Q_DECLARE_PRIVATE(QKdeTheme)
- QKdeTheme(const QString &kdeHome, int kdeVersion);
public:
+ QKdeTheme(const QString &kdeHome, int kdeVersion);
static QPlatformTheme *createKdeTheme();
virtual QVariant themeHint(ThemeHint hint) const;
@@ -109,6 +109,7 @@ public:
QGnomeTheme();
virtual QVariant themeHint(ThemeHint hint) const;
virtual const QFont *font(Font type) const;
+ QString standardButtonText(int button) const Q_DECL_OVERRIDE;
static const char *name;
};