diff options
Diffstat (limited to 'src/platformsupport')
17 files changed, 361 insertions, 113 deletions
diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp index eec6463c21..9691d12682 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp @@ -44,6 +44,7 @@ #include "qeglpbuffer_p.h" #include <qpa/qplatformwindow.h> #include <QOpenGLContext> +#include <QtPlatformHeaders/QEGLNativeContext> #include <QDebug> QT_BEGIN_NAMESPACE @@ -108,25 +109,21 @@ QT_BEGIN_NAMESPACE #define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 #endif -QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display) - : m_eglDisplay(display) - , m_eglConfig(q_configFromGLFormat(display, format)) - , m_swapInterval(-1) - , m_swapIntervalEnvChecked(false) - , m_swapIntervalFromEnv(-1) -{ - init(format, share); -} - QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, - EGLConfig config) + EGLConfig *config, const QVariant &nativeHandle) : m_eglDisplay(display) - , m_eglConfig(config) , m_swapInterval(-1) , m_swapIntervalEnvChecked(false) , m_swapIntervalFromEnv(-1) { - init(format, share); + if (nativeHandle.isNull()) { + m_eglConfig = config ? *config : q_configFromGLFormat(display, format); + m_ownsContext = true; + init(format, share); + } else { + m_ownsContext = false; + adopt(nativeHandle, share); + } } void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLContext *share) @@ -198,6 +195,59 @@ void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLCont q_printEglConfig(m_eglDisplay, m_eglConfig); } + updateFormatFromGL(); +} + +void QEGLPlatformContext::adopt(const QVariant &nativeHandle, QPlatformOpenGLContext *share) +{ + if (!nativeHandle.canConvert<QEGLNativeContext>()) { + qWarning("QEGLPlatformContext: Requires a QEGLNativeContext"); + return; + } + QEGLNativeContext handle = nativeHandle.value<QEGLNativeContext>(); + EGLContext context = handle.context(); + if (!context) { + qWarning("QEGLPlatformContext: No EGLContext given"); + return; + } + + // A context belonging to a given EGLDisplay cannot be used with another one. + if (handle.display() != m_eglDisplay) { + qWarning("QEGLPlatformContext: Cannot adopt context from different display"); + return; + } + + // Figure out the EGLConfig. + EGLint value = 0; + eglQueryContext(m_eglDisplay, context, EGL_CONFIG_ID, &value); + EGLint n = 0; + EGLConfig cfg; + const EGLint attribs[] = { EGL_CONFIG_ID, value, EGL_NONE }; + if (eglChooseConfig(m_eglDisplay, attribs, &cfg, 1, &n) && n == 1) { + m_eglConfig = cfg; + m_format = q_glFormatFromConfig(m_eglDisplay, m_eglConfig); + } else { + qWarning("QEGLPlatformContext: Failed to get framebuffer configuration for context"); + } + + // Fetch client API type. + value = 0; + eglQueryContext(m_eglDisplay, context, EGL_CONTEXT_CLIENT_TYPE, &value); + if (value == EGL_OPENGL_API || value == EGL_OPENGL_ES_API) { + m_api = value; + eglBindAPI(m_api); + } else { + qWarning("QEGLPlatformContext: Failed to get client API type"); + m_api = EGL_OPENGL_ES_API; + } + + m_eglContext = context; + m_shareContext = share ? static_cast<QEGLPlatformContext *>(share)->m_eglContext : 0; + updateFormatFromGL(); +} + +void QEGLPlatformContext::updateFormatFromGL() +{ #ifndef QT_NO_OPENGL // Make the context current to ensure the GL version query works. This needs a surface too. const EGLint pbufferAttributes[] = { @@ -296,10 +346,10 @@ bool QEGLPlatformContext::makeCurrent(QPlatformSurface *surface) QEGLPlatformContext::~QEGLPlatformContext() { - if (m_eglContext != EGL_NO_CONTEXT) { + if (m_ownsContext && m_eglContext != EGL_NO_CONTEXT) eglDestroyContext(m_eglDisplay, m_eglContext); - m_eglContext = EGL_NO_CONTEXT; - } + + m_eglContext = EGL_NO_CONTEXT; } void QEGLPlatformContext::doneCurrent() diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h index 714633c3bc..82f062c4a4 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h @@ -44,6 +44,7 @@ #include <qpa/qplatformwindow.h> #include <qpa/qplatformopenglcontext.h> +#include <QtCore/QVariant> #include <EGL/egl.h> QT_BEGIN_NAMESPACE @@ -51,9 +52,8 @@ QT_BEGIN_NAMESPACE class QEGLPlatformContext : public QPlatformOpenGLContext { public: - QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display); QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, - EGLConfig config); + EGLConfig *config = 0, const QVariant &nativeHandle = QVariant()); ~QEGLPlatformContext(); bool makeCurrent(QPlatformSurface *surface); @@ -74,6 +74,8 @@ protected: private: void init(const QSurfaceFormat &format, QPlatformOpenGLContext *share); + void adopt(const QVariant &nativeHandle, QPlatformOpenGLContext *share); + void updateFormatFromGL(); EGLContext m_eglContext; EGLContext m_shareContext; @@ -84,6 +86,7 @@ private: int m_swapInterval; bool m_swapIntervalEnvChecked; int m_swapIntervalFromEnv; + bool m_ownsContext; }; QT_END_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglplatformintegration.cpp b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp index b48f993436..560ff79ef8 100644 --- a/src/platformsupport/eglconvenience/qeglplatformintegration.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp @@ -158,9 +158,14 @@ QPlatformOpenGLContext *QEGLPlatformIntegration::createPlatformOpenGLContext(QOp // 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()); + QPlatformOpenGLContext *share = compositingContext ? compositingContext->handle() : context->shareHandle(); + QVariant nativeHandle = context->nativeHandle(); + QPlatformOpenGLContext *platformContext = createContext(context->format(), + share, + display(), + &nativeHandle); + context->setNativeHandle(nativeHandle); + return platformContext; } QPlatformOffscreenSurface *QEGLPlatformIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const @@ -189,7 +194,9 @@ QPlatformNativeInterface *QEGLPlatformIntegration::nativeInterface() const enum ResourceType { EglDisplay, EglWindow, - EglContext + EglContext, + NativeDisplay, + Display }; static int resourceType(const QByteArray &key) @@ -197,7 +204,9 @@ static int resourceType(const QByteArray &key) static const QByteArray names[] = { // match ResourceType QByteArrayLiteral("egldisplay"), QByteArrayLiteral("eglwindow"), - QByteArrayLiteral("eglcontext") + QByteArrayLiteral("eglcontext"), + QByteArrayLiteral("nativedisplay"), + QByteArrayLiteral("display") }; const QByteArray *end = names + sizeof(names) / sizeof(names[0]); const QByteArray *result = std::find(names, end, key); @@ -214,6 +223,26 @@ void *QEGLPlatformIntegration::nativeResourceForIntegration(const QByteArray &re case EglDisplay: result = m_screen->display(); break; + case NativeDisplay: + result = reinterpret_cast<void*>(nativeDisplay()); + break; + default: + break; + } + + return result; +} + +void *QEGLPlatformIntegration::nativeResourceForScreen(const QByteArray &resource, QScreen *) +{ + void *result = 0; + + switch (resourceType(resource)) { + case Display: + // Play nice when using the x11 hooks: Be compatible with xcb that allows querying + // the X Display pointer, which is nothing but our native display. + result = reinterpret_cast<void*>(nativeDisplay()); + break; default: break; } diff --git a/src/platformsupport/eglconvenience/qeglplatformintegration_p.h b/src/platformsupport/eglconvenience/qeglplatformintegration_p.h index f665455383..9d4207e005 100644 --- a/src/platformsupport/eglconvenience/qeglplatformintegration_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformintegration_p.h @@ -44,6 +44,7 @@ #include <qpa/qplatformintegration.h> #include <qpa/qplatformnativeinterface.h> +#include <QtCore/QVariant> #include <EGL/egl.h> QT_BEGIN_NAMESPACE @@ -79,6 +80,7 @@ public: QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE; // QPlatformNativeInterface void *nativeResourceForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE; + void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen) 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; @@ -88,7 +90,8 @@ protected: virtual QEGLPlatformWindow *createWindow(QWindow *window) const = 0; virtual QEGLPlatformContext *createContext(const QSurfaceFormat &format, QPlatformOpenGLContext *shareContext, - EGLDisplay display) const = 0; + EGLDisplay display, + QVariant *nativeHandle) const = 0; virtual QPlatformOffscreenSurface *createOffscreenSurface(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *surface) const = 0; diff --git a/src/platformsupport/fbconvenience/qfbscreen.cpp b/src/platformsupport/fbconvenience/qfbscreen.cpp index 37d16ddeb6..a962a5eb59 100644 --- a/src/platformsupport/fbconvenience/qfbscreen.cpp +++ b/src/platformsupport/fbconvenience/qfbscreen.cpp @@ -196,13 +196,13 @@ void QFbScreen::generateRects() remainingScreen -= localGeometry; QRegion windowRegion(localGeometry); windowRegion -= remainingScreen; - foreach (QRect rect, windowRegion.rects()) { + foreach (const QRect &rect, windowRegion.rects()) { mCachedRects += QPair<QRect, int>(rect, i); } } #endif } - foreach (QRect rect, remainingScreen.rects()) + foreach (const QRect &rect, remainingScreen.rects()) mCachedRects += QPair<QRect, int>(rect, -1); mIsUpToDate = true; return; @@ -242,7 +242,7 @@ QRegion QFbScreen::doRedraw() rectRegion -= intersect; // we only expect one rectangle, but defensive coding... - foreach (QRect rect, intersect.rects()) { + foreach (const QRect &rect, intersect.rects()) { bool firstLayer = true; if (layer == -1) { mCompositePainter->fillRect(rect, Qt::black); diff --git a/src/platformsupport/fbconvenience/qfbscreen_p.h b/src/platformsupport/fbconvenience/qfbscreen_p.h index dd940c4a1d..924b49afda 100644 --- a/src/platformsupport/fbconvenience/qfbscreen_p.h +++ b/src/platformsupport/fbconvenience/qfbscreen_p.h @@ -108,7 +108,7 @@ private: void generateRects(); QPainter *mCompositePainter; - QList<QPair<QRect, int> > mCachedRects; + QVector<QPair<QRect, int> > mCachedRects; QList <QFbBackingStore*> mBackingStores; friend class QFbWindow; diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index 9248785696..c0643444e2 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -348,7 +348,7 @@ QFontEngine *QCoreTextFontDatabase::fontEngine(const QByteArray &fontData, qreal QFontEngine *fontEngine = NULL; if (cgFont == NULL) { - qWarning("QRawFont::platformLoadFromData: CGFontCreateWithDataProvider failed"); + qWarning("QCoreTextFontDatabase::fontEngine: CGFontCreateWithDataProvider failed"); } else { QFontDef def; def.pixelSize = pixelSize; diff --git a/src/platformsupport/glxconvenience/qglxconvenience.cpp b/src/platformsupport/glxconvenience/qglxconvenience.cpp index 4630b12a57..851ad37a6a 100644 --- a/src/platformsupport/glxconvenience/qglxconvenience.cpp +++ b/src/platformsupport/glxconvenience/qglxconvenience.cpp @@ -250,7 +250,7 @@ XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *f return visualInfo; } -void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, GLXFBConfig config, GLXContext) +void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, GLXFBConfig config) { int redSize = 0; int greenSize = 0; @@ -262,8 +262,6 @@ void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, int sampleCount = 0; int stereo = 0; - XVisualInfo *vi = glXGetVisualFromFBConfig(display,config); - XFree(vi); glXGetFBConfigAttrib(display, config, GLX_RED_SIZE, &redSize); glXGetFBConfigAttrib(display, config, GLX_GREEN_SIZE, &greenSize); glXGetFBConfigAttrib(display, config, GLX_BLUE_SIZE, &blueSize); @@ -287,6 +285,41 @@ void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, format->setStereo(stereo); } +void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display, XVisualInfo *visualInfo) +{ + int redSize = 0; + int greenSize = 0; + int blueSize = 0; + int alphaSize = 0; + int depthSize = 0; + int stencilSize = 0; + int sampleBuffers = 0; + int sampleCount = 0; + int stereo = 0; + + glXGetConfig(display, visualInfo, GLX_RED_SIZE, &redSize); + glXGetConfig(display, visualInfo, GLX_GREEN_SIZE, &greenSize); + glXGetConfig(display, visualInfo, GLX_BLUE_SIZE, &blueSize); + glXGetConfig(display, visualInfo, GLX_ALPHA_SIZE, &alphaSize); + glXGetConfig(display, visualInfo, GLX_DEPTH_SIZE, &depthSize); + glXGetConfig(display, visualInfo, GLX_STENCIL_SIZE, &stencilSize); + glXGetConfig(display, visualInfo, GLX_SAMPLES_ARB, &sampleBuffers); + glXGetConfig(display, visualInfo, GLX_STEREO, &stereo); + + format->setRedBufferSize(redSize); + format->setGreenBufferSize(greenSize); + format->setBlueBufferSize(blueSize); + format->setAlphaBufferSize(alphaSize); + format->setDepthBufferSize(depthSize); + format->setStencilBufferSize(stencilSize); + if (sampleBuffers) { + glXGetConfig(display, visualInfo, GLX_SAMPLES_ARB, &sampleCount); + format->setSamples(sampleCount); + } + + format->setStereo(stereo); +} + QSurfaceFormat qglx_reduceSurfaceFormat(const QSurfaceFormat &format, bool *reduced) { QSurfaceFormat retFormat = format; diff --git a/src/platformsupport/glxconvenience/qglxconvenience_p.h b/src/platformsupport/glxconvenience/qglxconvenience_p.h index 66548a3479..04fa8595ef 100644 --- a/src/platformsupport/glxconvenience/qglxconvenience_p.h +++ b/src/platformsupport/glxconvenience/qglxconvenience_p.h @@ -50,7 +50,8 @@ XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *format); GLXFBConfig qglx_findConfig(Display *display, int screen, const QSurfaceFormat &format, int drawableBit = GLX_WINDOW_BIT); -void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, GLXFBConfig config, GLXContext context = 0); +void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, GLXFBConfig config); +void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display, XVisualInfo *visualInfo); QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit = GLX_WINDOW_BIT); QSurfaceFormat qglx_reduceSurfaceFormat(const QSurfaceFormat &format, bool *reduced); diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp index 92f807095f..611a7f9d6d 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp +++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp @@ -60,6 +60,8 @@ //#define QT_QPA_MOUSE_HANDLER_DEBUG +#define TEST_BIT(array, bit) (array[bit/8] & (1<<(bit%8))) + QT_BEGIN_NAMESPACE QEvdevMouseHandler *QEvdevMouseHandler::create(const QString &device, const QString &specification) @@ -71,6 +73,7 @@ QEvdevMouseHandler *QEvdevMouseHandler::create(const QString &device, const QStr bool compression = true; int jitterLimit = 0; int grab = 0; + bool abs = false; QStringList args = specification.split(QLatin1Char(':')); foreach (const QString &arg, args) { @@ -80,27 +83,37 @@ QEvdevMouseHandler *QEvdevMouseHandler::create(const QString &device, const QStr jitterLimit = arg.mid(9).toInt(); else if (arg.startsWith(QLatin1String("grab="))) grab = arg.mid(5).toInt(); + else if (arg == QLatin1String("abs")) + abs = true; } int fd; fd = qt_safe_open(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0); if (fd >= 0) { ::ioctl(fd, EVIOCGRAB, grab); - return new QEvdevMouseHandler(device, fd, compression, jitterLimit); + return new QEvdevMouseHandler(device, fd, abs, compression, jitterLimit); } else { qWarning("Cannot open mouse input device '%s': %s", qPrintable(device), strerror(errno)); return 0; } } -QEvdevMouseHandler::QEvdevMouseHandler(const QString &device, int fd, bool compression, int jitterLimit) +QEvdevMouseHandler::QEvdevMouseHandler(const QString &device, int fd, bool abs, bool compression, int jitterLimit) : m_device(device), m_fd(fd), m_notify(0), m_x(0), m_y(0), m_prevx(0), m_prevy(0), - m_compression(compression), m_buttons(0), m_prevInvalid(true) + m_abs(abs), m_compression(compression), m_buttons(0), m_prevInvalid(true) { setObjectName(QLatin1String("Evdev Mouse Handler")); m_jitterLimitSquared = jitterLimit * jitterLimit; + // Some touch screens present as mice with absolute coordinates. + // These can not be differentiated from touchpads, so supplying abs to QT_QPA_EVDEV_MOUSE_PARAMETERS + // will force qevdevmousehandler to treat the coordinates as absolute, scaled to the hardware maximums. + // Turning this on will not affect mice as these do not report in absolute coordinates + // but will make touchpads act like touch screens + if (m_abs) + m_abs = getHardwareMaximum(); + // socket notifier for events on the mouse device QSocketNotifier *notifier; notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); @@ -113,16 +126,66 @@ QEvdevMouseHandler::~QEvdevMouseHandler() qt_safe_close(m_fd); } +// Ask touch screen hardware for information on coordinate maximums +// If any ioctls fail, revert to non abs mode +bool QEvdevMouseHandler::getHardwareMaximum() +{ + unsigned char absFeatures[(ABS_MAX / 8) + 1]; + memset(absFeatures, '\0', sizeof (absFeatures)); + + // test if ABS_X, ABS_Y are available + if (ioctl(m_fd, EVIOCGBIT(EV_ABS, sizeof (absFeatures)), absFeatures) == -1) + return false; + + if ((!TEST_BIT(absFeatures, ABS_X)) || (!TEST_BIT(absFeatures, ABS_Y))) + return false; + + // ask hardware for minimum and maximum values + struct input_absinfo absInfo; + if (ioctl(m_fd, EVIOCGABS(ABS_X), &absInfo) == -1) + return false; + + m_hardwareWidth = absInfo.maximum - absInfo.minimum; + + if (ioctl(m_fd, EVIOCGABS(ABS_Y), &absInfo) == -1) + return false; + + m_hardwareHeight = absInfo.maximum - absInfo.minimum; + + QRect g = QGuiApplication::primaryScreen()->virtualGeometry(); + m_hardwareScalerX = static_cast<qreal>(m_hardwareWidth) / (g.right() - g.left()); + m_hardwareScalerY = static_cast<qreal>(m_hardwareHeight) / (g.bottom() - g.top()); + +#ifdef QT_QPA_MOUSE_HANDLER_DEBUG + qDebug() << "Absolute pointing device"; + qDebug() << "hardware max x" << m_hardwareWidth; + qDebug() << "hardware max y" << m_hardwareHeight; + qDebug() << "hardware scalers x" << m_hardwareScalerX << "y" << m_hardwareScalerY; +#endif + + return true; +} + void QEvdevMouseHandler::sendMouseEvent() { - int x = m_x - m_prevx; - int y = m_y - m_prevy; + int x; + int y; + + if (!m_abs) { + x = m_x - m_prevx; + y = m_y - m_prevy; + } + else { + x = m_x / m_hardwareScalerX; + y = m_y / m_hardwareScalerY; + } + if (m_prevInvalid) { x = y = 0; m_prevInvalid = false; } - emit handleMouseEvent(x, y, m_buttons); + emit handleMouseEvent(x, y, m_abs, m_buttons); m_prevx = m_x; m_prevy = m_y; diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h b/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h index d419a1913e..027d2862b0 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h +++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h @@ -57,26 +57,32 @@ public: ~QEvdevMouseHandler(); signals: - void handleMouseEvent(int x, int y, Qt::MouseButtons buttons); + void handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons); void handleWheelEvent(int delta, Qt::Orientation orientation); private slots: void readMouseData(); private: - QEvdevMouseHandler(const QString &device, int fd, bool compression, int jitterLimit); + QEvdevMouseHandler(const QString &device, int fd, bool abs, bool compression, int jitterLimit); void sendMouseEvent(); + bool getHardwareMaximum(); QString m_device; int m_fd; QSocketNotifier *m_notify; int m_x, m_y; int m_prevx, m_prevy; + bool m_abs; bool m_compression; Qt::MouseButtons m_buttons; int m_jitterLimitSquared; bool m_prevInvalid; + int m_hardwareWidth; + int m_hardwareHeight; + qreal m_hardwareScalerY; + qreal m_hardwareScalerX; }; QT_END_NAMESPACE diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp index 6c430091c1..7b834a5c61 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp +++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp @@ -111,11 +111,16 @@ QEvdevMouseManager::~QEvdevMouseManager() m_mice.clear(); } -void QEvdevMouseManager::handleMouseEvent(int x, int y, Qt::MouseButtons buttons) +void QEvdevMouseManager::handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons) { // update current absolute coordinates - m_x += x; - m_y += y; + if (!abs) { + m_x += x; + m_y += y; + } else { + m_x = x; + m_y = y; + } // clamp to screen geometry QRect g = QGuiApplication::primaryScreen()->virtualGeometry(); @@ -156,7 +161,7 @@ void QEvdevMouseManager::addMouse(const QString &deviceNode) QEvdevMouseHandler *handler; handler = QEvdevMouseHandler::create(deviceNode, m_spec); if (handler) { - connect(handler, SIGNAL(handleMouseEvent(int,int,Qt::MouseButtons)), this, SLOT(handleMouseEvent(int,int,Qt::MouseButtons))); + connect(handler, SIGNAL(handleMouseEvent(int,int,bool,Qt::MouseButtons)), this, SLOT(handleMouseEvent(int,int,bool,Qt::MouseButtons))); connect(handler, SIGNAL(handleWheelEvent(int,Qt::Orientation)), this, SLOT(handleWheelEvent(int,Qt::Orientation))); m_mice.insert(deviceNode, handler); } else { diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h b/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h index d52a16ea75..5280b5efbd 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h +++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h @@ -62,7 +62,7 @@ public: QDeviceDiscovery *deviceDiscovery() { return m_deviceDiscovery; } public slots: - void handleMouseEvent(int x, int y, Qt::MouseButtons buttons); + void handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons); void handleWheelEvent(int delta, Qt::Orientation orientation); private slots: diff --git a/src/platformsupport/input/evdevtouch/qevdevtouch.cpp b/src/platformsupport/input/evdevtouch/qevdevtouch.cpp index 563edf4fd7..6ed4abaeee 100644 --- a/src/platformsupport/input/evdevtouch/qevdevtouch.cpp +++ b/src/platformsupport/input/evdevtouch/qevdevtouch.cpp @@ -184,6 +184,8 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification, QString dev; int rotationAngle = 0; + bool invertx = false; + bool inverty = false; for (int i = 0; i < args.count(); ++i) { if (args.at(i).startsWith(QLatin1String("/dev/")) && dev.isEmpty()) { dev = args.at(i); @@ -201,6 +203,10 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification, break; } } + } else if (args.at(i) == QLatin1String("invertx")) { + invertx = true; + } else if (args.at(i) == QLatin1String("inverty")) { + inverty = true; } } @@ -326,6 +332,12 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification, if (rotationAngle) d->m_rotate = QTransform::fromTranslate(0.5, 0.5).rotate(rotationAngle).translate(-0.5, -0.5); + if (invertx) + d->m_rotate *= QTransform::fromTranslate(0.5, 0.5).scale(-1.0, 1.0).translate(-0.5, -0.5); + + if (inverty) + d->m_rotate *= QTransform::fromTranslate(0.5, 0.5).scale(1.0, -1.0).translate(-0.5, -0.5); + d->registerDevice(); } diff --git a/src/platformsupport/linuxaccessibility/dbusconnection.cpp b/src/platformsupport/linuxaccessibility/dbusconnection.cpp index 18915f8e08..7bdd586a1f 100644 --- a/src/platformsupport/linuxaccessibility/dbusconnection.cpp +++ b/src/platformsupport/linuxaccessibility/dbusconnection.cpp @@ -84,8 +84,14 @@ void DBusConnection::serviceRegistered() QDBusConnection c = QDBusConnection::sessionBus(); OrgA11yStatusInterface *a11yStatus = new OrgA11yStatusInterface(A11Y_SERVICE, A11Y_PATH, c, this); + //The variable was introduced because on some embedded platforms there are custom accessibility + //clients which don't set Status.ScreenReaderEnabled to true. The variable is also useful for + //debugging. + static const bool a11yAlwaysOn = !qEnvironmentVariableIsSet("QT_LINUX_ACCESSIBILITY_ALWAYS_ON"); + // a11yStatus->isEnabled() returns always true (since Gnome 3.6) - bool enabled = a11yStatus->screenReaderEnabled(); + bool enabled = a11yAlwaysOn || a11yStatus->screenReaderEnabled(); + if (enabled != m_enabled) { m_enabled = enabled; if (m_a11yConnection.isConnected()) { diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp index 4a1d67f4b5..bf73d30871 100644 --- a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp +++ b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp @@ -51,6 +51,7 @@ #include <QtCore/QFileInfo> #include <QtCore/QFile> #include <QtCore/QDebug> +#include <QtCore/QHash> #include <QtCore/QSettings> #include <QtCore/QVariant> #include <QtCore/QStringList> @@ -171,26 +172,26 @@ QVariant QGenericUnixTheme::themeHint(ThemeHint hint) const class QKdeThemePrivate : public QPlatformThemePrivate { public: - QKdeThemePrivate(const QString &kdeHome, int kdeVersion) - : kdeHome(kdeHome) + QKdeThemePrivate(const QStringList &kdeDirs, int kdeVersion) + : kdeDirs(kdeDirs) , kdeVersion(kdeVersion) , toolButtonStyle(Qt::ToolButtonTextBesideIcon) , toolBarIconSize(0) , singleClick(true) { } - QString globalSettingsFile() const + static QString kdeGlobals(const QString &kdeDir) { - return kdeHome + QStringLiteral("/share/config/kdeglobals"); + return kdeDir + QStringLiteral("/share/config/kdeglobals"); } void refresh(); - static void readKdeSystemPalette(const QSettings &kdeSettings, QPalette *pal); - static QFont *readKdeFontSetting(const QSettings &settings, const QString &key); - static QStringList kdeIconThemeSearchPaths(const QString &kdeHome); + static QVariant readKdeSetting(const QString &key, const QStringList &kdeDirs, QHash<QString, QSettings*> &kdeSettings); + static void readKdeSystemPalette(const QStringList &kdeDirs, QHash<QString, QSettings*> &kdeSettings, QPalette *pal); + static QFont *kdeFont(const QVariant &fontValue); + static QStringList kdeIconThemeSearchPaths(const QStringList &kdeDirs); - - const QString kdeHome; + const QStringList kdeDirs; const int kdeVersion; ResourceHelper resources; @@ -212,36 +213,33 @@ void QKdeThemePrivate::refresh() styleNames << QStringLiteral("Oxygen") << QStringLiteral("fusion") << QStringLiteral("windows"); iconFallbackThemeName = iconThemeName = QStringLiteral("oxygen"); - // Read settings file. - const QString settingsFile = globalSettingsFile(); - if (!QFileInfo(settingsFile).isReadable()) - return; - - const QSettings kdeSettings(settingsFile, QSettings::IniFormat); + QHash<QString, QSettings*> kdeSettings; QPalette systemPalette = QPalette(); - readKdeSystemPalette(kdeSettings, &systemPalette); + readKdeSystemPalette(kdeDirs, kdeSettings, &systemPalette); resources.palettes[QPlatformTheme::SystemPalette] = new QPalette(systemPalette); //## TODO tooltip color - const QVariant styleValue = kdeSettings.value(QStringLiteral("widgetStyle")); + const QVariant styleValue = readKdeSetting(QStringLiteral("widgetStyle"), kdeDirs, kdeSettings); if (styleValue.isValid()) { const QString style = styleValue.toString(); if (style != styleNames.front()) styleNames.push_front(style); } - singleClick = kdeSettings.value(QStringLiteral("KDE/SingleClick"), true).toBool(); + const QVariant singleClickValue = readKdeSetting(QStringLiteral("KDE/SingleClick"), kdeDirs, kdeSettings); + if (singleClickValue.isValid()) + singleClick = singleClickValue.toBool(); - const QVariant themeValue = kdeSettings.value(QStringLiteral("Icons/Theme")); + const QVariant themeValue = readKdeSetting(QStringLiteral("Icons/Theme"), kdeDirs, kdeSettings); if (themeValue.isValid()) iconThemeName = themeValue.toString(); - const QVariant toolBarIconSizeValue = kdeSettings.value(QStringLiteral("ToolbarIcons/Size")); + const QVariant toolBarIconSizeValue = readKdeSetting(QStringLiteral("ToolbarIcons/Size"), kdeDirs, kdeSettings); if (toolBarIconSizeValue.isValid()) toolBarIconSize = toolBarIconSizeValue.toInt(); - const QVariant toolbarStyleValue = kdeSettings.value(QStringLiteral("ToolButtonStyle")); + const QVariant toolbarStyleValue = readKdeSetting(QStringLiteral("Toolbar style/ToolButtonStyle"), kdeDirs, kdeSettings); if (toolbarStyleValue.isValid()) { const QString toolBarStyle = toolbarStyleValue.toString(); if (toolBarStyle == QStringLiteral("TextBesideIcon")) @@ -253,26 +251,46 @@ void QKdeThemePrivate::refresh() } // Read system font, ignore 'smallestReadableFont' - if (QFont *systemFont = readKdeFontSetting(kdeSettings, QStringLiteral("font"))) + if (QFont *systemFont = kdeFont(readKdeSetting(QStringLiteral("font"), kdeDirs, kdeSettings))) resources.fonts[QPlatformTheme::SystemFont] = systemFont; else resources.fonts[QPlatformTheme::SystemFont] = new QFont(QLatin1String(defaultSystemFontNameC), defaultSystemFontSize); - if (QFont *fixedFont = readKdeFontSetting(kdeSettings, QStringLiteral("fixed"))) { + if (QFont *fixedFont = kdeFont(readKdeSetting(QStringLiteral("fixed"), kdeDirs, kdeSettings))) { resources.fonts[QPlatformTheme::FixedFont] = fixedFont; } else { fixedFont = new QFont(QLatin1String(defaultSystemFontNameC), defaultSystemFontSize); fixedFont->setStyleHint(QFont::TypeWriter); resources.fonts[QPlatformTheme::FixedFont] = fixedFont; } + + qDeleteAll(kdeSettings); +} + +QVariant QKdeThemePrivate::readKdeSetting(const QString &key, const QStringList &kdeDirs, QHash<QString, QSettings*> &kdeSettings) +{ + foreach (const QString &kdeDir, kdeDirs) { + QSettings *settings = kdeSettings.value(kdeDir); + if (!settings) { + const QString kdeGlobalsPath = kdeGlobals(kdeDir); + if (QFileInfo(kdeGlobalsPath).isReadable()) { + settings = new QSettings(kdeGlobalsPath, QSettings::IniFormat); + kdeSettings.insert(kdeDir, settings); + } + } + if (settings) { + const QVariant value = settings->value(key); + if (value.isValid()) + return value; + } + } + return QVariant(); } // Reads the color from the KDE configuration, and store it in the // palette with the given color role if found. -static inline bool kdeColor(QPalette *pal, QPalette::ColorRole role, - const QSettings &kdeSettings, const QString &key) +static inline bool kdeColor(QPalette *pal, QPalette::ColorRole role, const QVariant &value) { - const QVariant value = kdeSettings.value(key); if (!value.isValid()) return false; const QStringList values = value.toStringList(); @@ -282,9 +300,9 @@ static inline bool kdeColor(QPalette *pal, QPalette::ColorRole role, return true; } -void QKdeThemePrivate::readKdeSystemPalette(const QSettings &kdeSettings, QPalette *pal) +void QKdeThemePrivate::readKdeSystemPalette(const QStringList &kdeDirs, QHash<QString, QSettings*> &kdeSettings, QPalette *pal) { - if (!kdeSettings.contains(QStringLiteral("Colors:Button/BackgroundNormal"))) { + if (!kdeColor(pal, QPalette::Button, readKdeSetting(QStringLiteral("Colors:Button/BackgroundNormal"), kdeDirs, kdeSettings))) { // kcolorscheme.cpp: SetDefaultColors const QColor defaultWindowBackground(214, 210, 208); const QColor defaultButtonBackground(223, 220, 217); @@ -292,19 +310,18 @@ void QKdeThemePrivate::readKdeSystemPalette(const QSettings &kdeSettings, QPalet return; } - kdeColor(pal, QPalette::Button, kdeSettings, QStringLiteral("Colors:Button/BackgroundNormal")); - kdeColor(pal, QPalette::Window, kdeSettings, QStringLiteral("Colors:Window/BackgroundNormal")); - kdeColor(pal, QPalette::Text, kdeSettings, QStringLiteral("Colors:View/ForegroundNormal")); - kdeColor(pal, QPalette::WindowText, kdeSettings, QStringLiteral("Colors:Window/ForegroundNormal")); - kdeColor(pal, QPalette::Base, kdeSettings, QStringLiteral("Colors:View/BackgroundNormal")); - kdeColor(pal, QPalette::Highlight, kdeSettings, QStringLiteral("Colors:Selection/BackgroundNormal")); - kdeColor(pal, QPalette::HighlightedText, kdeSettings, QStringLiteral("Colors:Selection/ForegroundNormal")); - kdeColor(pal, QPalette::AlternateBase, kdeSettings, QStringLiteral("Colors:View/BackgroundAlternate")); - kdeColor(pal, QPalette::ButtonText, kdeSettings, QStringLiteral("Colors:Button/ForegroundNormal")); - kdeColor(pal, QPalette::Link, kdeSettings, QStringLiteral("Colors:View/ForegroundLink")); - kdeColor(pal, QPalette::LinkVisited, kdeSettings, QStringLiteral("Colors:View/ForegroundVisited")); - kdeColor(pal, QPalette::ToolTipBase, kdeSettings, QStringLiteral("Colors:Tooltip/BackgroundNormal")); - kdeColor(pal, QPalette::ToolTipText, kdeSettings, QStringLiteral("Colors:Tooltip/ForegroundNormal")); + kdeColor(pal, QPalette::Window, readKdeSetting(QStringLiteral("Colors:Window/BackgroundNormal"), kdeDirs, kdeSettings)); + kdeColor(pal, QPalette::Text, readKdeSetting(QStringLiteral("Colors:View/ForegroundNormal"), kdeDirs, kdeSettings)); + kdeColor(pal, QPalette::WindowText, readKdeSetting(QStringLiteral("Colors:Window/ForegroundNormal"), kdeDirs, kdeSettings)); + kdeColor(pal, QPalette::Base, readKdeSetting(QStringLiteral("Colors:View/BackgroundNormal"), kdeDirs, kdeSettings)); + kdeColor(pal, QPalette::Highlight, readKdeSetting(QStringLiteral("Colors:Selection/BackgroundNormal"), kdeDirs, kdeSettings)); + kdeColor(pal, QPalette::HighlightedText, readKdeSetting(QStringLiteral("Colors:Selection/ForegroundNormal"), kdeDirs, kdeSettings)); + kdeColor(pal, QPalette::AlternateBase, readKdeSetting(QStringLiteral("Colors:View/BackgroundAlternate"), kdeDirs, kdeSettings)); + kdeColor(pal, QPalette::ButtonText, readKdeSetting(QStringLiteral("Colors:Button/ForegroundNormal"), kdeDirs, kdeSettings)); + kdeColor(pal, QPalette::Link, readKdeSetting(QStringLiteral("Colors:View/ForegroundLink"), kdeDirs, kdeSettings)); + kdeColor(pal, QPalette::LinkVisited, readKdeSetting(QStringLiteral("Colors:View/ForegroundVisited"), kdeDirs, kdeSettings)); + kdeColor(pal, QPalette::ToolTipBase, readKdeSetting(QStringLiteral("Colors:Tooltip/BackgroundNormal"), kdeDirs, kdeSettings)); + kdeColor(pal, QPalette::ToolTipText, readKdeSetting(QStringLiteral("Colors:Tooltip/ForegroundNormal"), kdeDirs, kdeSettings)); // The above code sets _all_ color roles to "normal" colors. In KDE, the disabled // color roles are calculated by applying various effects described in kdeglobals. @@ -347,15 +364,14 @@ void QKdeThemePrivate::readKdeSystemPalette(const QSettings &kdeSettings, QPalet const char *QKdeTheme::name = "kde"; -QKdeTheme::QKdeTheme(const QString &kdeHome, int kdeVersion) - : QPlatformTheme(new QKdeThemePrivate(kdeHome,kdeVersion)) +QKdeTheme::QKdeTheme(const QStringList& kdeDirs, int kdeVersion) + : QPlatformTheme(new QKdeThemePrivate(kdeDirs,kdeVersion)) { d_func()->refresh(); } -QFont *QKdeThemePrivate::readKdeFontSetting(const QSettings &settings, const QString &key) +QFont *QKdeThemePrivate::kdeFont(const QVariant &fontValue) { - const QVariant fontValue = settings.value(key); if (fontValue.isValid()) { // Read font value: Might be a QStringList as KDE stores fonts without quotes. // Also retrieve the family for the constructor since we cannot use the @@ -382,16 +398,11 @@ QFont *QKdeThemePrivate::readKdeFontSetting(const QSettings &settings, const QSt } -QStringList QKdeThemePrivate::kdeIconThemeSearchPaths(const QString &kdeHome) +QStringList QKdeThemePrivate::kdeIconThemeSearchPaths(const QStringList &kdeDirs) { - QStringList candidates = QStringList(kdeHome); - const QString kdeDirs = QFile::decodeName(qgetenv("KDEDIRS")); - if (!kdeDirs.isEmpty()) - candidates.append(kdeDirs.split(QLatin1Char(':'))); - QStringList paths = QGenericUnixTheme::xdgIconThemePaths(); const QString iconPath = QStringLiteral("/share/icons"); - foreach (const QString &candidate, candidates) { + foreach (const QString &candidate, kdeDirs) { const QFileInfo fi(candidate + iconPath); if (fi.isDir()) paths.append(fi.absoluteFilePath()); @@ -418,7 +429,7 @@ QVariant QKdeTheme::themeHint(QPlatformTheme::ThemeHint hint) const case QPlatformTheme::SystemIconFallbackThemeName: return QVariant(d->iconFallbackThemeName); case QPlatformTheme::IconThemeSearchPaths: - return QVariant(d->kdeIconThemeSearchPaths(d->kdeHome)); + return QVariant(d->kdeIconThemeSearchPaths(d->kdeDirs)); case QPlatformTheme::StyleNames: return QVariant(d->styleNames); case QPlatformTheme::KeyboardScheme: @@ -445,26 +456,52 @@ const QFont *QKdeTheme::font(Font type) const QPlatformTheme *QKdeTheme::createKdeTheme() { - // Check for version >= 4 and determine home folder from environment, - // defaulting to ~/.kde<version>, ~/.kde const QByteArray kdeVersionBA = qgetenv("KDE_SESSION_VERSION"); const int kdeVersion = kdeVersionBA.toInt(); if (kdeVersion < 4) return 0; - const QString kdeHomePathVar = QString::fromLocal8Bit(qgetenv("KDEHOME")); + + // Determine KDE prefixes in the following priority order: + // - KDEHOME and KDEDIRS environment variables + // - ~/.kde(<version>) + // - read prefixes from /etc/kde<version>rc + // - fallback to /etc/kde<version> + + QStringList kdeDirs; + const QString kdeHomePathVar = QFile::decodeName(qgetenv("KDEHOME")); if (!kdeHomePathVar.isEmpty()) - return new QKdeTheme(kdeHomePathVar, kdeVersion); + kdeDirs += kdeHomePathVar; + + const QString kdeDirsVar = QFile::decodeName(qgetenv("KDEDIRS")); + if (!kdeDirsVar.isEmpty()) + kdeDirs += kdeDirsVar.split(QLatin1Char(':'), QString::SkipEmptyParts); + + const QString kdeVersionHomePath = QDir::homePath() + QStringLiteral("/.kde") + QLatin1String(kdeVersionBA); + if (QFileInfo(kdeVersionHomePath).isDir()) + kdeDirs += kdeVersionHomePath; - const QString kdeVersionHomePath = QDir::homePath() + QStringLiteral("/.kde") + QLatin1String(kdeVersionBA); - if (QFileInfo(kdeVersionHomePath).isDir()) - return new QKdeTheme(kdeVersionHomePath, kdeVersion); + const QString kdeHomePath = QDir::homePath() + QStringLiteral("/.kde"); + if (QFileInfo(kdeHomePath).isDir()) + kdeDirs += kdeHomePath; - const QString kdeHomePath = QDir::homePath() + QStringLiteral("/.kde"); - if (QFileInfo(kdeHomePath).isDir()) - return new QKdeTheme(kdeHomePath, kdeVersion); + const QString kdeRcPath = QStringLiteral("/etc/kde") + QLatin1String(kdeVersionBA) + QStringLiteral("rc"); + if (QFileInfo(kdeRcPath).isReadable()) { + QSettings kdeSettings(kdeRcPath, QSettings::IniFormat); + kdeSettings.beginGroup(QStringLiteral("Directories-default")); + kdeDirs += kdeSettings.value(QStringLiteral("prefixes")).toStringList(); + } + + const QString kdeVersionPrefix = QStringLiteral("/etc/kde") + QLatin1String(kdeVersionBA); + if (QFileInfo(kdeVersionPrefix).isDir()) + kdeDirs += kdeVersionPrefix; + + kdeDirs.removeDuplicates(); + if (kdeDirs.isEmpty()) { + qWarning("%s: Unable to determine KDE dirs", Q_FUNC_INFO); + return 0; + } - qWarning("%s: Unable to determine KDEHOME", Q_FUNC_INFO); - return 0; + return new QKdeTheme(kdeDirs, kdeVersion); } #endif // QT_NO_SETTINGS diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h b/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h index 36fcdd8dce..d01e6d485c 100644 --- a/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h +++ b/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h @@ -87,7 +87,7 @@ class QKdeTheme : public QPlatformTheme { Q_DECLARE_PRIVATE(QKdeTheme) public: - QKdeTheme(const QString &kdeHome, int kdeVersion); + QKdeTheme(const QStringList& kdeDirs, int kdeVersion); static QPlatformTheme *createKdeTheme(); virtual QVariant themeHint(ThemeHint hint) const; |