diff options
author | Oswald Buddenhagen <oswald.buddenhagen@digia.com> | 2014-02-19 10:06:25 +0100 |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@digia.com> | 2014-02-19 10:06:25 +0100 |
commit | 30fd22b9574def54726e7b193127cc0c901c1b4c (patch) | |
tree | 96dfc923044db0515064ba39d052d9ed577e3e40 /src/platformsupport | |
parent | d7b0581c1c2ef60c08d238dae39298af6904918f (diff) | |
parent | 6aa09bbce59828d028f6d1e81d2bfc6ba537aae1 (diff) |
Merge remote-tracking branch 'origin/dev' into stable
Change-Id: Ice524edcc51373509f0023ae7f7c2963f4602f88
Diffstat (limited to 'src/platformsupport')
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 ®ion, 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 ®ion, 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 ®ion, 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 ®ion, 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 ®ion); + 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; }; |