diff options
Diffstat (limited to 'src/platformsupport')
13 files changed, 802 insertions, 109 deletions
diff --git a/src/platformsupport/devicediscovery/qdevicediscovery_p.h b/src/platformsupport/devicediscovery/qdevicediscovery_p.h index c78c57b86f..d9bd9a78e4 100644 --- a/src/platformsupport/devicediscovery/qdevicediscovery_p.h +++ b/src/platformsupport/devicediscovery/qdevicediscovery_p.h @@ -72,7 +72,8 @@ public: Device_Touchscreen = 0x04, Device_Keyboard = 0x08, Device_DRM = 0x10, - Device_Tablet = 0x20, + Device_DRM_PrimaryGPU = 0x20, + Device_Tablet = 0x40, Device_InputMask = Device_Mouse | Device_Touchpad | Device_Touchscreen | Device_Keyboard | Device_Tablet, Device_VideoMask = Device_DRM }; diff --git a/src/platformsupport/devicediscovery/qdevicediscovery_udev.cpp b/src/platformsupport/devicediscovery/qdevicediscovery_udev.cpp index 9e0ce47e18..ac902b4140 100644 --- a/src/platformsupport/devicediscovery/qdevicediscovery_udev.cpp +++ b/src/platformsupport/devicediscovery/qdevicediscovery_udev.cpp @@ -149,8 +149,16 @@ QStringList QDeviceDiscovery::scanConnectedDevices() QString candidate = QString::fromUtf8(udev_device_get_devnode(udevice)); if ((m_types & Device_InputMask) && candidate.startsWith(QLatin1String(QT_EVDEV_DEVICE))) devices << candidate; - if ((m_types & Device_VideoMask) && candidate.startsWith(QLatin1String(QT_DRM_DEVICE))) - devices << candidate; + if ((m_types & Device_VideoMask) && candidate.startsWith(QLatin1String(QT_DRM_DEVICE))) { + if (m_types & Device_DRM_PrimaryGPU) { + udev_device *pci = udev_device_get_parent_with_subsystem_devtype(udevice, "pci", 0); + if (pci) { + if (qstrcmp(udev_device_get_sysattr_value(pci, "boot_vga"), "1") == 0) + devices << candidate; + } + } else + devices << candidate; + } udev_device_unref(udevice); } diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp index 8152f74067..34ba21afdc 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp @@ -106,6 +106,14 @@ bool QEGLPlatformContext::makeCurrent(QPlatformSurface *surface) EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface); + // shortcut: on some GPUs, eglMakeCurrent is not a cheap operation + if (eglGetCurrentContext() == m_eglContext && + eglGetCurrentDisplay() == m_eglDisplay && + eglGetCurrentSurface(EGL_READ) == eglSurface && + eglGetCurrentSurface(EGL_DRAW) == eglSurface) { + return true; + } + bool ok = eglMakeCurrent(m_eglDisplay, eglSurface, eglSurface, m_eglContext); if (!ok) qWarning("QEGLPlatformContext::makeCurrent: eglError: %x, this: %p \n", eglGetError(), this); diff --git a/src/platformsupport/eglconvenience/qxlibeglintegration.cpp b/src/platformsupport/eglconvenience/qxlibeglintegration.cpp index 58f24c0a04..80453816fc 100644 --- a/src/platformsupport/eglconvenience/qxlibeglintegration.cpp +++ b/src/platformsupport/eglconvenience/qxlibeglintegration.cpp @@ -41,17 +41,6 @@ #include "qxlibeglintegration_p.h" -static int countBits(unsigned long mask) -{ - int count = 0; - while (mask != 0) { - if (mask & 1) - ++count; - mask >>= 1; - } - return count; -} - VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLDisplay eglDisplay, EGLConfig config) { VisualID visualId = 0; @@ -92,9 +81,9 @@ VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLDisplay return visualId; } - int visualRedSize = countBits(chosenVisualInfo->red_mask); - int visualGreenSize = countBits(chosenVisualInfo->green_mask); - int visualBlueSize = countBits(chosenVisualInfo->blue_mask); + int visualRedSize = qPopulationCount(chosenVisualInfo->red_mask); + int visualGreenSize = qPopulationCount(chosenVisualInfo->green_mask); + int visualBlueSize = qPopulationCount(chosenVisualInfo->blue_mask); int visualAlphaSize = -1; // Need XRender to tell us the alpha channel size bool visualMatchesConfig = false; diff --git a/src/platformsupport/eventdispatchers/eventdispatchers.pri b/src/platformsupport/eventdispatchers/eventdispatchers.pri index 6e16a46b34..c9bbe1f5b7 100644 --- a/src/platformsupport/eventdispatchers/eventdispatchers.pri +++ b/src/platformsupport/eventdispatchers/eventdispatchers.pri @@ -8,6 +8,14 @@ HEADERS +=\ $$PWD/qgenericunixeventdispatcher_p.h\ } +ios { +OBJECTIVE_SOURCES +=\ + $$PWD/qeventdispatcher_cf.mm + +HEADERS +=\ + $$PWD/qeventdispatcher_cf_p.h +} + contains(QT_CONFIG, glib) { SOURCES +=$$PWD/qeventdispatcher_glib.cpp HEADERS +=$$PWD/qeventdispatcher_glib_p.h diff --git a/src/platformsupport/eventdispatchers/qeventdispatcher_cf.mm b/src/platformsupport/eventdispatchers/qeventdispatcher_cf.mm new file mode 100644 index 0000000000..78f97d5556 --- /dev/null +++ b/src/platformsupport/eventdispatchers/qeventdispatcher_cf.mm @@ -0,0 +1,353 @@ +/**************************************************************************** +** +** 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 "qeventdispatcher_cf_p.h" +#include <qdebug.h> +#include <qpa/qwindowsysteminterface.h> +#include <QtCore/QThread> +#include <QtCore/private/qcoreapplication_p.h> + +#include <limits> + +#include <UIKit/UIApplication.h> + +QT_BEGIN_NAMESPACE +QT_USE_NAMESPACE + +static const CFTimeInterval kCFTimeIntervalMinimum = 0; +static const CFTimeInterval kCFTimeIntervalDistantFuture = std::numeric_limits<CFTimeInterval>::max(); + +void QEventDispatcherCoreFoundation::nonBlockingTimerRunLoopCallback(CFRunLoopTimerRef, void *info) +{ + // The (one and only) CFRunLoopTimer has fired, which means that at least + // one QTimer should now fire as well. Note that CFRunLoopTimer's callback will + // never recurse. So if the app starts a new QEventLoop within this callback, other + // timers will stop working. The work-around is to forward the callback to a + // dedicated CFRunLoopSource that can recurse: + QEventDispatcherCoreFoundation *self = static_cast<QEventDispatcherCoreFoundation *>(info); + self->m_blockingTimerRunLoopSource.signal(); + // FIXME: And not wake up main run loop? +} + +void QEventDispatcherCoreFoundation::maybeStartCFRunLoopTimer() +{ + // Find out when the next registered timer should fire, and schedule + // runLoopTimer accordingly. If the runLoopTimer does not yet exist, and + // at least one timer is registered, start by creating the timer: + if (m_timerInfoList.isEmpty()) { + Q_ASSERT(m_runLoopTimerRef == 0); + return; + } + + CFAbsoluteTime ttf = CFAbsoluteTimeGetCurrent(); + CFTimeInterval interval; + + if (m_runLoopTimerRef == 0) { + // start the CFRunLoopTimer + + // calculate when the next timer should fire: + struct timespec tv; + if (m_timerInfoList.timerWait(tv)) { + interval = qMax(tv.tv_sec + tv.tv_nsec / 1000000000., 0.0000001); + } else { + // this shouldn't really happen, but in case it does, set the timer + // to fire a some point in the distant future: + interval = kCFTimeIntervalDistantFuture; + } + + ttf += interval; + CFRunLoopTimerContext info = { 0, this, 0, 0, 0 }; + // create the timer with a large interval, as recommended by the CFRunLoopTimerSetNextFireDate() + // documentation, since we will adjust the timer's time-to-fire as needed to keep Qt timers working + m_runLoopTimerRef = CFRunLoopTimerCreate(0, ttf, kCFTimeIntervalDistantFuture, 0, 0, QEventDispatcherCoreFoundation::nonBlockingTimerRunLoopCallback, &info); + Q_ASSERT(m_runLoopTimerRef != 0); + + CFRunLoopRef mainRunLoop = CFRunLoopGetMain(); + CFRunLoopAddTimer(mainRunLoop, m_runLoopTimerRef, kCFRunLoopCommonModes); + CFRunLoopAddTimer(mainRunLoop, m_runLoopTimerRef, (CFStringRef) UITrackingRunLoopMode); + } else { + struct timespec tv; + // Calculate when the next timer should fire: + if (m_timerInfoList.timerWait(tv)) { + interval = qMax(tv.tv_sec + tv.tv_nsec / 1000000000., 0.0000001); + } else { + // no timers can fire, but we cannot stop the CFRunLoopTimer, set the timer to fire at some + // point in the distant future (the timer interval is one year) + interval = CFRunLoopTimerGetInterval(m_runLoopTimerRef); + } + + ttf += interval; + CFRunLoopTimerSetNextFireDate(m_runLoopTimerRef, ttf); + } +} + +void QEventDispatcherCoreFoundation::maybeStopCFRunLoopTimer() +{ + if (m_runLoopTimerRef == 0) + return; + + CFRunLoopTimerInvalidate(m_runLoopTimerRef); + CFRelease(m_runLoopTimerRef); + m_runLoopTimerRef = 0; +} + +QEventDispatcherCoreFoundation::QEventDispatcherCoreFoundation(QObject *parent) + : QAbstractEventDispatcher(parent) + , m_interrupted(false) + , m_postedEventsRunLoopSource(this, &QEventDispatcherCoreFoundation::processPostedEvents) + , m_blockingTimerRunLoopSource(this, &QEventDispatcherCoreFoundation::processTimers) + , m_awakeAndBlockObserver(this, &QEventDispatcherCoreFoundation::handleRunLoopActivity, + kCFRunLoopBeforeWaiting | kCFRunLoopAfterWaiting) + , m_runLoopTimerRef(0) +{ + m_cfSocketNotifier.setHostEventDispatcher(this); + + m_postedEventsRunLoopSource.addToMode(kCFRunLoopCommonModes); + + m_blockingTimerRunLoopSource.addToMode(kCFRunLoopCommonModes); + m_blockingTimerRunLoopSource.addToMode(CFStringRef(UITrackingRunLoopMode)); + + m_awakeAndBlockObserver.addToMode(kCFRunLoopCommonModes); +} + +QEventDispatcherCoreFoundation::~QEventDispatcherCoreFoundation() +{ + qDeleteAll(m_timerInfoList); + maybeStopCFRunLoopTimer(); + + m_cfSocketNotifier.removeSocketNotifiers(); +} + +void QEventDispatcherCoreFoundation::processPostedEvents() +{ + QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::AllEvents); +} + +void QEventDispatcherCoreFoundation::processTimers() +{ + // TODO: + // We also need to block this new timer source + // along with the posted event source when calling processEvents() + // "manually" to prevent livelock deep in CFRunLoop. + + m_timerInfoList.activateTimers(); + maybeStartCFRunLoopTimer(); +} + +void QEventDispatcherCoreFoundation::handleRunLoopActivity(CFRunLoopActivity activity) +{ + switch (activity) { + case kCFRunLoopBeforeWaiting: + emit aboutToBlock(); + break; + case kCFRunLoopAfterWaiting: + emit awake(); + break; + default: + Q_UNREACHABLE(); + } +} + +bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlags flags) +{ + m_interrupted = false; + bool eventsProcessed = false; + + // The documentation states that this signal is emitted after the event + // loop returns from a function that could block, which is not the case + // here, but all the other event dispatchers emit awake at the start of + // processEvents, and the QEventLoop auto-test has an explicit check for + // this behavior, so we assume it's for a good reason and do it as well. + emit awake(); + + bool excludeUserEvents = flags & QEventLoop::ExcludeUserInputEvents; + bool execFlagSet = (flags & QEventLoop::DialogExec) || (flags & QEventLoop::EventLoopExec); + bool useExecMode = execFlagSet && !excludeUserEvents; + + SInt32 result; + + if (useExecMode) { + while (!m_interrupted) { + // Run a single pass on the runloop to unblock it + result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, kCFTimeIntervalMinimum, true); + + // Run the default runloop until interrupted (by Qt or UIKit) + if (result != kCFRunLoopRunFinished) + result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, kCFTimeIntervalDistantFuture, false); + + // App has quit or Qt has interrupted? + if (result == kCFRunLoopRunFinished || m_interrupted) + break; + + // Runloop was interrupted by UIKit? + if (result == kCFRunLoopRunStopped && !m_interrupted) { + // Run runloop in UI tracking mode + if (CFRunLoopRunInMode((CFStringRef) UITrackingRunLoopMode, + kCFTimeIntervalDistantFuture, false) == kCFRunLoopRunFinished) + break; + } + } + eventsProcessed = true; + } else { + if (!(flags & QEventLoop::WaitForMoreEvents)) + wakeUp(); + + // Run runloop in default mode + result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, kCFTimeIntervalDistantFuture, true); + if (result != kCFRunLoopRunFinished) { + // Run runloop in UI tracking mode + CFRunLoopRunInMode((CFStringRef) UITrackingRunLoopMode, kCFTimeIntervalDistantFuture, false); + } + eventsProcessed = (result == kCFRunLoopRunHandledSource); + } + return eventsProcessed; +} + +bool QEventDispatcherCoreFoundation::hasPendingEvents() +{ + qDebug() << __FUNCTION__ << "not implemented"; + return false; +} + +void QEventDispatcherCoreFoundation::registerSocketNotifier(QSocketNotifier *notifier) +{ + m_cfSocketNotifier.registerSocketNotifier(notifier); +} + +void QEventDispatcherCoreFoundation::unregisterSocketNotifier(QSocketNotifier *notifier) +{ + m_cfSocketNotifier.unregisterSocketNotifier(notifier); +} + +void QEventDispatcherCoreFoundation::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *obj) +{ +#ifndef QT_NO_DEBUG + if (timerId < 1 || interval < 0 || !obj) { + qWarning("QEventDispatcherCoreFoundation::registerTimer: invalid arguments"); + return; + } else if (obj->thread() != thread() || thread() != QThread::currentThread()) { + qWarning("QEventDispatcherCoreFoundation: timers cannot be started from another thread"); + return; + } +#endif + + m_timerInfoList.registerTimer(timerId, interval, timerType, obj); + maybeStartCFRunLoopTimer(); +} + +bool QEventDispatcherCoreFoundation::unregisterTimer(int timerId) +{ +#ifndef QT_NO_DEBUG + if (timerId < 1) { + qWarning("QEventDispatcherCoreFoundation::unregisterTimer: invalid argument"); + return false; + } else if (thread() != QThread::currentThread()) { + qWarning("QObject::killTimer: timers cannot be stopped from another thread"); + return false; + } +#endif + + bool returnValue = m_timerInfoList.unregisterTimer(timerId); + m_timerInfoList.isEmpty() ? maybeStopCFRunLoopTimer() : maybeStartCFRunLoopTimer(); + return returnValue; +} + +bool QEventDispatcherCoreFoundation::unregisterTimers(QObject *object) +{ +#ifndef QT_NO_DEBUG + if (!object) { + qWarning("QEventDispatcherCoreFoundation::unregisterTimers: invalid argument"); + return false; + } else if (object->thread() != thread() || thread() != QThread::currentThread()) { + qWarning("QObject::killTimers: timers cannot be stopped from another thread"); + return false; + } +#endif + + bool returnValue = m_timerInfoList.unregisterTimers(object); + m_timerInfoList.isEmpty() ? maybeStopCFRunLoopTimer() : maybeStartCFRunLoopTimer(); + return returnValue; +} + +QList<QAbstractEventDispatcher::TimerInfo> QEventDispatcherCoreFoundation::registeredTimers(QObject *object) const +{ +#ifndef QT_NO_DEBUG + if (!object) { + qWarning("QEventDispatcherCoreFoundation:registeredTimers: invalid argument"); + return QList<TimerInfo>(); + } +#endif + + return m_timerInfoList.registeredTimers(object); +} + +int QEventDispatcherCoreFoundation::remainingTime(int timerId) +{ +#ifndef QT_NO_DEBUG + if (timerId < 1) { + qWarning("QEventDispatcherCoreFoundation::remainingTime: invalid argument"); + return -1; + } +#endif + + return m_timerInfoList.timerRemainingTime(timerId); +} + +void QEventDispatcherCoreFoundation::wakeUp() +{ + m_postedEventsRunLoopSource.signal(); + CFRunLoopWakeUp(CFRunLoopGetMain()); +} + +void QEventDispatcherCoreFoundation::interrupt() +{ + // Stop the runloop, which will cause processEvents() to exit + m_interrupted = true; + CFRunLoopStop(CFRunLoopGetMain()); +} + +void QEventDispatcherCoreFoundation::flush() +{ + // X11 only. +} + +QT_END_NAMESPACE + diff --git a/src/platformsupport/eventdispatchers/qeventdispatcher_cf_p.h b/src/platformsupport/eventdispatchers/qeventdispatcher_cf_p.h new file mode 100644 index 0000000000..e23b8f0ece --- /dev/null +++ b/src/platformsupport/eventdispatchers/qeventdispatcher_cf_p.h @@ -0,0 +1,228 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +/**************************************************************************** +** +** Copyright (c) 2007-2008, Apple, Inc. +** +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** +** * Neither the name of Apple, Inc. nor the names of its contributors +** may be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#ifndef QEVENTDISPATCHER_CF_P_H +#define QEVENTDISPATCHER_CF_P_H + +#include <QtCore/qabstracteventdispatcher.h> +#include <QtCore/private/qtimerinfo_unix_p.h> +#include <QtPlatformSupport/private/qcfsocketnotifier_p.h> +#include <CoreFoundation/CoreFoundation.h> + +QT_BEGIN_NAMESPACE + +class QEventDispatcherCoreFoundation; + +template <class T = QEventDispatcherCoreFoundation> +class RunLoopSource +{ +public: + typedef void (T::*CallbackFunction) (); + + enum { kHighestPriority = 0 } RunLoopSourcePriority; + + RunLoopSource(T *delegate, CallbackFunction callback) + : m_delegate(delegate), m_callback(callback) + { + CFRunLoopSourceContext context = {}; + context.info = this; + context.perform = RunLoopSource::process; + + m_source = CFRunLoopSourceCreate(kCFAllocatorDefault, kHighestPriority, &context); + Q_ASSERT(m_source); + } + + ~RunLoopSource() + { + CFRunLoopSourceInvalidate(m_source); + CFRelease(m_source); + } + + void addToMode(CFStringRef mode, CFRunLoopRef runLoop = 0) + { + if (!runLoop) + runLoop = CFRunLoopGetCurrent(); + + CFRunLoopAddSource(runLoop, m_source, mode); + } + + void signal() { CFRunLoopSourceSignal(m_source); } + +private: + static void process(void *info) + { + RunLoopSource *self = static_cast<RunLoopSource *>(info); + ((self->m_delegate)->*(self->m_callback))(); + } + + T *m_delegate; + CallbackFunction m_callback; + CFRunLoopSourceRef m_source; +}; + +template <class T = QEventDispatcherCoreFoundation> +class RunLoopObserver +{ +public: + typedef void (T::*CallbackFunction) (CFRunLoopActivity activity); + + RunLoopObserver(T *delegate, CallbackFunction callback, CFOptionFlags activities) + : m_delegate(delegate), m_callback(callback) + { + CFRunLoopObserverContext context = {}; + context.info = this; + + m_observer = CFRunLoopObserverCreate(kCFAllocatorDefault, activities, true, 0, process, &context); + Q_ASSERT(m_observer); + } + + ~RunLoopObserver() + { + CFRunLoopObserverInvalidate(m_observer); + CFRelease(m_observer); + } + + void addToMode(CFStringRef mode, CFRunLoopRef runLoop = 0) + { + if (!runLoop) + runLoop = CFRunLoopGetCurrent(); + + CFRunLoopAddObserver(runLoop, m_observer, mode); + } + +private: + static void process(CFRunLoopObserverRef, CFRunLoopActivity activity, void *info) + { + RunLoopObserver *self = static_cast<RunLoopObserver *>(info); + ((self->m_delegate)->*(self->m_callback))(activity); + } + + T *m_delegate; + CallbackFunction m_callback; + CFRunLoopObserverRef m_observer; +}; + +class QEventDispatcherCoreFoundation : public QAbstractEventDispatcher +{ + Q_OBJECT + +public: + explicit QEventDispatcherCoreFoundation(QObject *parent = 0); + ~QEventDispatcherCoreFoundation(); + + bool processEvents(QEventLoop::ProcessEventsFlags flags); + bool hasPendingEvents(); + + void registerSocketNotifier(QSocketNotifier *notifier); + void unregisterSocketNotifier(QSocketNotifier *notifier); + + void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object); + bool unregisterTimer(int timerId); + bool unregisterTimers(QObject *object); + QList<QAbstractEventDispatcher::TimerInfo> registeredTimers(QObject *object) const; + + int remainingTime(int timerId); + + void wakeUp(); + void interrupt(); + void flush(); + +private: + bool m_interrupted; + + RunLoopSource<> m_postedEventsRunLoopSource; + RunLoopSource<> m_blockingTimerRunLoopSource; + + RunLoopObserver<> m_awakeAndBlockObserver; + + QTimerInfoList m_timerInfoList; + CFRunLoopTimerRef m_runLoopTimerRef; + + QCFSocketNotifier m_cfSocketNotifier; + + void processPostedEvents(); + void processTimers(); + + void maybeStartCFRunLoopTimer(); + void maybeStopCFRunLoopTimer(); + + void handleRunLoopActivity(CFRunLoopActivity activity); + + static void nonBlockingTimerRunLoopCallback(CFRunLoopTimerRef, void *info); +}; + +QT_END_NAMESPACE + +#endif // QEVENTDISPATCHER_CF_P_H diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index afe634dc4b..6b8a82352d 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -317,8 +317,6 @@ static const char *getFcFamilyForStyleHint(const QFont::StyleHint style) return stylehint; } -Q_GUI_EXPORT void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias); - void QFontconfigDatabase::populateFontDatabase() { FcFontSet *fonts; @@ -453,7 +451,7 @@ void QFontconfigDatabase::populateFontDatabase() // 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) - qt_registerAliasToFontFamily(familyName, QString::fromUtf8((const char *)value)); + QPlatformFontDatabase::registerAliasToFontFamily(familyName, QString::fromUtf8((const char *)value)); } FcFontSetDestroy (fonts); diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index 1e15a9e62c..5139f11d23 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -176,6 +176,10 @@ QCoreTextFontDatabase::~QCoreTextFontDatabase() void QCoreTextFontDatabase::populateFontDatabase() { + // The caller (QFontDB) expects the db to be populate only with system fonts, so we need + // to make sure that any previously registered app fonts become invisible. + removeApplicationFonts(); + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; QCFType<CTFontCollectionRef> collection = CTFontCollectionCreateFromAvailableFonts(0); @@ -186,82 +190,87 @@ void QCoreTextFontDatabase::populateFontDatabase() if (! fonts) return; - QString foundryName = QLatin1String("CoreText"); const int numFonts = CFArrayGetCount(fonts); for (int i = 0; i < numFonts; ++i) { CTFontDescriptorRef font = (CTFontDescriptorRef) CFArrayGetValueAtIndex(fonts, i); - QCFString familyName = (CFStringRef) CTFontDescriptorCopyLocalizedAttribute(font, kCTFontFamilyNameAttribute, NULL); - QCFString styleName = (CFStringRef)CTFontDescriptorCopyLocalizedAttribute(font, kCTFontStyleNameAttribute, NULL); - QCFType<CFDictionaryRef> styles = (CFDictionaryRef) CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute); - QFont::Weight weight = QFont::Normal; - QFont::Style style = QFont::StyleNormal; - QFont::Stretch stretch = QFont::Unstretched; - bool fixedPitch = false; - - if (styles) { - if (CFNumberRef weightValue = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontWeightTrait)) { - Q_ASSERT(CFNumberIsFloatType(weightValue)); - double d; - if (CFNumberGetValue(weightValue, kCFNumberDoubleType, &d)) - weight = (d > 0.0) ? QFont::Bold : QFont::Normal; - } - if (CFNumberRef italic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSlantTrait)) { - Q_ASSERT(CFNumberIsFloatType(italic)); - double d; - if (CFNumberGetValue(italic, kCFNumberDoubleType, &d)) { - if (d > 0.0) - style = QFont::StyleItalic; - } - } - if (CFNumberRef symbolic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSymbolicTrait)) { - int d; - if (CFNumberGetValue(symbolic, kCFNumberSInt32Type, &d)) { - if (d & kCTFontMonoSpaceTrait) - fixedPitch = true; - if (d & kCTFontExpandedTrait) - stretch = QFont::Expanded; - else if (d & kCTFontCondensedTrait) - stretch = QFont::Condensed; - } - } - } + populateFromDescriptor(font); + } - int pixelSize = 0; - if (QCFType<CFNumberRef> size = (CFNumberRef) CTFontDescriptorCopyAttribute(font, kCTFontSizeAttribute)) { - if (CFNumberIsFloatType(size)) { - double d; - CFNumberGetValue(size, kCFNumberDoubleType, &d); - pixelSize = d; - } else { - CFNumberGetValue(size, kCFNumberIntType, &pixelSize); + [pool release]; +} + +void QCoreTextFontDatabase::populateFromDescriptor(CTFontDescriptorRef font) +{ + QString foundryName = QStringLiteral("CoreText"); + QCFString familyName = (CFStringRef) CTFontDescriptorCopyLocalizedAttribute(font, kCTFontFamilyNameAttribute, NULL); + QCFString styleName = (CFStringRef)CTFontDescriptorCopyLocalizedAttribute(font, kCTFontStyleNameAttribute, NULL); + QCFType<CFDictionaryRef> styles = (CFDictionaryRef) CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute); + QFont::Weight weight = QFont::Normal; + QFont::Style style = QFont::StyleNormal; + QFont::Stretch stretch = QFont::Unstretched; + bool fixedPitch = false; + + if (styles) { + if (CFNumberRef weightValue = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontWeightTrait)) { + Q_ASSERT(CFNumberIsFloatType(weightValue)); + double d; + if (CFNumberGetValue(weightValue, kCFNumberDoubleType, &d)) + weight = (d > 0.0) ? QFont::Bold : QFont::Normal; + } + if (CFNumberRef italic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSlantTrait)) { + Q_ASSERT(CFNumberIsFloatType(italic)); + double d; + if (CFNumberGetValue(italic, kCFNumberDoubleType, &d)) { + if (d > 0.0) + style = QFont::StyleItalic; } } - - QSupportedWritingSystems writingSystems; - if (QCFType<CFArrayRef> languages = (CFArrayRef) CTFontDescriptorCopyAttribute(font, kCTFontLanguagesAttribute)) { - CFIndex length = CFArrayGetCount(languages); - for (int i = 1; i < LanguageCount; ++i) { - if (!languageForWritingSystem[i]) - continue; - QCFString lang = CFStringCreateWithCString(NULL, languageForWritingSystem[i], kCFStringEncodingASCII); - if (CFArrayContainsValue(languages, CFRangeMake(0, length), lang)) - writingSystems.setSupported(QFontDatabase::WritingSystem(i)); + if (CFNumberRef symbolic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSymbolicTrait)) { + int d; + if (CFNumberGetValue(symbolic, kCFNumberSInt32Type, &d)) { + if (d & kCTFontMonoSpaceTrait) + fixedPitch = true; + if (d & kCTFontExpandedTrait) + stretch = QFont::Expanded; + else if (d & kCTFontCondensedTrait) + stretch = QFont::Condensed; } } + } - CFRetain(font); - QPlatformFontDatabase::registerFont(familyName, styleName, foundryName, weight, style, stretch, - true /* antialiased */, true /* scalable */, - pixelSize, fixedPitch, writingSystems, (void *) font); + int pixelSize = 0; + if (QCFType<CFNumberRef> size = (CFNumberRef) CTFontDescriptorCopyAttribute(font, kCTFontSizeAttribute)) { + if (CFNumberIsFloatType(size)) { + double d; + CFNumberGetValue(size, kCFNumberDoubleType, &d); + pixelSize = d; + } else { + CFNumberGetValue(size, kCFNumberIntType, &pixelSize); + } + } - // We need to map back and forth between PostScript-names and family-names for fallback list construction - CFStringRef psName = (CFStringRef) CTFontDescriptorCopyAttribute(font, kCTFontNameAttribute); - psNameToFamily[QCFString::toQString((NSString *) psName)] = familyName; - familyNameToPsName[familyName] = QCFString::toQString((NSString *) psName); - CFRelease(psName); + QSupportedWritingSystems writingSystems; + if (QCFType<CFArrayRef> languages = (CFArrayRef) CTFontDescriptorCopyAttribute(font, kCTFontLanguagesAttribute)) { + CFIndex length = CFArrayGetCount(languages); + for (int i = 1; i < LanguageCount; ++i) { + if (!languageForWritingSystem[i]) + continue; + QCFString lang = CFStringCreateWithCString(NULL, languageForWritingSystem[i], kCFStringEncodingASCII); + if (CFArrayContainsValue(languages, CFRangeMake(0, length), lang)) + writingSystems.setSupported(QFontDatabase::WritingSystem(i)); + } } - [pool release]; + CFRetain(font); + QPlatformFontDatabase::registerFont(familyName, styleName, foundryName, weight, style, stretch, + true /* antialiased */, true /* scalable */, + pixelSize, fixedPitch, writingSystems, (void *) font); + + // We need to map back and forth between PostScript-names and family-names for fallback list construction + CFStringRef psName = (CFStringRef) CTFontDescriptorCopyAttribute(font, kCTFontNameAttribute); + psNameToFamily[QCFString::toQString((NSString *) psName)] = familyName; + familyNameToPsName[familyName] = QCFString::toQString((NSString *) psName); + CFRelease(psName); } void QCoreTextFontDatabase::releaseHandle(void *handle) @@ -473,6 +482,7 @@ QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData 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); @@ -484,12 +494,13 @@ QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData QCFType<CFURLRef> fontURL = CFURLCreateWithFileSystemPath(NULL, QCFString(fileName), kCFURLPOSIXPathStyle, false); bool success = CTFontManagerRegisterFontsForURL(fontURL, kCTFontManagerScopeProcess, &error); if (success) { - const void *keys[] = { fontURL }; - const void *values[] = { kCTFontURLAttribute }; + 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); @@ -499,6 +510,10 @@ QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData if (font) { QStringList families; families.append(QCFString(CTFontCopyFamilyName(font))); + + QCFType<CTFontDescriptorRef> descriptor = CTFontCopyFontDescriptor(font); + populateFromDescriptor(descriptor); + CFRelease(font); return families; } @@ -534,9 +549,12 @@ QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData 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))); } + m_applicationFonts.append(fontContainer); return families; } #endif @@ -569,5 +587,28 @@ QList<int> QCoreTextFontDatabase::standardSizes() const return ret; } +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 + for (int i = 0; i < m_applicationFonts.count(); ++i) + ATSFontDeactivate(m_applicationFonts[i], 0, kATSOptionFlagsDoNotNotify); + m_applicationFonts.clear(); + ATSFontNotify(kATSFontNotifyActionFontsChanged, 0); +#endif +#endif +} + QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h index 8536ad9123..c3bb4d428a 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h @@ -43,6 +43,14 @@ #define QCORETEXTFONTDATABASE_H #include <qpa/qplatformfontdatabase.h> +#include <private/qcore_mac_p.h> + +#ifndef Q_OS_IOS +#include <ApplicationServices/ApplicationServices.h> +#else +#include <CoreText/CoreText.h> +#include <CoreGraphics/CoreGraphics.h> +#endif QT_BEGIN_NAMESPACE @@ -63,9 +71,21 @@ public: QList<int> standardSizes() const; private: + void populateFromDescriptor(CTFontDescriptorRef font); + mutable QString defaultFontName; mutable QHash<QString, QString> psNameToFamily; 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; +#else + QVector<ATSFontContainerRef> m_applicationFonts; +#endif +#endif }; QT_END_NAMESPACE diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp index d42251d4dd..231576ed01 100644 --- a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp +++ b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp @@ -2242,11 +2242,14 @@ bool AtSpiAdaptor::tableInterface(QAccessibleInterface *interface, const QString col = index % cols; QAccessibleTableCellInterface *cell = interface->tableInterface()->cellAt(row, col)->tableCellInterface(); if (cell) { - cell->rowColumnExtents(&row, &col, &rowExtents, &colExtents, &isSelected); + row = cell->rowIndex(); + col = cell->columnIndex(); + rowExtents = cell->rowExtent(); + colExtents = cell->columnExtent(); + isSelected = cell->isSelected(); success = true; } } - QVariantList list; list << success << row << col << rowExtents << colExtents << isSelected; connection.send(message.createReply(list)); diff --git a/src/platformsupport/services/genericunix/qgenericunixservices.cpp b/src/platformsupport/services/genericunix/qgenericunixservices.cpp index fedaa3a655..77ea0f1db8 100644 --- a/src/platformsupport/services/genericunix/qgenericunixservices.cpp +++ b/src/platformsupport/services/genericunix/qgenericunixservices.cpp @@ -54,16 +54,24 @@ enum { debug = 0 }; static inline QByteArray detectDesktopEnvironment() { - if (!qEnvironmentVariableIsEmpty("KDE_FULL_SESSION")) - return QByteArray("KDE"); - // Check Unity first, whose older versions also have "GNOME_DESKTOP_SESSION_ID" set. const QByteArray xdgCurrentDesktop = qgetenv("XDG_CURRENT_DESKTOP"); - if (xdgCurrentDesktop == "Unity") - return QByteArrayLiteral("UNITY"); - // GNOME_DESKTOP_SESSION_ID is deprecated for some reason, but still check it - if (qgetenv("DESKTOP_SESSION") == "gnome" || !qEnvironmentVariableIsEmpty("GNOME_DESKTOP_SESSION_ID")) - return QByteArray("GNOME"); - return QByteArray("UNKNOWN"); + if (!xdgCurrentDesktop.isEmpty()) + return xdgCurrentDesktop.toUpper(); // KDE, GNOME, UNITY, LXDE, MATE, XFCE... + + // Classic fallbacks + if (!qEnvironmentVariableIsEmpty("KDE_FULL_SESSION")) + return QByteArrayLiteral("KDE"); + if (!qEnvironmentVariableIsEmpty("GNOME_DESKTOP_SESSION_ID")) + return QByteArrayLiteral("GNOME"); + + // Fallback to checking $DESKTOP_SESSION (unreliable) + const QByteArray desktopSession = qgetenv("DESKTOP_SESSION"); + if (desktopSession == "gnome") + return QByteArrayLiteral("GNOME"); + if (desktopSession == "xfce") + return QByteArrayLiteral("XFCE"); + + return QByteArrayLiteral("UNKNOWN"); } static inline bool checkExecutable(const QString &candidate, QString *result) diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp index fdd45a49c5..fb50230382 100644 --- a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp +++ b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp @@ -95,9 +95,13 @@ public: QGenericUnixThemePrivate() : QPlatformThemePrivate() , systemFont(QLatin1String(defaultSystemFontNameC), defaultSystemFontSize) - { } + , fixedFont(QStringLiteral("monospace"), systemFont.pointSize()) + { + fixedFont.setStyleHint(QFont::TypeWriter); + } const QFont systemFont; + QFont fixedFont; }; QGenericUnixTheme::QGenericUnixTheme() @@ -108,9 +112,14 @@ QGenericUnixTheme::QGenericUnixTheme() const QFont *QGenericUnixTheme::font(Font type) const { Q_D(const QGenericUnixTheme); - if (type == QPlatformTheme::SystemFont) + switch (type) { + case QPlatformTheme::SystemFont: return &d->systemFont; - return 0; + case QPlatformTheme::FixedFont: + return &d->fixedFont; + default: + return 0; + } } // Helper to return the icon theme paths from XDG. @@ -240,11 +249,18 @@ void QKdeThemePrivate::refresh() toolButtonStyle = Qt::ToolButtonTextUnderIcon; } - // Read system font, ignore 'fixed' 'smallestReadableFont' - if (QFont *systemFont = readKdeFontSetting(kdeSettings, QStringLiteral("font"))) { + // Read system font, ignore 'smallestReadableFont' + if (QFont *systemFont = readKdeFontSetting(kdeSettings, QStringLiteral("font"))) resources.fonts[QPlatformTheme::SystemFont] = systemFont; - } else { + else resources.fonts[QPlatformTheme::SystemFont] = new QFont(QLatin1String(defaultSystemFontNameC), defaultSystemFontSize); + + if (QFont *fixedFont = readKdeFontSetting(kdeSettings, QStringLiteral("fixed"))) { + resources.fonts[QPlatformTheme::FixedFont] = fixedFont; + } else { + fixedFont = new QFont(QLatin1String(defaultSystemFontNameC), defaultSystemFontSize); + fixedFont->setStyleHint(QFont::TypeWriter); + resources.fonts[QPlatformTheme::FixedFont] = fixedFont; } } @@ -461,9 +477,13 @@ class QGnomeThemePrivate : public QPlatformThemePrivate public: QGnomeThemePrivate() : systemFont(QLatin1Literal(defaultSystemFontNameC), defaultSystemFontSize) - {} + , fixedFont(QStringLiteral("monospace"), systemFont.pointSize()) + { + fixedFont.setStyleHint(QFont::TypeWriter); + } const QFont systemFont; + QFont fixedFont; }; QGnomeTheme::QGnomeTheme() @@ -501,10 +521,14 @@ QVariant QGnomeTheme::themeHint(QPlatformTheme::ThemeHint hint) const const QFont *QGnomeTheme::font(Font type) const { Q_D(const QGnomeTheme); - if (type == QPlatformTheme::SystemFont) - return &d->systemFont; - - return 0; + switch (type) { + case QPlatformTheme::SystemFont: + return &d->systemFont; + case QPlatformTheme::FixedFont: + return &d->fixedFont; + default: + return 0; + } } /*! @@ -534,7 +558,11 @@ QStringList QGenericUnixTheme::themeNames() #ifndef QT_NO_SETTINGS result.push_back(QLatin1String(QKdeTheme::name)); #endif - } else { // Gnome, Unity, other Gtk-based desktops like XFCE. + } else if (desktopEnvironment == QByteArrayLiteral("GNOME") || + desktopEnvironment == QByteArrayLiteral("UNITY") || + desktopEnvironment == QByteArrayLiteral("MATE") || + desktopEnvironment == QByteArrayLiteral("XFCE") || + desktopEnvironment == QByteArrayLiteral("LXDE")) { // Gtk-based desktops // prefer the GTK2 theme implementation with native dialogs etc. result.push_back(QStringLiteral("gtk2")); // fallback to the generic Gnome theme if loading the GTK2 theme fails |