diff options
Diffstat (limited to 'src/platformsupport')
12 files changed, 246 insertions, 90 deletions
diff --git a/src/platformsupport/eglconvenience/qeglplatformintegration.cpp b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp index b48f993436..820c433a2c 100644 --- a/src/platformsupport/eglconvenience/qeglplatformintegration.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp @@ -189,7 +189,8 @@ QPlatformNativeInterface *QEGLPlatformIntegration::nativeInterface() const enum ResourceType { EglDisplay, EglWindow, - EglContext + EglContext, + NativeDisplay }; static int resourceType(const QByteArray &key) @@ -197,7 +198,8 @@ static int resourceType(const QByteArray &key) static const QByteArray names[] = { // match ResourceType QByteArrayLiteral("egldisplay"), QByteArrayLiteral("eglwindow"), - QByteArrayLiteral("eglcontext") + QByteArrayLiteral("eglcontext"), + QByteArrayLiteral("nativedisplay") }; const QByteArray *end = names + sizeof(names) / sizeof(names[0]); const QByteArray *result = std::find(names, end, key); @@ -214,6 +216,9 @@ void *QEGLPlatformIntegration::nativeResourceForIntegration(const QByteArray &re case EglDisplay: result = m_screen->display(); break; + case NativeDisplay: + result = reinterpret_cast<void*>(nativeDisplay()); + break; default: break; } 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/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/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; |