diff options
Diffstat (limited to 'src/corelib/kernel')
21 files changed, 1049 insertions, 59 deletions
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 7625a74381..4c43f292fb 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -68,16 +68,21 @@ SOURCES += \ win32 { SOURCES += \ - kernel/qeventdispatcher_win.cpp \ kernel/qcoreapplication_win.cpp \ kernel/qwineventnotifier.cpp \ kernel/qsharedmemory_win.cpp \ kernel/qsystemsemaphore_win.cpp HEADERS += \ - kernel/qeventdispatcher_win_p.h \ kernel/qwineventnotifier.h -} + winrt { + SOURCES += kernel/qeventdispatcher_winrt.cpp + HEADERS += kernel/qeventdispatcher_winrt_p.h + } else { + SOURCES += kernel/qeventdispatcher_win.cpp + HEADERS += kernel/qeventdispatcher_win_p.h + } +} wince*: { SOURCES += \ @@ -86,6 +91,13 @@ wince*: { kernel/qfunctions_wince.h } +winrt { + SOURCES += \ + kernel/qfunctions_winrt.cpp + HEADERS += \ + kernel/qfunctions_winrt.h +} + mac { SOURCES += \ kernel/qcoreapplication_mac.cpp diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index 8c0589fdc6..7ab632d7a0 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -117,6 +117,8 @@ inline bool operator<(const timespec &t1, const timespec &t2) { return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_nsec < t2.tv_nsec); } inline bool operator==(const timespec &t1, const timespec &t2) { return t1.tv_sec == t2.tv_sec && t1.tv_nsec == t2.tv_nsec; } +inline bool operator!=(const timespec &t1, const timespec &t2) +{ return !(t1 == t2); } inline timespec &operator+=(timespec &t1, const timespec &t2) { t1.tv_sec += t2.tv_sec; diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index e77d6894d0..2dd56423ac 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -85,7 +85,11 @@ # endif #endif #ifdef Q_OS_WIN +# ifdef Q_OS_WINRT +# include "qeventdispatcher_winrt_p.h" +# else # include "qeventdispatcher_win_p.h" +# endif #endif #endif // QT_NO_QOBJECT @@ -98,6 +102,7 @@ #ifdef Q_OS_UNIX # include <locale.h> # include <unistd.h> +# include <sys/types.h> #endif #ifdef Q_OS_VXWORKS @@ -134,6 +139,8 @@ extern QString qAppFileName(); #endif int QCoreApplicationPrivate::app_compile_version = 0x050000; //we don't know exactly, but it's at least 5.0.0 +bool QCoreApplicationPrivate::setuidAllowed = false; + #if !defined(Q_OS_WIN) #ifdef Q_OS_MAC QString QCoreApplicationPrivate::macMenuBarName() @@ -410,6 +417,11 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint QCoreApplicationPrivate::is_app_closing = false; # if defined(Q_OS_UNIX) + if (!setuidAllowed && (geteuid() != getuid())) + qFatal("FATAL: The application binary appears to be running setuid, this is a security hole."); +# endif // Q_OS_UNIX + +# if defined(Q_OS_UNIX) qt_application_thread_id = QThread::currentThreadId(); # endif @@ -471,6 +483,8 @@ void QCoreApplicationPrivate::createEventDispatcher() # endif eventDispatcher = new QEventDispatcherUNIX(q); # endif +#elif defined(Q_OS_WINRT) + eventDispatcher = new QEventDispatcherWinRT(q); #elif defined(Q_OS_WIN) eventDispatcher = new QEventDispatcherWin32(q); #else @@ -518,6 +532,10 @@ void QCoreApplicationPrivate::appendApplicationPathToLibraryPaths() coreappdata()->app_libpaths = app_libpaths = new QStringList; QString app_location = QCoreApplication::applicationFilePath(); app_location.truncate(app_location.lastIndexOf(QLatin1Char('/'))); +#ifdef Q_OS_WINRT + if (app_location.isEmpty()) + app_location.append(QLatin1Char('/')); +#endif app_location = QDir(app_location).canonicalPath(); if (QFile::exists(app_location) && !app_libpaths->contains(app_location)) app_libpaths->append(app_location); @@ -786,6 +804,44 @@ QCoreApplication::~QCoreApplication() #endif } +/*! + \since 5.3 + + Allows the application to run setuid on UNIX platforms if \a allow + is true. + + If \a allow is false (the default) and Qt detects the application is + running with an effective user id different than the real user id, + the application will be aborted when a QCoreApplication instance is + created. + + Qt is not an appropriate solution for setuid programs due to its + large attack surface. However some applications may be required + to run in this manner for historical reasons. This flag will + prevent Qt from aborting the application when this is detected, + and must be set before a QCoreApplication instance is created. + + \note It is strongly recommended not to enable this option since + it introduces security risks. +*/ +void QCoreApplication::setSetuidAllowed(bool allow) +{ + QCoreApplicationPrivate::setuidAllowed = allow; +} + +/*! + \since 5.3 + + Returns true if the application is allowed to run setuid on UNIX + platforms. + + \sa QCoreApplication::setSetuidAllowed() +*/ +bool QCoreApplication::isSetuidAllowed() +{ + return QCoreApplicationPrivate::setuidAllowed; +} + /*! Sets the attribute \a attribute if \a on is true; diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h index ae17aeec0e..c2843030fd 100644 --- a/src/corelib/kernel/qcoreapplication.h +++ b/src/corelib/kernel/qcoreapplication.h @@ -112,6 +112,9 @@ public: static void setApplicationVersion(const QString &version); static QString applicationVersion(); + static void setSetuidAllowed(bool allow); + static bool isSetuidAllowed(); + static QCoreApplication *instance() { return self; } #ifndef QT_NO_QOBJECT diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index 0c00f396b5..c3d83112ae 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -153,6 +153,7 @@ public: static bool is_app_closing; #endif + static bool setuidAllowed; static uint attribs; static inline bool testAttribute(uint flag) { return attribs & (1 << flag); } static int app_compile_version; diff --git a/src/corelib/kernel/qeventdispatcher_glib_p.h b/src/corelib/kernel/qeventdispatcher_glib_p.h index 933faff5a5..a2e7b6b33e 100644 --- a/src/corelib/kernel/qeventdispatcher_glib_p.h +++ b/src/corelib/kernel/qeventdispatcher_glib_p.h @@ -77,19 +77,19 @@ public: bool processEvents(QEventLoop::ProcessEventsFlags flags); bool hasPendingEvents(); - void registerSocketNotifier(QSocketNotifier *socketNotifier); - void unregisterSocketNotifier(QSocketNotifier *socketNotifier); + void registerSocketNotifier(QSocketNotifier *socketNotifier) Q_DECL_FINAL; + void unregisterSocketNotifier(QSocketNotifier *socketNotifier) Q_DECL_FINAL; - void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object); - bool unregisterTimer(int timerId); - bool unregisterTimers(QObject *object); - QList<TimerInfo> registeredTimers(QObject *object) const; + void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) Q_DECL_FINAL; + bool unregisterTimer(int timerId) Q_DECL_FINAL; + bool unregisterTimers(QObject *object) Q_DECL_FINAL; + QList<TimerInfo> registeredTimers(QObject *object) const Q_DECL_FINAL; - int remainingTime(int timerId); + int remainingTime(int timerId) Q_DECL_FINAL; - void wakeUp(); - void interrupt(); - void flush(); + void wakeUp() Q_DECL_FINAL; + void interrupt() Q_DECL_FINAL; + void flush() Q_DECL_FINAL; static bool versionSupported(); diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h index 5d69d5e396..242aa9e695 100644 --- a/src/corelib/kernel/qeventdispatcher_unix_p.h +++ b/src/corelib/kernel/qeventdispatcher_unix_p.h @@ -94,6 +94,12 @@ public: class QEventDispatcherUNIXPrivate; +#ifdef Q_OS_QNX +# define FINAL_EXCEPT_BLACKBERRY +#else +# define FINAL_EXCEPT_BLACKBERRY Q_DECL_FINAL +#endif + class Q_CORE_EXPORT QEventDispatcherUNIX : public QAbstractEventDispatcher { Q_OBJECT @@ -106,18 +112,18 @@ public: bool processEvents(QEventLoop::ProcessEventsFlags flags); bool hasPendingEvents(); - void registerSocketNotifier(QSocketNotifier *notifier); - void unregisterSocketNotifier(QSocketNotifier *notifier); + void registerSocketNotifier(QSocketNotifier *notifier) FINAL_EXCEPT_BLACKBERRY; + void unregisterSocketNotifier(QSocketNotifier *notifier) FINAL_EXCEPT_BLACKBERRY; - void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object); - bool unregisterTimer(int timerId); - bool unregisterTimers(QObject *object); - QList<TimerInfo> registeredTimers(QObject *object) const; + void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) Q_DECL_FINAL; + bool unregisterTimer(int timerId) Q_DECL_FINAL; + bool unregisterTimers(QObject *object) Q_DECL_FINAL; + QList<TimerInfo> registeredTimers(QObject *object) const Q_DECL_FINAL; - int remainingTime(int timerId); + int remainingTime(int timerId) Q_DECL_FINAL; - void wakeUp(); - void interrupt(); + void wakeUp() FINAL_EXCEPT_BLACKBERRY; + void interrupt() Q_DECL_FINAL; void flush(); protected: @@ -130,7 +136,7 @@ protected: virtual int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, - timespec *timeout); + timespec *timeout) Q_DECL_FINAL; }; class Q_CORE_EXPORT QEventDispatcherUNIXPrivate : public QAbstractEventDispatcherPrivate @@ -142,8 +148,8 @@ public: ~QEventDispatcherUNIXPrivate(); int doSelect(QEventLoop::ProcessEventsFlags flags, timespec *timeout); - virtual int initThreadWakeUp(); - virtual int processThreadWakeUp(int nsel); + virtual int initThreadWakeUp() FINAL_EXCEPT_BLACKBERRY; + virtual int processThreadWakeUp(int nsel) FINAL_EXCEPT_BLACKBERRY; bool mainThread; @@ -165,6 +171,8 @@ public: QAtomicInt interrupt; // bool }; +#undef FINAL_EXCEPT_BLACKBERRY + QT_END_NAMESPACE #endif // QEVENTDISPATCHER_UNIX_P_H diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp new file mode 100644 index 0000000000..8639e925cd --- /dev/null +++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp @@ -0,0 +1,402 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module 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_winrt_p.h" + +#include <QtCore/QCoreApplication> +#include <QtCore/QThread> +#include <QtCore/QHash> + +#include <private/qcoreapplication_p.h> +#include <private/qthread_p.h> +#include <private/qabstracteventdispatcher_p.h> + +#include <wrl.h> +#include <windows.foundation.h> +#include <windows.system.threading.h> +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::System::Threading; +using namespace ABI::Windows::Foundation; + +QT_BEGIN_NAMESPACE + +class QZeroTimerEvent : public QTimerEvent +{ +public: + explicit inline QZeroTimerEvent(int timerId) + : QTimerEvent(timerId) + { t = QEvent::ZeroTimerEvent; } +}; + +struct WinRTTimerInfo // internal timer info +{ + WinRTTimerInfo() : timer(0) {} + + int id; + int interval; + Qt::TimerType timerType; + quint64 timeout; // - when to actually fire + QObject *obj; // - object to receive events + bool inTimerEvent; + ComPtr<IThreadPoolTimer> timer; +}; + +class QEventDispatcherWinRTPrivate : public QAbstractEventDispatcherPrivate +{ + Q_DECLARE_PUBLIC(QEventDispatcherWinRT) + +public: + QEventDispatcherWinRTPrivate(); + ~QEventDispatcherWinRTPrivate(); + + void registerTimer(WinRTTimerInfo *t); + void unregisterTimer(WinRTTimerInfo *t); + void sendTimerEvent(int timerId); + + +private: + static HRESULT timerExpiredCallback(ABI::Windows::System::Threading::IThreadPoolTimer *source); + static int idForTimer(IThreadPoolTimer *timer) + { + QAbstractEventDispatcher *eventDispatcher = QCoreApplication::eventDispatcher(); + if (!eventDispatcher) + return -1; + if (QEventDispatcherWinRTPrivate *that = static_cast<QEventDispatcherWinRTPrivate *>(get(eventDispatcher))) + return that->timerIds.value(timer, -1); + return -1; + } + + QHash<int, WinRTTimerInfo*> timerDict; + QHash<IThreadPoolTimer *, int> timerIds; + + ComPtr<IThreadPoolTimerStatics> timerFactory; +}; + +QEventDispatcherWinRT::QEventDispatcherWinRT(QObject *parent) + : QAbstractEventDispatcher(*new QEventDispatcherWinRTPrivate, parent) +{ +} + +QEventDispatcherWinRT::QEventDispatcherWinRT(QEventDispatcherWinRTPrivate &dd, QObject *parent) + : QAbstractEventDispatcher(dd, parent) +{ } + +QEventDispatcherWinRT::~QEventDispatcherWinRT() +{ +} + +bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags) +{ + Q_UNUSED(flags); + + // we are awake, broadcast it + emit awake(); + QCoreApplicationPrivate::sendPostedEvents(0, 0, QThreadData::current()); + + return false; +} + +bool QEventDispatcherWinRT::hasPendingEvents() +{ + return qGlobalPostedEventsCount(); +} + +void QEventDispatcherWinRT::registerSocketNotifier(QSocketNotifier *notifier) +{ + Q_UNUSED(notifier); + Q_UNIMPLEMENTED(); +} +void QEventDispatcherWinRT::unregisterSocketNotifier(QSocketNotifier *notifier) +{ + Q_UNUSED(notifier); + Q_UNIMPLEMENTED(); +} + +void QEventDispatcherWinRT::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) +{ + Q_UNUSED(timerType); + + if (timerId < 1 || interval < 0 || !object) { + qWarning("QEventDispatcherWinRT::registerTimer: invalid arguments"); + return; + } else if (object->thread() != thread() || thread() != QThread::currentThread()) { + qWarning("QObject::startTimer: timers cannot be started from another thread"); + return; + } + + Q_D(QEventDispatcherWinRT); + WinRTTimerInfo *t = new WinRTTimerInfo(); + t->id = timerId; + t->interval = interval; + t->timerType = timerType; + t->obj = object; + t->inTimerEvent = false; + + d->registerTimer(t); + d->timerDict.insert(t->id, t); +} + +bool QEventDispatcherWinRT::unregisterTimer(int timerId) +{ + if (timerId < 1) { + qWarning("QEventDispatcherWinRT::unregisterTimer: invalid argument"); + return false; + } + if (thread() != QThread::currentThread()) { + qWarning("QObject::killTimer: timers cannot be stopped from another thread"); + return false; + } + + Q_D(QEventDispatcherWinRT); + + WinRTTimerInfo *t = d->timerDict.value(timerId); + if (!t) + return false; + + d->unregisterTimer(t); + return true; +} + +bool QEventDispatcherWinRT::unregisterTimers(QObject *object) +{ + if (!object) { + qWarning("QEventDispatcherWinRT::unregisterTimers: invalid argument"); + return false; + } + QThread *currentThread = QThread::currentThread(); + if (object->thread() != thread() || thread() != currentThread) { + qWarning("QObject::killTimers: timers cannot be stopped from another thread"); + return false; + } + + Q_D(QEventDispatcherWinRT); + foreach (WinRTTimerInfo *t, d->timerDict) { + if (t->obj == object) + d->unregisterTimer(t); + } + return true; +} + +QList<QAbstractEventDispatcher::TimerInfo> QEventDispatcherWinRT::registeredTimers(QObject *object) const +{ + if (!object) { + qWarning("QEventDispatcherWinRT:registeredTimers: invalid argument"); + return QList<TimerInfo>(); + } + + Q_D(const QEventDispatcherWinRT); + QList<TimerInfo> list; + foreach (const WinRTTimerInfo *t, d->timerDict) { + if (t->obj == object) + list.append(TimerInfo(t->id, t->interval, t->timerType)); + } + return list; +} + +bool QEventDispatcherWinRT::registerEventNotifier(QWinEventNotifier *notifier) +{ + Q_UNUSED(notifier); + Q_UNIMPLEMENTED(); + return false; +} + +void QEventDispatcherWinRT::unregisterEventNotifier(QWinEventNotifier *notifier) +{ + Q_UNUSED(notifier); + Q_UNIMPLEMENTED(); +} + +int QEventDispatcherWinRT::remainingTime(int timerId) +{ +#ifndef QT_NO_DEBUG + if (timerId < 1) { + qWarning("QEventDispatcherWinRT::remainingTime: invalid argument"); + return -1; + } +#endif + + Q_D(QEventDispatcherWinRT); + if (WinRTTimerInfo *t = d->timerDict.value(timerId)) { + const quint64 currentTime = qt_msectime(); + if (currentTime < t->timeout) { + // time to wait + return t->timeout - currentTime; + } else { + return 0; + } + } + +#ifndef QT_NO_DEBUG + qWarning("QEventDispatcherWinRT::remainingTime: timer id %d not found", timerId); +#endif + return -1; +} + +void QEventDispatcherWinRT::wakeUp() +{ +} + +void QEventDispatcherWinRT::interrupt() +{ +} + +void QEventDispatcherWinRT::flush() +{ +} + +void QEventDispatcherWinRT::startingUp() +{ +} + +void QEventDispatcherWinRT::closingDown() +{ + Q_D(QEventDispatcherWinRT); + foreach (WinRTTimerInfo *t, d->timerDict) + d->unregisterTimer(t); + d->timerDict.clear(); + d->timerIds.clear(); +} + +bool QEventDispatcherWinRT::event(QEvent *e) +{ + Q_D(QEventDispatcherWinRT); + if (e->type() == QEvent::ZeroTimerEvent) { + QZeroTimerEvent *zte = static_cast<QZeroTimerEvent*>(e); + WinRTTimerInfo *t = d->timerDict.value(zte->timerId()); + if (t) { + t->inTimerEvent = true; + + QTimerEvent te(zte->timerId()); + QCoreApplication::sendEvent(t->obj, &te); + + t = d->timerDict.value(zte->timerId()); + if (t) { + if (t->interval == 0 && t->inTimerEvent) { + // post the next zero timer event as long as the timer was not restarted + QCoreApplication::postEvent(this, new QZeroTimerEvent(zte->timerId())); + } + + t->inTimerEvent = false; + } + } + return true; + } else if (e->type() == QEvent::Timer) { + QTimerEvent *te = static_cast<QTimerEvent*>(e); + d->sendTimerEvent(te->timerId()); + } + return QAbstractEventDispatcher::event(e); +} + +QEventDispatcherWinRTPrivate::QEventDispatcherWinRTPrivate() +{ + CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_System_Threading_ThreadPoolTimer).Get(), &timerFactory); + if (FAILED(hr)) + qWarning("QEventDispatcherWinRTPrivate::QEventDispatcherWinRTPrivate: Could not obtain timer factory: %lx", hr); +} + +QEventDispatcherWinRTPrivate::~QEventDispatcherWinRTPrivate() +{ + CoUninitialize(); +} + +void QEventDispatcherWinRTPrivate::registerTimer(WinRTTimerInfo *t) +{ + Q_Q(QEventDispatcherWinRT); + + bool ok = false; + uint interval = t->interval; + if (interval == 0u) { + // optimization for single-shot-zero-timer + QCoreApplication::postEvent(q, new QZeroTimerEvent(t->id)); + ok = true; + } else { + TimeSpan period; + period.Duration = interval * 10000; // TimeSpan is based on 100-nanosecond units + ok = SUCCEEDED(timerFactory->CreatePeriodicTimer( + Callback<ITimerElapsedHandler>(&QEventDispatcherWinRTPrivate::timerExpiredCallback).Get(), period, &t->timer)); + if (ok) + timerIds.insert(t->timer.Get(), t->id); + } + t->timeout = qt_msectime() + interval; + if (!ok) + qErrnoWarning("QEventDispatcherWinRT::registerTimer: Failed to create a timer"); +} + +void QEventDispatcherWinRTPrivate::unregisterTimer(WinRTTimerInfo *t) +{ + if (t->timer) { + t->timer->Cancel(); + timerIds.remove(t->timer.Get()); + } + timerDict.remove(t->id); + delete t; +} + +void QEventDispatcherWinRTPrivate::sendTimerEvent(int timerId) +{ + WinRTTimerInfo *t = timerDict.value(timerId); + if (t && !t->inTimerEvent) { + // send event, but don't allow it to recurse + t->inTimerEvent = true; + + QTimerEvent e(t->id); + QCoreApplication::sendEvent(t->obj, &e); + + // timer could have been removed + t = timerDict.value(timerId); + if (t) + t->inTimerEvent = false; + } +} + +HRESULT QEventDispatcherWinRTPrivate::timerExpiredCallback(IThreadPoolTimer *source) +{ + int timerId = idForTimer(source); + if (timerId > 0) + QCoreApplication::postEvent(QCoreApplication::eventDispatcher(), new QTimerEvent(timerId)); + else + qWarning("QEventDispatcherWinRT::timerExpiredCallback: Could not find timer %d in timer list", source); + return S_OK; +} + +QT_END_NAMESPACE diff --git a/src/corelib/kernel/qeventdispatcher_winrt_p.h b/src/corelib/kernel/qeventdispatcher_winrt_p.h new file mode 100644 index 0000000000..0631b2ea33 --- /dev/null +++ b/src/corelib/kernel/qeventdispatcher_winrt_p.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QEVENTDISPATCHER_WINRT_P_H +#define QEVENTDISPATCHER_WINRT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "QtCore/qabstracteventdispatcher.h" + +#include <qt_windows.h> + +QT_BEGIN_NAMESPACE + +int qt_msectime(); + +class QEventDispatcherWinRTPrivate; + +class Q_CORE_EXPORT QEventDispatcherWinRT : public QAbstractEventDispatcher +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QEventDispatcherWinRT) + +public: + explicit QEventDispatcherWinRT(QObject *parent = 0); + ~QEventDispatcherWinRT(); + + 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<TimerInfo> registeredTimers(QObject *object) const; + + int remainingTime(int timerId); + + bool registerEventNotifier(QWinEventNotifier *notifier); + void unregisterEventNotifier(QWinEventNotifier *notifier); + + void wakeUp(); + void interrupt(); + void flush(); + + void startingUp(); + void closingDown(); + +protected: + QEventDispatcherWinRT(QEventDispatcherWinRTPrivate &dd, QObject *parent = 0); + + bool event(QEvent *); + int activateTimers(); +}; + +QT_END_NAMESPACE + +#endif // QEVENTDISPATCHER_WINRT_P_H diff --git a/src/corelib/kernel/qfunctions_p.h b/src/corelib/kernel/qfunctions_p.h index 6e094f1ed3..e3014a0dcf 100644 --- a/src/corelib/kernel/qfunctions_p.h +++ b/src/corelib/kernel/qfunctions_p.h @@ -61,6 +61,8 @@ # include "QtCore/qfunctions_vxworks.h" #elif defined(Q_OS_NACL) # include "QtCore/qfunctions_nacl.h" +#elif defined(Q_OS_WINRT) +# include "QtCore/qfunctions_winrt.h" #endif #ifdef Q_CC_RVCT diff --git a/src/corelib/kernel/qfunctions_winrt.cpp b/src/corelib/kernel/qfunctions_winrt.cpp new file mode 100644 index 0000000000..1348af2acb --- /dev/null +++ b/src/corelib/kernel/qfunctions_winrt.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ +#ifdef Q_OS_WINRT + +#include "qfunctions_winrt.h" +#include "qstring.h" +#include "qbytearray.h" +#include "qhash.h" + +QT_USE_NAMESPACE + +// Environment ------------------------------------------------------ +inline QHash<QByteArray, QByteArray> &qt_app_environment() +{ + static QHash<QByteArray, QByteArray> internalEnvironment; + return internalEnvironment; +} + +errno_t qt_winrt_getenv_s(size_t* sizeNeeded, char* buffer, size_t bufferSize, const char* varName) +{ + if (!sizeNeeded) + return EINVAL; + + if (!qt_app_environment().contains(varName)) { + if (buffer) + buffer[0] = '\0'; + return ENOENT; + } + + QByteArray value = qt_app_environment().value(varName); + if (!value.endsWith('\0')) // win32 guarantees terminated string + value.append('\0'); + + if (bufferSize < (size_t)value.size()) { + *sizeNeeded = value.size(); + return ERANGE; + } + + strcpy(buffer, value.constData()); + return 0; +} + +errno_t qt_winrt__putenv_s(const char* varName, const char* value) +{ + QByteArray input = value; + if (input.isEmpty()) { + if (qt_app_environment().contains(varName)) + qt_app_environment().remove(varName); + } else { + // win32 on winrt guarantees terminated string + if (!input.endsWith('\0')) + input.append('\0'); + qt_app_environment()[varName] = input; + } + + return 0; +} + +void qt_winrt_tzset() +{ +} + +void qt_winrt__tzset() +{ +} + +#endif // Q_OS_WINRT diff --git a/src/corelib/kernel/qfunctions_winrt.h b/src/corelib/kernel/qfunctions_winrt.h new file mode 100644 index 0000000000..fa2b2e12ff --- /dev/null +++ b/src/corelib/kernel/qfunctions_winrt.h @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFUNCTIONS_WINRT_H +#define QFUNCTIONS_WINRT_H + +#include <QtCore/qglobal.h> + +#ifdef Q_OS_WINRT + +QT_BEGIN_NAMESPACE + +#ifdef QT_BUILD_CORE_LIB +#endif + +QT_END_NAMESPACE + +// Environment ------------------------------------------------------ +errno_t qt_winrt_getenv_s(size_t*, char*, size_t, const char*); +errno_t qt_winrt__putenv_s(const char*, const char*); +void qt_winrt_tzset(); +void qt_winrt__tzset(); + +// As Windows Runtime lacks some standard functions used in Qt, these got +// reimplemented. Other projects do this as well. Inline functions are used +// that there is a central place to disable functions for newer versions if +// they get available. There are no defines used anymore, because this +// will break member functions of classes which are called like these +// functions. +// The other declarations available in this file are being used per +// define inside qplatformdefs.h of the corresponding WinRT mkspec. + +#define generate_inline_return_func0(funcname, returntype) \ + inline returntype funcname() \ + { \ + return qt_winrt_##funcname(); \ + } +#define generate_inline_return_func1(funcname, returntype, param1) \ + inline returntype funcname(param1 p1) \ + { \ + return qt_winrt_##funcname(p1); \ + } +#define generate_inline_return_func2(funcname, returntype, param1, param2) \ + inline returntype funcname(param1 p1, param2 p2) \ + { \ + return qt_winrt_##funcname(p1, p2); \ + } +#define generate_inline_return_func3(funcname, returntype, param1, param2, param3) \ + inline returntype funcname(param1 p1, param2 p2, param3 p3) \ + { \ + return qt_winrt_##funcname(p1, p2, p3); \ + } +#define generate_inline_return_func4(funcname, returntype, param1, param2, param3, param4) \ + inline returntype funcname(param1 p1, param2 p2, param3 p3, param4 p4) \ + { \ + return qt_winrt_##funcname(p1, p2, p3, p4); \ + } +#define generate_inline_return_func5(funcname, returntype, param1, param2, param3, param4, param5) \ + inline returntype funcname(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ + { \ + return qt_winrt_##funcname(p1, p2, p3, p4, p5); \ + } +#define generate_inline_return_func6(funcname, returntype, param1, param2, param3, param4, param5, param6) \ + inline returntype funcname(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ + { \ + return qt_winrt_##funcname(p1, p2, p3, p4, p5, p6); \ + } +#define generate_inline_return_func7(funcname, returntype, param1, param2, param3, param4, param5, param6, param7) \ + inline returntype funcname(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) \ + { \ + return qt_winrt_##funcname(p1, p2, p3, p4, p5, p6, p7); \ + } + +typedef unsigned (__stdcall *StartAdressExFunc)(void *); +typedef void(*StartAdressFunc)(void *); +typedef int ( __cdecl *CompareFunc ) (const void *, const void *) ; + +generate_inline_return_func4(getenv_s, errno_t, size_t *, char *, size_t, const char *) +generate_inline_return_func2(_putenv_s, errno_t, const char *, const char *) +generate_inline_return_func0(tzset, void) +generate_inline_return_func0(_tzset, void) + +#endif // Q_OS_WINRT +#endif // QFUNCTIONS_WINRT_H diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index ff2675dfc8..0e38f2a2bf 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -942,7 +942,7 @@ static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, co return self; if (self->d.relatedMetaObjects) { Q_ASSERT(priv(self->d.data)->revision >= 2); - const QMetaObject **e = self->d.relatedMetaObjects; + const QMetaObject * const *e = self->d.relatedMetaObjects; if (e) { while (*e) { if (const QMetaObject *m =QMetaObject_findMetaObject((*e), name)) @@ -2694,10 +2694,14 @@ int QMetaProperty::userType() const if (type != QMetaType::UnknownType) return type; if (isEnumType()) { - int enumMetaTypeId = QMetaType::type(qualifiedName(menum)); - if (enumMetaTypeId == QMetaType::UnknownType) - return QVariant::Int; // Match behavior of QMetaType::type() - return enumMetaTypeId; + type = QMetaType::type(qualifiedName(menum)); + if (type == QMetaType::UnknownType) { + void *argv[] = { &type }; + mobj->static_metacall(QMetaObject::RegisterPropertyMetaType, idx, argv); + if (type == -1 || type == QMetaType::UnknownType) + return QVariant::Int; // Match behavior of QMetaType::type() + } + return type; } type = QMetaType::type(typeName()); if (type != QMetaType::UnknownType) diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp index 11ab39af1a..09d8271413 100644 --- a/src/corelib/kernel/qmetaobjectbuilder.cpp +++ b/src/corelib/kernel/qmetaobjectbuilder.cpp @@ -741,7 +741,7 @@ void QMetaObjectBuilder::addMetaObject if ((members & RelatedMetaObjects) != 0) { Q_ASSERT(priv(prototype->d.data)->revision >= 2); - const QMetaObject **objects = prototype->d.relatedMetaObjects; + const QMetaObject * const *objects = prototype->d.relatedMetaObjects; if (objects) { while (*objects != 0) { addRelatedMetaObject(*objects); diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index f1351f5a07..40e1e8bcc5 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -491,6 +491,100 @@ void QMetaCallEvent::placeMetaCall(QObject *object) } /*! + \class QSignalBlocker + \brief Exception-safe wrapper around QObject::blockSignals() + \since 5.3 + \ingroup objectmodel + + \reentrant + + QSignalBlocker can be used whereever you would otherwise use a + pair of calls to blockSignals(). It blocks signals in its + constructor and in the destructor it resets the state to what + it was before the constructor ran. + + \code + { + const QSignalBlocker blocker(someQObject); + // no signals here + } + \endcode + is thus equivalent to + \code + const bool wasBlocked = someQObject->blockSignals(true); + // no signals here + someQObject->blockSignals(false); + \endcode + + except the code using QSignalBlocker is safe in the face of + exceptions. + + \sa QMutexLocker, QEventLoopLocker +*/ + +/*! + \fn QSignalBlocker::QSignalBlocker(QObject *object) + + Constructor. Calls \a{object}->blockSignals(true). +*/ + +/*! + \fn QSignalBlocker::QSignalBlocker(QObject &object) + \overload + + Calls \a{object}.blockSignals(true). +*/ + +/*! + \fn QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) + + Move-constructs a signal blocker from \a other. \a other will have + a no-op destructor, while repsonsibility for restoring the + QObject::signalsBlocked() state is transferred to the new object. +*/ + +/*! + \fn QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other) + + Move-assigns this signal blocker from \a other. \a other will have + a no-op destructor, while repsonsibility for restoring the + QObject::signalsBlocked() state is transferred to this object. + + The object's signals this signal blocker was blocking prior to + being moved to, if any, are unblocked \em except in the case where + both instances block the same object's signals and \c *this is + unblocked while \a other is not, at the time of the move. +*/ + +/*! + \fn QSignalBlocker::~QSignalBlocker() + + Destructor. Restores the QObject::signalsBlocked() state to what it + was before the constructor ran, unless unblock() has been called + without a following reblock(), in which case it does nothing. +*/ + +/*! + \fn void QSignalBlocker::reblock() + + Re-blocks signals after a previous unblock(). + + The numbers of reblock() and unblock() calls are not counted, so + every reblock() undoes any number of unblock() calls. +*/ + +/*! + \fn void QSignalBlocker::unblock() + + Temporarily restores the QObject::signalsBlocked() state to what + it was before this QSignaBlocker's constructor ran. To undo, use + reblock(). + + The numbers of reblock() and unblock() calls are not counted, so + every unblock() undoes any number of reblock() calls. +*/ + +/*! \class QObject \inmodule QtCore \brief The QObject class is the base class of all Qt objects. @@ -2233,11 +2327,19 @@ QObject *QObject::sender() const int QObject::senderSignalIndex() const { Q_D(const QObject); - int signal_index = d->senderSignalIndex(); - if (signal_index < 0) - return signal_index; - // Convert from signal range to method range - return QMetaObjectPrivate::signal(sender()->metaObject(), signal_index).methodIndex(); + + QMutexLocker locker(signalSlotLock(this)); + if (!d->currentSender) + return -1; + + for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) { + if (c->sender == d->currentSender->sender) { + // Convert from signal range to method range + return QMetaObjectPrivate::signal(c->sender->metaObject(), d->currentSender->signal).methodIndex(); + } + } + + return -1; } /*! @@ -3620,25 +3722,6 @@ void QMetaObject::activate(QObject *sender, int signal_index, void **argv) /*! \internal - Implementation of QObject::senderSignalIndex() -*/ -int QObjectPrivate::senderSignalIndex() const -{ - Q_Q(const QObject); - QMutexLocker locker(signalSlotLock(q)); - if (!currentSender) - return -1; - - for (QObjectPrivate::Connection *c = senders; c; c = c->next) { - if (c->sender == currentSender->sender) - return currentSender->signal; - } - - return -1; -} - -/*! - \internal Returns the signal index used in the internal connectionLists vector. It is different from QMetaObject::indexOfSignal(): indexOfSignal is the same as indexOfMethod @@ -3715,6 +3798,8 @@ bool QObject::setProperty(const char *name, const QVariant &value) d->extraData->propertyNames.append(name); d->extraData->propertyValues.append(value); } else { + if (value == d->extraData->propertyValues.at(idx)) + return false; d->extraData->propertyValues[idx] = value; } } diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index e2000afc82..5197d98f19 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -549,6 +549,83 @@ template <class T> inline const char * qobject_interface_iid() Q_CORE_EXPORT QDebug operator<<(QDebug, const QObject *); #endif +class Q_CORE_EXPORT QSignalBlocker +{ +public: + inline explicit QSignalBlocker(QObject *o); + inline explicit QSignalBlocker(QObject &o); + inline ~QSignalBlocker(); + +#ifdef Q_COMPILER_RVALUE_REFS + inline QSignalBlocker(QSignalBlocker &&other); + inline QSignalBlocker &operator=(QSignalBlocker &&other); +#endif + + inline void reblock(); + inline void unblock(); +private: + Q_DISABLE_COPY(QSignalBlocker) + QObject * m_o; + bool m_blocked; + bool m_inhibited; +}; + +QSignalBlocker::QSignalBlocker(QObject *o) + : m_o(o), + m_blocked(o && o->blockSignals(true)), + m_inhibited(false) +{} + +QSignalBlocker::QSignalBlocker(QObject &o) + : m_o(&o), + m_blocked(o.blockSignals(true)), + m_inhibited(false) +{} + +#ifdef Q_COMPILER_RVALUE_REFS +QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) + : m_o(other.m_o), + m_blocked(other.m_blocked), + m_inhibited(other.m_inhibited) +{ + other.m_o = 0; +} + +QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other) +{ + if (this != &other) { + // if both *this and other block the same object's signals: + // unblock *this iff our dtor would unblock, but other's wouldn't + if (m_o != other.m_o || (!m_inhibited && other.m_inhibited)) + unblock(); + m_o = other.m_o; + m_blocked = other.m_blocked; + m_inhibited = other.m_inhibited; + // disable other: + other.m_o = 0; + } + return *this; +} +#endif + +QSignalBlocker::~QSignalBlocker() +{ + if (m_o && !m_inhibited) + m_o->blockSignals(m_blocked); +} + +void QSignalBlocker::reblock() +{ + if (m_o) m_o->blockSignals(true); + m_inhibited = false; +} + +void QSignalBlocker::unblock() +{ + if (m_o) m_o->blockSignals(m_blocked); + m_inhibited = true; +} + namespace QtPrivate { inline QObject & deref_for_methodcall(QObject &o) { return o; } inline QObject & deref_for_methodcall(QObject *o) { return *o; } diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 011e140e3b..193fa78403 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -199,7 +199,6 @@ public: return o->d_func(); } - int senderSignalIndex() const; int signalIndex(const char *signalName, const QMetaObject **meta = 0) const; inline bool isSignalConnected(uint signalIdx) const; diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 7354c3f0d0..c3141c1abb 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -447,7 +447,7 @@ struct Q_CORE_EXPORT QMetaObject const uint *data; typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **); StaticMetacallFunction static_metacall; - const QMetaObject **relatedMetaObjects; + const QMetaObject * const *relatedMetaObjects; void *extradata; //reserved for future use } d; }; diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 69cfa7888f..91ccf3996e 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -868,7 +868,7 @@ static void customConstruct(QVariant::Private *d, const void *copy) // this logic should match with QVariantIntegrator::CanUseInternalSpace if (size <= sizeof(QVariant::Private::Data) - && (type.flags() & QMetaType::MovableType)) { + && (type.flags() & (QMetaType::MovableType | QMetaType::IsEnumeration))) { type.construct(&d->data.ptr, copy); d->is_shared = false; } else { diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h index 4ec049e20d..b523d19187 100644 --- a/src/corelib/kernel/qvariant_p.h +++ b/src/corelib/kernel/qvariant_p.h @@ -67,7 +67,7 @@ template<typename T> struct QVariantIntegrator { static const bool CanUseInternalSpace = sizeof(T) <= sizeof(QVariant::Private::Data) - && (!QTypeInfo<T>::isStatic); + && ((!QTypeInfo<T>::isStatic) || Q_IS_ENUM(T)); }; Q_STATIC_ASSERT(QVariantIntegrator<double>::CanUseInternalSpace); Q_STATIC_ASSERT(QVariantIntegrator<long int>::CanUseInternalSpace); diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp index eab5a37645..c694237dc3 100644 --- a/src/corelib/kernel/qwineventnotifier.cpp +++ b/src/corelib/kernel/qwineventnotifier.cpp @@ -41,7 +41,11 @@ #include "qwineventnotifier.h" +#ifdef Q_OS_WINRT +#include "qeventdispatcher_winrt_p.h" +#else #include "qeventdispatcher_win_p.h" +#endif #include "qcoreapplication.h" #include <private/qthread_p.h> |