From 7c35824e6b855d134f51d46a0da8aaa900cd0b2e Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 22 Sep 2013 19:39:39 -0700 Subject: [PATCH 001/684] Bump Qt version to 5.3.0 Change-Id: Id15c3bcc4bced847a11eec08fcffda5100d778ec Reviewed-by: Sergio Ahumada --- src/corelib/global/qglobal.h | 4 ++-- src/corelib/io/qdatastream.cpp | 3 ++- src/corelib/io/qdatastream.h | 5 +++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index b1a22ddf03..0f124e0ccd 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -45,11 +45,11 @@ #include -#define QT_VERSION_STR "5.2.0" +#define QT_VERSION_STR "5.3.0" /* QT_VERSION is (major << 16) + (minor << 8) + patch. */ -#define QT_VERSION 0x050200 +#define QT_VERSION 0x050300 /* can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)) */ diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp index 008460df5d..614ac97f2f 100644 --- a/src/corelib/io/qdatastream.cpp +++ b/src/corelib/io/qdatastream.cpp @@ -251,7 +251,7 @@ QT_BEGIN_NAMESPACE return retVal; enum { - DefaultStreamVersion = QDataStream::Qt_5_2 + DefaultStreamVersion = QDataStream::Qt_5_3 }; /*! @@ -541,6 +541,7 @@ void QDataStream::setByteOrder(ByteOrder bo) \value Qt_5_0 Version 13 (Qt 5.0) \value Qt_5_1 Version 14 (Qt 5.1) \value Qt_5_2 Version 15 (Qt 5.2) + \value Qt_5_3 Same as Qt_5_2 \sa setVersion(), version() */ diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h index f107e801b6..28f1d51a12 100644 --- a/src/corelib/io/qdatastream.h +++ b/src/corelib/io/qdatastream.h @@ -87,8 +87,9 @@ public: Qt_4_9 = Qt_4_8, Qt_5_0 = 13, Qt_5_1 = 14, - Qt_5_2 = 15 -#if QT_VERSION >= 0x050300 + Qt_5_2 = 15, + Qt_5_3 = Qt_5_2 +#if QT_VERSION >= 0x050400 #error Add the datastream version for this Qt version #endif }; From 9260a3917a0e0b067e62d1c4bd6343a22656b495 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Fri, 6 Sep 2013 12:46:21 +0200 Subject: [PATCH 002/684] WinRT: Disable QFileSystemWatcher It might be possible to implement some kind of file system watcher using http://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.search.aspx Change-Id: I375f299e2420f266c8e19d77360bdecf6ff88a56 Reviewed-by: Andrew Knight Reviewed-by: Friedemann Kleint --- src/corelib/global/qglobal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 0f124e0ccd..1ebe0bd8ea 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -542,6 +542,7 @@ class QDataStream; #if defined(Q_OS_WINRT) # define QT_NO_PROCESS +# define QT_NO_FILESYSTEMWATCHER #endif inline void qt_noop(void) {} From d7af71b3187d9b67eb2aec04197fd41f74149497 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 29 Aug 2013 16:03:19 +0200 Subject: [PATCH 003/684] threading support for winrt Change-Id: Ife296e15ddf727c3f53ab3d3d84634b5c7bbf85c Done-with: Maurice Kalinowski Reviewed-by: Lars Knoll --- src/corelib/thread/qmutex_win.cpp | 9 ++ src/corelib/thread/qthread.cpp | 2 + src/corelib/thread/qthread_p.h | 9 ++ src/corelib/thread/qthread_win.cpp | 146 +++++++++++++++++- src/corelib/thread/qwaitcondition_win.cpp | 11 ++ .../corelib/thread/qthread/tst_qthread.cpp | 12 ++ 6 files changed, 187 insertions(+), 2 deletions(-) diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp index 14b7f34008..a8cdf85fb6 100644 --- a/src/corelib/thread/qmutex_win.cpp +++ b/src/corelib/thread/qmutex_win.cpp @@ -48,7 +48,12 @@ QT_BEGIN_NAMESPACE QMutexPrivate::QMutexPrivate() { +#ifndef Q_OS_WINRT event = CreateEvent(0, FALSE, FALSE, 0); +#else + event = CreateEventEx(0, NULL, 0, EVENT_ALL_ACCESS); +#endif + if (!event) qWarning("QMutexData::QMutexData: Cannot create event"); } @@ -58,7 +63,11 @@ QMutexPrivate::~QMutexPrivate() bool QMutexPrivate::wait(int timeout) { +#ifndef Q_OS_WINRT return (WaitForSingleObject(event, timeout < 0 ? INFINITE : timeout) == WAIT_OBJECT_0); +#else + return (WaitForSingleObjectEx(event, timeout < 0 ? INFINITE : timeout, FALSE) == WAIT_OBJECT_0); +#endif } void QMutexPrivate::wakeUp() Q_DECL_NOTHROW diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 35d57b3d83..77a5584f43 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -154,7 +154,9 @@ QThreadPrivate::QThreadPrivate(QThreadData *d) thread_id = 0; #elif defined (Q_OS_WIN) handle = 0; +# ifndef Q_OS_WINRT id = 0; +# endif waiters = 0; #endif #if defined (Q_OS_WIN) diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index 5e4eedaac7..8c75690404 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -66,6 +66,10 @@ #include +#ifdef Q_OS_WINRT +#include +#endif + QT_BEGIN_NAMESPACE class QAbstractEventDispatcher; @@ -173,8 +177,13 @@ public: static unsigned int __stdcall start(void *); static void finish(void *, bool lockAnyway=true); +# ifndef Q_OS_WINRT Qt::HANDLE handle; unsigned int id; +# else + std::thread *handle; + std::thread::id id; +# endif int waiters; bool terminationEnabled, terminatePending; # endif diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index d49a6a9a8e..eaf2f416a7 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -40,7 +40,7 @@ ****************************************************************************/ //#define WINVER 0x0500 -#if _WIN32_WINNT < 0x0400 +#if (_WIN32_WINNT < 0x0400) && !defined(Q_OS_WINRT) #define _WIN32_WINNT 0x0400 #endif @@ -58,6 +58,9 @@ #include +#ifdef Q_OS_WINRT +#include +#endif #ifndef Q_OS_WINCE #ifndef _MT @@ -71,6 +74,7 @@ #ifndef QT_NO_THREAD QT_BEGIN_NAMESPACE +#ifndef Q_OS_WINRT void qt_watch_adopted_thread(const HANDLE adoptedThreadHandle, QThread *qthread); DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID); @@ -92,6 +96,38 @@ static void qt_free_tls() } } Q_DESTRUCTOR_FUNCTION(qt_free_tls) +#else // !Q_OS_WINRT + +__declspec(thread) static QThreadData* qt_current_thread_data_tls_index = 0; +void qt_create_tls() +{ +} + +static void qt_free_tls() +{ + if (qt_current_thread_data_tls_index) { + qt_current_thread_data_tls_index->deref(); + qt_current_thread_data_tls_index = 0; + } +} + +QThreadData* TlsGetValue(QThreadData*& tls) +{ + Q_ASSERT(tls == qt_current_thread_data_tls_index); + return tls; +} + +void TlsSetValue(QThreadData*& tls, QThreadData* data) +{ + Q_ASSERT(tls == qt_current_thread_data_tls_index); + if (tls) + tls->deref(); + tls = data; + if (tls) + tls->ref(); +} +Q_DESTRUCTOR_FUNCTION(qt_free_tls) +#endif // Q_OS_WINRT /* QThreadData @@ -124,6 +160,9 @@ QThreadData *QThreadData::current() if (!QCoreApplicationPrivate::theMainThread) { QCoreApplicationPrivate::theMainThread = threadData->thread; +#ifndef Q_OS_WINRT + // TODO: is there a way to reflect the branch's behavior using + // WinRT API? } else { HANDLE realHandle = INVALID_HANDLE_VALUE; #if !defined(Q_OS_WINCE) || (defined(_WIN32_WCE) && (_WIN32_WCE>=0x600)) @@ -138,6 +177,7 @@ QThreadData *QThreadData::current() realHandle = reinterpret_cast(GetCurrentThreadId()); #endif qt_watch_adopted_thread(realHandle, threadData->thread); +#endif // !Q_OS_WINRT } } return threadData; @@ -145,10 +185,16 @@ QThreadData *QThreadData::current() void QAdoptedThread::init() { +#ifndef Q_OS_WINRT d_func()->handle = GetCurrentThread(); d_func()->id = GetCurrentThreadId(); +#else + d_func()->handle = nullptr; + d_func()->id = std::this_thread::get_id(); +#endif } +#ifndef Q_OS_WINRT static QVector qt_adopted_thread_handles; static QVector qt_adopted_qthreads; static QMutex qt_adopted_thread_watcher_mutex; @@ -297,6 +343,7 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName) } } #endif // !QT_NO_DEBUG && Q_CC_MSVC && !Q_OS_WINCE +#endif // !Q_OS_WINRT /************************************************************************** ** QThreadPrivate @@ -334,7 +381,7 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi else createEventDispatcher(data); -#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE) +#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) // sets the name of the current thread. QByteArray objectName = thr->objectName().toLocal8Bit(); qt_set_thread_name((HANDLE)-1, @@ -380,11 +427,20 @@ void QThreadPrivate::finish(void *arg, bool lockAnyway) d->interruptionRequested = false; if (!d->waiters) { +#ifndef Q_OS_WINRT CloseHandle(d->handle); +#else + CloseHandle(d->handle->native_handle()); + delete d->handle; +#endif d->handle = 0; } +#ifndef Q_OS_WINRT d->id = 0; +#else + d->id = std::thread::id(); +#endif } @@ -400,10 +456,15 @@ Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW int QThread::idealThreadCount() Q_DECL_NOTHROW { SYSTEM_INFO sysinfo; +#ifndef Q_OS_WINRT GetSystemInfo(&sysinfo); +#else + GetNativeSystemInfo(&sysinfo); +#endif return sysinfo.dwNumberOfProcessors; } +#ifndef Q_OS_WINRT void QThread::yieldCurrentThread() { #ifndef Q_OS_WINCE @@ -427,7 +488,28 @@ void QThread::usleep(unsigned long usecs) { ::Sleep((usecs / 1000) + 1); } +#else // !Q_OS_WINRT +void QThread::yieldCurrentThread() +{ + std::this_thread::yield(); +} + +void QThread::sleep(unsigned long secs) +{ + std::this_thread::sleep_for(std::chrono::seconds(secs)); +} + +void QThread::msleep(unsigned long msecs) +{ + std::this_thread::sleep_for(std::chrono::milliseconds(msecs)); +} + +void QThread::usleep(unsigned long usecs) +{ + std::this_thread::sleep_for(std::chrono::microseconds(usecs)); +} +#endif // Q_OS_WINRT void QThread::start(Priority priority) { @@ -449,6 +531,7 @@ void QThread::start(Priority priority) d->returnCode = 0; d->interruptionRequested = false; +#ifndef Q_OS_WINRT /* NOTE: we create the thread in the suspended state, set the priority and then resume the thread. @@ -513,6 +596,23 @@ void QThread::start(Priority priority) if (ResumeThread(d->handle) == (DWORD) -1) { qErrnoWarning("QThread::start: Failed to resume new thread"); } +#else // !Q_OS_WINRT + d->handle = new std::thread(QThreadPrivate::start, this); + + if (!d->handle) { + qErrnoWarning(errno, "QThread::start: Failed to create thread"); + d->running = false; + d->finished = true; + return; + } + + d->id = d->handle->get_id(); + + if (priority != NormalPriority || priority != InheritPriority) { + qWarning("QThread::start: Failed to set thread priority (not implemented)"); + d->priority = NormalPriority; + } +#endif // Q_OS_WINRT } void QThread::terminate() @@ -525,7 +625,14 @@ void QThread::terminate() d->terminatePending = true; return; } + +#ifndef Q_OS_WINRT TerminateThread(d->handle, 0); +#else // !Q_OS_WINRT + qWarning("QThread::terminate: Terminate is not supported on WinRT"); + CloseHandle(d->handle->native_handle()); + d->handle = 0; +#endif // Q_OS_WINRT QThreadPrivate::finish(this, false); } @@ -534,7 +641,11 @@ bool QThread::wait(unsigned long time) Q_D(QThread); QMutexLocker locker(&d->mutex); +#ifndef Q_OS_WINRT if (d->id == GetCurrentThreadId()) { +#else + if (d->id == std::this_thread::get_id()) { +#endif qWarning("QThread::wait: Thread tried to wait on itself"); return false; } @@ -545,6 +656,7 @@ bool QThread::wait(unsigned long time) locker.mutex()->unlock(); bool ret = false; +#ifndef Q_OS_WINRT switch (WaitForSingleObject(d->handle, time)) { case WAIT_OBJECT_0: ret = true; @@ -557,6 +669,23 @@ bool QThread::wait(unsigned long time) default: break; } +#else // !Q_OS_WINRT + if (d->handle->joinable()) { + switch (WaitForSingleObjectEx(d->handle->native_handle(), time, FALSE)) { + case WAIT_OBJECT_0: + ret = true; + d->handle->join(); + break; + case WAIT_FAILED: + qErrnoWarning("QThread::wait: WaitForSingleObjectEx() failed"); + break; + case WAIT_ABANDONED: + case WAIT_TIMEOUT: + default: + break; + } + } +#endif // Q_OS_WINRT locker.mutex()->lock(); --d->waiters; @@ -568,7 +697,11 @@ bool QThread::wait(unsigned long time) } if (d->finished && !d->waiters) { +#ifndef Q_OS_WINRT CloseHandle(d->handle); +#else + delete d->handle; +#endif d->handle = 0; } @@ -586,13 +719,16 @@ void QThread::setTerminationEnabled(bool enabled) if (enabled && d->terminatePending) { QThreadPrivate::finish(thr, false); locker.unlock(); // don't leave the mutex locked! +#ifndef Q_OS_WINRT _endthreadex(0); +#endif } } // Caller must hold the mutex void QThreadPrivate::setPriority(QThread::Priority threadPriority) { +#ifndef Q_OS_WINRT // copied from start() with a few modifications: int prio; @@ -635,6 +771,12 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority) if (!SetThreadPriority(handle, prio)) { qErrnoWarning("QThread::setPriority: Failed to set thread priority"); } +#else // !Q_OS_WINRT + if (priority != threadPriority) { + qWarning("QThread::setPriority: Failed to set thread priority (not implemented)"); + return; + } +#endif // Q_OS_WINRT } QT_END_NAMESPACE diff --git a/src/corelib/thread/qwaitcondition_win.cpp b/src/corelib/thread/qwaitcondition_win.cpp index 1cb1f82b03..f09667a364 100644 --- a/src/corelib/thread/qwaitcondition_win.cpp +++ b/src/corelib/thread/qwaitcondition_win.cpp @@ -64,7 +64,11 @@ class QWaitConditionEvent public: inline QWaitConditionEvent() : priority(0), wokenUp(false) { +#ifndef Q_OS_WINRT event = CreateEvent(NULL, TRUE, FALSE, NULL); +#else + event = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); +#endif } inline ~QWaitConditionEvent() { CloseHandle(event); } int priority; @@ -91,7 +95,9 @@ QWaitConditionEvent *QWaitConditionPrivate::pre() mtx.lock(); QWaitConditionEvent *wce = freeQueue.isEmpty() ? new QWaitConditionEvent : freeQueue.takeFirst(); +#ifndef Q_OS_WINRT wce->priority = GetThreadPriority(GetCurrentThread()); +#endif wce->wokenUp = false; // insert 'wce' into the queue (sorted by priority) @@ -111,7 +117,12 @@ bool QWaitConditionPrivate::wait(QWaitConditionEvent *wce, unsigned long time) { // wait for the event bool ret = false; +#ifndef Q_OS_WINRT switch (WaitForSingleObject(wce->event, time)) { +#else + switch (WaitForSingleObjectEx(wce->event, time, FALSE)) { +#endif + default: break; case WAIT_OBJECT_0: diff --git a/tests/auto/corelib/thread/qthread/tst_qthread.cpp b/tests/auto/corelib/thread/qthread/tst_qthread.cpp index 5cc0e5bdb4..4ebdd63b99 100644 --- a/tests/auto/corelib/thread/qthread/tst_qthread.cpp +++ b/tests/auto/corelib/thread/qthread/tst_qthread.cpp @@ -55,6 +55,8 @@ #endif #if defined(Q_OS_WINCE) #include +#elif defined(Q_OS_WINRT) +#include #elif defined(Q_OS_WIN) #include #include @@ -460,6 +462,10 @@ void tst_QThread::start() QVERIFY(!thread.isFinished()); QVERIFY(!thread.isRunning()); QMutexLocker locker(&thread.mutex); +#ifdef Q_OS_WINRT + if (priorities[i] != QThread::NormalPriority && priorities[i] != QThread::InheritPriority) + QTest::ignoreMessage(QtWarningMsg, "QThread::start: Failed to set thread priority (not implemented)"); +#endif thread.start(priorities[i]); QVERIFY(thread.isRunning()); QVERIFY(!thread.isFinished()); @@ -630,6 +636,8 @@ void noop(void*) { } #if defined Q_OS_UNIX typedef pthread_t ThreadHandle; +#elif defined Q_OS_WINRT + typedef std::thread ThreadHandle; #elif defined Q_OS_WIN typedef HANDLE ThreadHandle; #endif @@ -671,6 +679,8 @@ void NativeThreadWrapper::start(FunctionPointer functionPointer, void *data) #if defined Q_OS_UNIX const int state = pthread_create(&nativeThreadHandle, 0, NativeThreadWrapper::runUnix, this); Q_UNUSED(state); +#elif defined(Q_OS_WINRT) + nativeThreadHandle = std::thread(NativeThreadWrapper::runWin, this); #elif defined(Q_OS_WINCE) nativeThreadHandle = CreateThread(NULL, 0 , (LPTHREAD_START_ROUTINE)NativeThreadWrapper::runWin , this, 0, NULL); #elif defined Q_OS_WIN @@ -690,6 +700,8 @@ void NativeThreadWrapper::join() { #if defined Q_OS_UNIX pthread_join(nativeThreadHandle, 0); +#elif defined Q_OS_WINRT + nativeThreadHandle.join(); #elif defined Q_OS_WIN WaitForSingleObject(nativeThreadHandle, INFINITE); CloseHandle(nativeThreadHandle); From 81dea57593b5b28990bb7f012aae1387c8d2de33 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Fri, 20 Sep 2013 14:06:33 +0200 Subject: [PATCH 004/684] add WinRT event dispatcher Change-Id: I40b3f896b89b99e271e1a5ca625a5193f4a7f59e Done-with: Kamil Trzcinski Reviewed-by: Lars Knoll --- mkspecs/common/winrt_winphone/qmake.conf | 2 +- src/corelib/kernel/kernel.pri | 11 +- src/corelib/kernel/qcoreapplication.cpp | 6 + src/corelib/kernel/qeventdispatcher_winrt.cpp | 394 ++++++++++++++++++ src/corelib/kernel/qeventdispatcher_winrt_p.h | 168 ++++++++ src/corelib/kernel/qwineventnotifier.cpp | 4 + src/corelib/thread/qthread_win.cpp | 8 + .../platforms/minimal/qminimalintegration.cpp | 17 +- .../offscreen/qoffscreenintegration.cpp | 8 + 9 files changed, 608 insertions(+), 10 deletions(-) create mode 100644 src/corelib/kernel/qeventdispatcher_winrt.cpp create mode 100644 src/corelib/kernel/qeventdispatcher_winrt_p.h diff --git a/mkspecs/common/winrt_winphone/qmake.conf b/mkspecs/common/winrt_winphone/qmake.conf index a1bf19d3aa..dd4b7f1b94 100644 --- a/mkspecs/common/winrt_winphone/qmake.conf +++ b/mkspecs/common/winrt_winphone/qmake.conf @@ -75,7 +75,7 @@ QMAKE_LFLAGS_DLL = /WINMD /MANIFEST:NO /DLL /WINMDFILE:$(DESTDIR_TARGET). QMAKE_LFLAGS_LTCG = /LTCG QMAKE_EXTENSION_STATICLIB = lib -QMAKE_LIBS_CORE = +QMAKE_LIBS_CORE += runtimeobject.lib QMAKE_LIBS_GUI = d3d11.lib QMAKE_LIBS_NETWORK = diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 26ad9f488c..9118c7cbc6 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 += \ diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index f3caa1d918..1799cf6a24 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -84,7 +84,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 @@ -466,6 +470,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 diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp new file mode 100644 index 0000000000..c94c69b90f --- /dev/null +++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp @@ -0,0 +1,394 @@ +/**************************************************************************** +** +** 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 "qelapsedtimer.h" +#include "qcoreapplication.h" +#include "qthread.h" + +#include +#include + +#include +#include +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::System::Threading; +using namespace ABI::Windows::Foundation; + +QT_BEGIN_NAMESPACE + +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->dispatcher = this; + t->timerId = timerId; + t->interval = interval; + t->timeout = interval; + t->timerType = timerType; + t->obj = object; + t->inTimerEvent = false; + + d->registerTimer(t); + d->timerVec.append(t); // store in timer vector + d->timerDict.insert(t->timerId, t); // store timers in dict +} + +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); + if (d->timerVec.isEmpty() || timerId <= 0) + return false; + + WinRTTimerInfo *t = d->timerDict.value(timerId); + if (!t) + return false; + + if (t->timer) + d->threadPoolTimerDict.remove(t->timer); + d->timerDict.remove(t->timerId); + d->timerVec.removeAll(t); + 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); + if (d->timerVec.isEmpty()) + return false; + register WinRTTimerInfo *t; + for (int i = 0; i < d->timerVec.size(); i++) { + t = d->timerVec.at(i); + if (t && t->obj == object) { // object found + if (t->timer) + d->threadPoolTimerDict.remove(t->timer); + d->timerDict.remove(t->timerId); + d->timerVec.removeAt(i); + d->unregisterTimer(t); + --i; + } + } + return true; +} + +QList QEventDispatcherWinRT::registeredTimers(QObject *object) const +{ + if (!object) { + qWarning("QEventDispatcherWinRT:registeredTimers: invalid argument"); + return QList(); + } + + Q_D(const QEventDispatcherWinRT); + QList list; + for (int i = 0; i < d->timerVec.size(); ++i) { + const WinRTTimerInfo *t = d->timerVec.at(i); + if (t && t->obj == object) + list << TimerInfo(t->timerId, 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 (d->timerVec.isEmpty()) + return -1; + + quint64 currentTime = qt_msectime(); + + register WinRTTimerInfo *t; + for (int i = 0; i < d->timerVec.size(); i++) { + t = d->timerVec.at(i); + if (t && t->timerId == timerId) { // timer found + 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() +{ + Q_D(QEventDispatcherWinRT); + if (d->wakeUps.testAndSetAcquire(0, 1)) { + // ###TODO: is there any thing to wake up? + } +} + +void QEventDispatcherWinRT::interrupt() +{ + Q_D(QEventDispatcherWinRT); + d->interrupt = true; + wakeUp(); +} + +void QEventDispatcherWinRT::flush() +{ +} + +void QEventDispatcherWinRT::startingUp() +{ +} + +void QEventDispatcherWinRT::closingDown() +{ + Q_D(QEventDispatcherWinRT); + + // clean up any timers + for (int i = 0; i < d->timerVec.count(); ++i) + d->unregisterTimer(d->timerVec.at(i)); + d->timerVec.clear(); + d->timerDict.clear(); + d->threadPoolTimerDict.clear(); +} + +bool QEventDispatcherWinRT::event(QEvent *e) +{ + Q_D(QEventDispatcherWinRT); + if (e->type() == QEvent::ZeroTimerEvent) { + QZeroTimerEvent *zte = static_cast(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(e); + d->sendTimerEvent(te->timerId()); + } + return QAbstractEventDispatcher::event(e); +} + +QEventDispatcherWinRTPrivate::QEventDispatcherWinRTPrivate() + : interrupt(false) + , timerFactory(0) +{ + CoInitializeEx(NULL, COINIT_MULTITHREADED); + 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() +{ + if (timerFactory) + timerFactory->Release(); + CoUninitialize(); +} + +void QEventDispatcherWinRTPrivate::registerTimer(WinRTTimerInfo *t) +{ + Q_Q(QEventDispatcherWinRT); + + int ok = 0; + uint interval = t->interval; + if (interval == 0u) { + // optimization for single-shot-zero-timer + QCoreApplication::postEvent(q, new QZeroTimerEvent(t->timerId)); + ok = 1; + } else { + TimeSpan period; + period.Duration = interval * 10000; // TimeSpan is based on 100-nanosecond units + ok = SUCCEEDED(timerFactory->CreatePeriodicTimer( + Callback(this, &QEventDispatcherWinRTPrivate::timerExpiredCallback).Get(), period, &t->timer)); + if (ok) + threadPoolTimerDict.insert(t->timer, t); + } + t->timeout = qt_msectime() + interval; + if (ok == 0) + qErrnoWarning("QEventDispatcherWinRT::registerTimer: Failed to create a timer"); +} + +void QEventDispatcherWinRTPrivate::unregisterTimer(WinRTTimerInfo *t) +{ + if (t->timer) { + t->timer->Cancel(); + t->timer->Release(); + } + delete t; + t = 0; +} + +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->timerId); + QCoreApplication::sendEvent(t->obj, &e); + + // timer could have been removed + t = timerDict.value(timerId); + if (t) { + t->inTimerEvent = false; + } + } +} + +HRESULT QEventDispatcherWinRTPrivate::timerExpiredCallback(IThreadPoolTimer *source) +{ + register WinRTTimerInfo *t = threadPoolTimerDict.value(source); + if (t) + QCoreApplication::postEvent(t->dispatcher, new QTimerEvent(t->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..35b3faa771 --- /dev/null +++ b/src/corelib/kernel/qeventdispatcher_winrt_p.h @@ -0,0 +1,168 @@ +/**************************************************************************** +** +** 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 "private/qabstracteventdispatcher_p.h" + +#include +#include + +namespace ABI { + namespace Windows { + namespace System { + namespace Threading { + struct IThreadPoolTimer; + struct IThreadPoolTimerStatics; + } + } + } +} + +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 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(); + int activateSocketNotifiers(); +}; + +struct WinRTTimerInfo // internal timer info +{ + WinRTTimerInfo() : timer(0) {} + + QObject *dispatcher; + int timerId; + int interval; + Qt::TimerType timerType; + quint64 timeout; // - when to actually fire + QObject *obj; // - object to receive events + bool inTimerEvent; + ABI::Windows::System::Threading::IThreadPoolTimer *timer; +}; + +class QZeroTimerEvent : public QTimerEvent +{ +public: + explicit inline QZeroTimerEvent(int timerId) + : QTimerEvent(timerId) + { t = QEvent::ZeroTimerEvent; } +}; + +class Q_CORE_EXPORT QEventDispatcherWinRTPrivate : public QAbstractEventDispatcherPrivate +{ + Q_DECLARE_PUBLIC(QEventDispatcherWinRT) + +public: + QEventDispatcherWinRTPrivate(); + ~QEventDispatcherWinRTPrivate(); + + QList timerVec; + QHash timerDict; + QHash threadPoolTimerDict; + + void registerTimer(WinRTTimerInfo *t); + void unregisterTimer(WinRTTimerInfo *t); + void sendTimerEvent(int timerId); + HRESULT timerExpiredCallback(ABI::Windows::System::Threading::IThreadPoolTimer *source); + + QAtomicInt wakeUps; + bool interrupt; + + ABI::Windows::System::Threading::IThreadPoolTimerStatics *timerFactory; +}; + +QT_END_NAMESPACE + +#endif // QEVENTDISPATCHER_WINRT_P_H diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp index 242702b304..5eb34e635e 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 diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index eaf2f416a7..3de1e991c1 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -54,7 +54,11 @@ #include #include +#ifdef Q_OS_WINRT +#include "private/qeventdispatcher_winrt_p.h" +#else #include +#endif #include @@ -353,7 +357,11 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName) void QThreadPrivate::createEventDispatcher(QThreadData *data) { +#ifdef Q_OS_WINRT + QEventDispatcherWinRT *theEventDispatcher = new QEventDispatcherWinRT; +#else QEventDispatcherWin32 *theEventDispatcher = new QEventDispatcherWin32; +#endif data->eventDispatcher.storeRelease(theEventDispatcher); theEventDispatcher->startingUp(); } diff --git a/src/plugins/platforms/minimal/qminimalintegration.cpp b/src/plugins/platforms/minimal/qminimalintegration.cpp index 8d0586a5a3..29bd223f3f 100644 --- a/src/plugins/platforms/minimal/qminimalintegration.cpp +++ b/src/plugins/platforms/minimal/qminimalintegration.cpp @@ -41,20 +41,25 @@ #include "qminimalintegration.h" #include "qminimalbackingstore.h" -#ifndef Q_OS_WIN -#include -#else -#include -#endif #include #include #include +#if !defined(Q_OS_WIN) +#include +#elif defined(Q_OS_WINRT) +#include +#else +#include +#endif + QT_BEGIN_NAMESPACE QMinimalIntegration::QMinimalIntegration() : -#ifdef Q_OS_WIN +#if defined(Q_OS_WINRT) + m_eventDispatcher(new QEventDispatcherWinRT()) +#elif defined(Q_OS_WIN) m_eventDispatcher(new QEventDispatcherWin32()) #else m_eventDispatcher(createUnixEventDispatcher()) diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp index bce52963df..aafa90c0fd 100644 --- a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp +++ b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp @@ -52,7 +52,11 @@ #endif #elif defined(Q_OS_WIN) #include +#ifndef Q_OS_WINRT #include +#else +#include +#endif #endif #include @@ -102,7 +106,11 @@ QOffscreenIntegration::QOffscreenIntegration() m_fontDatabase.reset(new QGenericUnixFontDatabase()); #endif #elif defined(Q_OS_WIN) +#ifndef Q_OS_WINRT m_eventDispatcher = new QOffscreenEventDispatcher(); +#else + m_eventDispatcher = new QOffscreenEventDispatcher(); +#endif m_fontDatabase.reset(new QBasicFontDatabase()); #endif From 8cc0f19f832053d3d2682e3b53bf2e17813da71a Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Sat, 31 Aug 2013 16:39:15 +0300 Subject: [PATCH 005/684] WinRT: Don't build the network-chat example WinRT doesn't support QProcess, so the network-chat example shouldn't be built there. Change-Id: I7885a992d3b8baffd5530c694063140535240f07 Reviewed-by: Oliver Wolff Reviewed-by: Friedemann Kleint --- examples/network/network.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/network/network.pro b/examples/network/network.pro index be4ccdbddf..8ed72315e2 100644 --- a/examples/network/network.pro +++ b/examples/network/network.pro @@ -23,7 +23,7 @@ qtHaveModule(widgets) { multicastsender # no QProcess - !vxworks:!qnx:SUBDIRS += network-chat + !vxworks:!qnx:!winrt:SUBDIRS += network-chat contains(QT_CONFIG, openssl):SUBDIRS += securesocketclient contains(QT_CONFIG, openssl-linked):SUBDIRS += securesocketclient From f89d30aa34337b7998f50fe4391114d1277d6814 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Tue, 17 Sep 2013 14:05:03 +0200 Subject: [PATCH 006/684] WinRT: Introduced qfunctions_winrt Using the same approach as, wince qfunctions_winrt is introduced to replace functions not available on Windows Runtime by their successor functions/ equivalents. Additionally this functionality is used for implementing a fake environment because WinRT does not support getting/setting of environment variables. The approach here is also the same that is used for wince. Change-Id: Ifc3b6b796ab8e8ea41456f4c929f9c3f65f24a0e Reviewed-by: Friedemann Kleint Reviewed-by: Andrew Knight Reviewed-by: Joerg Bornemann --- mkspecs/common/winrt_winphone/qplatformdefs.h | 141 ++++++++++++++++++ mkspecs/winphone-arm-msvc2012/qplatformdefs.h | 2 +- mkspecs/winphone-x86-msvc2012/qplatformdefs.h | 2 +- mkspecs/winrt-arm-msvc2012/qplatformdefs.h | 2 +- mkspecs/winrt-x64-msvc2012/qplatformdefs.h | 2 +- mkspecs/winrt-x86-msvc2012/qplatformdefs.h | 2 +- src/corelib/kernel/kernel.pri | 7 + src/corelib/kernel/qfunctions_p.h | 2 + src/corelib/kernel/qfunctions_winrt.cpp | 105 +++++++++++++ src/corelib/kernel/qfunctions_winrt.h | 122 +++++++++++++++ 10 files changed, 382 insertions(+), 5 deletions(-) create mode 100644 mkspecs/common/winrt_winphone/qplatformdefs.h create mode 100644 src/corelib/kernel/qfunctions_winrt.cpp create mode 100644 src/corelib/kernel/qfunctions_winrt.h diff --git a/mkspecs/common/winrt_winphone/qplatformdefs.h b/mkspecs/common/winrt_winphone/qplatformdefs.h new file mode 100644 index 0000000000..96f20569d2 --- /dev/null +++ b/mkspecs/common/winrt_winphone/qplatformdefs.h @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the qmake spec 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 QPLATFORMDEFS_H +#define QPLATFORMDEFS_H + +#ifdef UNICODE +#ifndef _UNICODE +#define _UNICODE +#endif +#endif + +// Get Qt defines/settings + +#include "qglobal.h" +#include "qfunctions_winrt.h" + +#define _POSIX_ +#include +#undef _POSIX_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef QT_LARGEFILE_SUPPORT +#define QT_STATBUF struct _stati64 // non-ANSI defs +#define QT_STATBUF4TSTAT struct _stati64 // non-ANSI defs +#define QT_STAT ::_stati64 +#define QT_FSTAT ::_fstati64 +#else +#define QT_STATBUF struct _stat // non-ANSI defs +#define QT_STATBUF4TSTAT struct _stat // non-ANSI defs +#define QT_STAT ::_stat +#define QT_FSTAT ::_fstat +#endif +#define QT_STAT_REG _S_IFREG +#define QT_STAT_DIR _S_IFDIR +#define QT_STAT_MASK _S_IFMT +#if defined(_S_IFLNK) +# define QT_STAT_LNK _S_IFLNK +#endif +#define QT_FILENO _fileno +#define QT_OPEN ::_open +#define QT_CLOSE ::_close +#ifdef QT_LARGEFILE_SUPPORT +#define QT_LSEEK ::_lseeki64 +#define QT_TSTAT ::_tstati64 +#else +#define QT_LSEEK ::_lseek +#define QT_TSTAT ::_tstat +#endif +#define QT_READ ::_read +#define QT_WRITE ::_write +#define QT_ACCESS ::_access +#define QT_GETCWD ::_getcwd +#define QT_CHDIR ::_chdir +#define QT_MKDIR ::_mkdir +#define QT_RMDIR ::_rmdir +#define QT_OPEN_LARGEFILE 0 +#define QT_OPEN_RDONLY _O_RDONLY +#define QT_OPEN_WRONLY _O_WRONLY +#define QT_OPEN_RDWR _O_RDWR +#define QT_OPEN_CREAT _O_CREAT +#define QT_OPEN_TRUNC _O_TRUNC +#define QT_OPEN_APPEND _O_APPEND +#if defined(O_TEXT) +# define QT_OPEN_TEXT _O_TEXT +# define QT_OPEN_BINARY _O_BINARY +#endif + +#include "../common/c89/qplatformdefs.h" + +#ifdef QT_LARGEFILE_SUPPORT +#undef QT_FSEEK +#undef QT_FTELL +#undef QT_OFF_T + +#define QT_FSEEK ::_fseeki64 +#define QT_FTELL ::_ftelli64 +#define QT_OFF_T __int64 +#endif + +#define QT_SIGNAL_ARGS int + +#define QT_VSNPRINTF(buffer, count, format, arg) \ + vsnprintf_s(buffer, count, count-1, format, arg) + +#define QT_SNPRINTF ::_snprintf + +# define F_OK 0 +# define X_OK 1 +# define W_OK 2 +# define R_OK 4 + +typedef int mode_t; + +#endif // QPLATFORMDEFS_H diff --git a/mkspecs/winphone-arm-msvc2012/qplatformdefs.h b/mkspecs/winphone-arm-msvc2012/qplatformdefs.h index e03bce8e6c..781107b2dc 100644 --- a/mkspecs/winphone-arm-msvc2012/qplatformdefs.h +++ b/mkspecs/winphone-arm-msvc2012/qplatformdefs.h @@ -39,4 +39,4 @@ ** ****************************************************************************/ -#include "../win32-msvc2005/qplatformdefs.h" +#include "../common/winrt_winphone/qplatformdefs.h" diff --git a/mkspecs/winphone-x86-msvc2012/qplatformdefs.h b/mkspecs/winphone-x86-msvc2012/qplatformdefs.h index e03bce8e6c..781107b2dc 100644 --- a/mkspecs/winphone-x86-msvc2012/qplatformdefs.h +++ b/mkspecs/winphone-x86-msvc2012/qplatformdefs.h @@ -39,4 +39,4 @@ ** ****************************************************************************/ -#include "../win32-msvc2005/qplatformdefs.h" +#include "../common/winrt_winphone/qplatformdefs.h" diff --git a/mkspecs/winrt-arm-msvc2012/qplatformdefs.h b/mkspecs/winrt-arm-msvc2012/qplatformdefs.h index e03bce8e6c..781107b2dc 100644 --- a/mkspecs/winrt-arm-msvc2012/qplatformdefs.h +++ b/mkspecs/winrt-arm-msvc2012/qplatformdefs.h @@ -39,4 +39,4 @@ ** ****************************************************************************/ -#include "../win32-msvc2005/qplatformdefs.h" +#include "../common/winrt_winphone/qplatformdefs.h" diff --git a/mkspecs/winrt-x64-msvc2012/qplatformdefs.h b/mkspecs/winrt-x64-msvc2012/qplatformdefs.h index e03bce8e6c..781107b2dc 100644 --- a/mkspecs/winrt-x64-msvc2012/qplatformdefs.h +++ b/mkspecs/winrt-x64-msvc2012/qplatformdefs.h @@ -39,4 +39,4 @@ ** ****************************************************************************/ -#include "../win32-msvc2005/qplatformdefs.h" +#include "../common/winrt_winphone/qplatformdefs.h" diff --git a/mkspecs/winrt-x86-msvc2012/qplatformdefs.h b/mkspecs/winrt-x86-msvc2012/qplatformdefs.h index e03bce8e6c..781107b2dc 100644 --- a/mkspecs/winrt-x86-msvc2012/qplatformdefs.h +++ b/mkspecs/winrt-x86-msvc2012/qplatformdefs.h @@ -39,4 +39,4 @@ ** ****************************************************************************/ -#include "../win32-msvc2005/qplatformdefs.h" +#include "../common/winrt_winphone/qplatformdefs.h" diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 9118c7cbc6..998bf56874 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -91,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/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..f4a278dc43 --- /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 &qt_app_environment() +{ + static QHash 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 0; + } + + 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 + +#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 From 785eee0bf227955bb30f2a46724566f5d1848406 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Wed, 4 Sep 2013 13:07:56 +0200 Subject: [PATCH 007/684] Implement qt_error_string for WinRT Change-Id: I6049d67da0295aeec311b644ccedf8f27f86b1d1 Reviewed-by: Friedemann Kleint --- src/corelib/global/qglobal.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 59bdecc868..5b1a7dbbcb 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -2132,7 +2132,9 @@ QString qt_error_string(int errorCode) s = QT_TRANSLATE_NOOP("QIODevice", "No space left on device"); break; default: { -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) + // Retrieve the system error message for the last-error code. +# ifndef Q_OS_WINRT wchar_t *string = 0; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, @@ -2143,6 +2145,17 @@ QString qt_error_string(int errorCode) NULL); ret = QString::fromWCharArray(string); LocalFree((HLOCAL)string); +# else // !Q_OS_WINRT + __declspec(thread) static wchar_t errorString[4096]; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + errorCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + errorString, + ARRAYSIZE(errorString), + NULL); + ret = QString::fromWCharArray(errorString); +# endif // Q_OS_WINRT if (ret.isEmpty() && errorCode == ERROR_MOD_NOT_FOUND) ret = QString::fromLatin1("The specified module could not be found."); From 3d4cd88fd01fac83b2e35b34e2745d6fc2be740d Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Fri, 20 Sep 2013 18:03:25 +0300 Subject: [PATCH 008/684] WinRT: QSettings stub Enable the non-native QSettings path on WinRT. Native settings can probably be implemented using http://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.applicationdata.localsettings.aspx at least for Desktop WinRT applications. Task-number: QTBUG-33498 Change-Id: I1a3aa506e1393b04b5759ee90732ab35de32b1fc Done-with: Oliver Wolff Reviewed-by: Lars Knoll --- src/corelib/io/io.pri | 2 +- src/corelib/io/qsettings.cpp | 67 +++++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index eab3981f7a..9bba84ceb0 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -94,7 +94,6 @@ SOURCES += \ io/qloggingregistry.cpp win32 { - SOURCES += io/qsettings_win.cpp SOURCES += io/qfsfileengine_win.cpp SOURCES += io/qlockfile_win.cpp @@ -105,6 +104,7 @@ win32 { SOURCES += io/qstandardpaths_win.cpp !winrt { + SOURCES += io/qsettings_win.cpp HEADERS += io/qwindowspipewriter_p.h SOURCES += io/qwindowspipewriter.cpp diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index ebcaf062e3..e3adcad4bd 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -80,6 +80,16 @@ # include #endif +#ifdef Q_OS_WINRT +#include +#include +#include +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Storage; +#endif + #ifndef CSIDL_COMMON_APPDATA #define CSIDL_COMMON_APPDATA 0x0023 // All Users\Application Data #endif @@ -365,7 +375,7 @@ after_loop: // see also qsettings_win.cpp and qsettings_mac.cpp -#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC) +#if defined(Q_OS_WINRT) || (!defined(Q_OS_WIN) && !defined(Q_OS_MAC)) QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings::Scope scope, const QString &organization, const QString &application) { @@ -373,7 +383,7 @@ QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings:: } #endif -#if !defined(Q_OS_WIN) +#if defined(Q_OS_WINRT) || !defined(Q_OS_WIN) QSettingsPrivate *QSettingsPrivate::create(const QString &fileName, QSettings::Format format) { return new QConfFileSettingsPrivate(fileName, format); @@ -1019,7 +1029,7 @@ void QConfFileSettingsPrivate::initAccess() sync(); // loads the files the first time } -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) static QString windowsConfigPath(int type) { QString result; @@ -1061,7 +1071,40 @@ static QString windowsConfigPath(int type) return result; } -#endif // Q_OS_WIN +#elif defined(Q_OS_WINRT) // Q_OS_WIN && !Q_OS_WINRT +static QString windowsConfigPath(int type) +{ + static QString result; + while (result.isEmpty()) { + ComPtr applicationDataStatics; + if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_ApplicationData).Get(), &applicationDataStatics))) + return result; + ComPtr applicationData; + if (FAILED(applicationDataStatics->get_Current(&applicationData))) + return result; + ComPtr localFolder; + if (FAILED(applicationData->get_LocalFolder(&localFolder))) + return result; + ComPtr localFolderItem; + if (FAILED(localFolder.As(&localFolderItem))) + return result; + HSTRING path; + if (FAILED(localFolderItem->get_Path(&path))) + return result; + result = QString::fromWCharArray(WindowsGetStringRawBuffer(path, nullptr)); + } + + switch (type) { + case CSIDL_COMMON_APPDATA: + return result + QLatin1String("\\qt-common"); + case CSIDL_APPDATA: + return result + QLatin1String("\\qt-user"); + default: + break; + } + return result; +} +#endif // Q_OS_WINRT static inline int pathHashKey(QSettings::Format format, QSettings::Scope scope) { @@ -1447,10 +1490,18 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo) QString writeSemName = QLatin1String("QSettingsWriteSem "); writeSemName.append(file.fileName()); +#ifndef Q_OS_WINRT writeSemaphore = CreateSemaphore(0, 1, 1, reinterpret_cast(writeSemName.utf16())); +#else + writeSemaphore = CreateSemaphoreEx(0, 1, 1, reinterpret_cast(writeSemName.utf16()), 0, SEMAPHORE_ALL_ACCESS); +#endif if (writeSemaphore) { +#ifndef Q_OS_WINRT WaitForSingleObject(writeSemaphore, INFINITE); +#else + WaitForSingleObjectEx(writeSemaphore, INFINITE, FALSE); +#endif } else { setStatus(QSettings::AccessError); return; @@ -1463,11 +1514,19 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo) QString readSemName(QLatin1String("QSettingsReadSem ")); readSemName.append(file.fileName()); +#ifndef Q_OS_WINRT readSemaphore = CreateSemaphore(0, FileLockSemMax, FileLockSemMax, reinterpret_cast(readSemName.utf16())); +#else + readSemaphore = CreateSemaphoreEx(0, FileLockSemMax, FileLockSemMax, reinterpret_cast(readSemName.utf16()), 0, SEMAPHORE_ALL_ACCESS); +#endif if (readSemaphore) { for (int i = 0; i < numReadLocks; ++i) +#ifndef Q_OS_WINRT WaitForSingleObject(readSemaphore, INFINITE); +#else + WaitForSingleObjectEx(readSemaphore, INFINITE, FALSE); +#endif } else { setStatus(QSettings::AccessError); if (writeSemaphore != 0) { From 7e1654cd75a6bbf56632461e4f829fd7578f87ca Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Fri, 6 Sep 2013 12:39:49 +0200 Subject: [PATCH 009/684] WinRT: Stub out QStandardPaths It might be possible to obtain special directories like documents and music if the according rights are granted. Change-Id: I086c341236b831326acc74754d067867d0eda04b Reviewed-by: Friedemann Kleint --- src/corelib/io/io.pri | 4 +- src/corelib/io/qstandardpaths_winrt.cpp | 74 +++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 src/corelib/io/qstandardpaths_winrt.cpp diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 9bba84ceb0..701f79d21e 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -101,12 +101,12 @@ win32 { HEADERS += io/qfilesystemwatcher_win_p.h SOURCES += io/qfilesystemengine_win.cpp SOURCES += io/qfilesystemiterator_win.cpp - SOURCES += io/qstandardpaths_win.cpp !winrt { SOURCES += io/qsettings_win.cpp HEADERS += io/qwindowspipewriter_p.h SOURCES += io/qwindowspipewriter.cpp + SOURCES += io/qstandardpaths_win.cpp wince* { SOURCES += io/qprocess_wince.cpp @@ -119,6 +119,8 @@ win32 { io/qwinoverlappedionotifier.cpp \ io/qwindowspipereader.cpp } + } else { + SOURCES += io/qstandardpaths_winrt.cpp } } else:unix|integrity { SOURCES += \ diff --git a/src/corelib/io/qstandardpaths_winrt.cpp b/src/corelib/io/qstandardpaths_winrt.cpp new file mode 100644 index 0000000000..55a801332e --- /dev/null +++ b/src/corelib/io/qstandardpaths_winrt.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** 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 "qstandardpaths.h" + +#include +#include +#include +#include + +#include + +#ifndef QT_NO_STANDARDPATHS + +QT_BEGIN_NAMESPACE + +static QString convertCharArray(const wchar_t *path) +{ + return QDir::fromNativeSeparators(QString::fromWCharArray(path)); +} + +QString QStandardPaths::writableLocation(StandardLocation type) +{ + Q_UNUSED(type) + Q_UNIMPLEMENTED(); + return QString(); +} + +QStringList QStandardPaths::standardLocations(StandardLocation type) +{ + return QStringList(writableLocation(type)); +} + +QT_END_NAMESPACE + +#endif // QT_NO_STANDARDPATHS From bb4869a0c53a7e4aeda12f80be834cf18811d3f6 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Fri, 20 Sep 2013 11:40:16 +0200 Subject: [PATCH 010/684] WinRT: Disable network As network reimplementation is not in place yet it is disabled for now. Once I78ea88901a30280d4098b75ef7398c2628dd19c8 is done this can be reverted. Change-Id: I042427fff9664fd8b7ea0a59476d6a6bb6b4eaec Reviewed-by: Andrew Knight --- src/src.pro | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/src.pro b/src/src.pro index 377e8cb650..641a8a98a6 100644 --- a/src/src.pro +++ b/src/src.pro @@ -141,6 +141,12 @@ SUBDIRS += src_plugins src_tools_qdoc nacl: SUBDIRS -= src_network src_testlib +winrt { + src_platformsupport.depends -= src_network + src_plugins.depends -= src_network + SUBDIRS -= src_network +} + android:!android-no-sdk: SUBDIRS += src_android TR_EXCLUDE = \ @@ -148,4 +154,4 @@ TR_EXCLUDE = \ src_tools_bootstrap_dbus src_tools_qdbusxml2cpp src_tools_qdbuscpp2xml sub-tools.depends = $$TOOLS -QMAKE_EXTRA_TARGETS = sub-tools \ No newline at end of file +QMAKE_EXTRA_TARGETS = sub-tools From 4a7630085429248f47b3fca1365d928a058a6bad Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Mon, 23 Sep 2013 14:05:54 +0200 Subject: [PATCH 011/684] WinRT: Use UtcTimeZone instead of QWinTimeZone backend As registry access isn't possible on WinRT it cannot use QWinTimeZone as backend. Instead it uses QUtcTimeZone. Change-Id: I51c59a187e3da6e957d0b3f6376069d55c9fc2ec Reviewed-by: Andrew Knight Reviewed-by: John Layt --- src/corelib/tools/qtimezone.cpp | 6 ++++-- src/corelib/tools/tools.pri | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp index cdd0aba102..890798b421 100644 --- a/src/corelib/tools/qtimezone.cpp +++ b/src/corelib/tools/qtimezone.cpp @@ -65,7 +65,8 @@ static QTimeZonePrivate *newBackendTimeZone() return new QMacTimeZonePrivate(); #elif defined Q_OS_UNIX return new QTzTimeZonePrivate(); -#elif defined Q_OS_WIN + // Registry based timezone backend not available on WinRT +#elif defined Q_OS_WIN && !defined Q_OS_WINRT return new QWinTimeZonePrivate(); #elif defined QT_USE_ICU return new QIcuTimeZonePrivate(); @@ -89,7 +90,8 @@ static QTimeZonePrivate *newBackendTimeZone(const QByteArray &olsenId) return new QMacTimeZonePrivate(olsenId); #elif defined Q_OS_UNIX return new QTzTimeZonePrivate(olsenId); -#elif defined Q_OS_WIN + // Registry based timezone backend not available on WinRT +#elif defined Q_OS_WIN && !defined Q_OS_WINRT return new QWinTimeZonePrivate(olsenId); #elif defined QT_USE_ICU return new QIcuTimeZonePrivate(olsenId); diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index e043a4cd15..a645961236 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -124,8 +124,10 @@ else:blackberry { HEADERS += tools/qlocale_blackberry.h } else:unix:SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_unix.cpp tools/qtimezoneprivate_tz.cpp -else:win32:SOURCES += tools/qelapsedtimer_win.cpp tools/qlocale_win.cpp tools/qtimezoneprivate_win.cpp -else:integrity:SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_unix.cpp +else:win32 { + SOURCES += tools/qelapsedtimer_win.cpp tools/qlocale_win.cpp + !winrt: SOURCES += tools/qtimezoneprivate_win.cpp +} else:integrity:SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_unix.cpp else:SOURCES += tools/qelapsedtimer_generic.cpp contains(QT_CONFIG, zlib) { From 88999e9ea037ee79557d0c012ad9fdfc72fb5ece Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 26 Sep 2013 14:10:45 +0200 Subject: [PATCH 012/684] QPen: optimize population of dd->dashPattern Change-Id: I02b3bb9b503303b931f075f899126a506f9e25d0 Reviewed-by: Olivier Goffart --- src/gui/painting/qpen.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gui/painting/qpen.cpp b/src/gui/painting/qpen.cpp index 4122322e36..d27e0c409d 100644 --- a/src/gui/painting/qpen.cpp +++ b/src/gui/painting/qpen.cpp @@ -447,15 +447,19 @@ QVector QPen::dashPattern() const switch (d->style) { case Qt::DashLine: + dd->dashPattern.reserve(2); dd->dashPattern << dash << space; break; case Qt::DotLine: + dd->dashPattern.reserve(2); dd->dashPattern << dot << space; break; case Qt::DashDotLine: + dd->dashPattern.reserve(4); dd->dashPattern << dash << space << dot << space; break; case Qt::DashDotDotLine: + dd->dashPattern.reserve(6); dd->dashPattern << dash << space << dot << space << dot << space; break; default: From e37001aad7f6e4bbad250addba033f1eaf97d566 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Wed, 31 Jul 2013 15:43:09 +0200 Subject: [PATCH 013/684] Say hello to qFloatDistance() This function is useful if a floating point comparison requires a certain precision. The return value can be considered as the precision. For instance, if you want to compare two 32-bit floating point values and all you need is a 24-bit precision, you can use this function like this: if (qFloatDistance(a,b) < (1 << 7)) { // The last 7 bits are not // significant // precise enough } Task-number: QTBUG-32632 Change-Id: I020a58d2f9f9452ac3c510b4bb560dc806f0d93c Reviewed-by: Shawn Rutledge Reviewed-by: Thiago Macieira --- src/corelib/global/qnumeric.cpp | 136 ++++++++++++++++++ src/corelib/global/qnumeric.h | 3 + .../corelib/global/qnumeric/tst_qnumeric.cpp | 93 ++++++++++++ 3 files changed, 232 insertions(+) diff --git a/src/corelib/global/qnumeric.cpp b/src/corelib/global/qnumeric.cpp index 5e71753c8a..83ccb7075d 100644 --- a/src/corelib/global/qnumeric.cpp +++ b/src/corelib/global/qnumeric.cpp @@ -41,6 +41,7 @@ #include "qnumeric.h" #include "qnumeric_p.h" +#include QT_BEGIN_NAMESPACE @@ -99,4 +100,139 @@ Q_CORE_EXPORT double qQNaN() { return qt_qnan(); } Q_CORE_EXPORT double qInf() { return qt_inf(); } + +/*! + \internal + */ +static inline quint32 f2i(float f) +{ + quint32 i; + memcpy(&i, &f, sizeof(f)); + return i; +} + +/*! + Returns the number of representable floating-point numbers between \a a and \a b. + + This function provides an alternative way of doing approximated comparisons of floating-point + numbers similar to qFuzzyCompare(). However, it returns the distance between two numbers, which + gives the caller a possibility to choose the accepted error. Errors are relative, so for + instance the distance between 1.0E-5 and 1.00001E-5 will give 110, while the distance between + 1.0E36 and 1.00001E36 will give 127. + + This function is useful if a floating point comparison requires a certain precision. + Therefore, if \a a and \a b are equal it will return 0. The maximum value it will return for 32-bit + floating point numbers is 4,278,190,078. This is the distance between \c{-FLT_MAX} and + \c{+FLT_MAX}. + + The function does not give meaningful results if any of the arguments are \c Infinite or \c NaN. + You can check for this by calling qIsFinite(). + + The return value can be considered as the "error", so if you for instance want to compare + two 32-bit floating point numbers and all you need is an approximated 24-bit precision, you can + use this function like this: + + \code + if (qFloatDistance(a, b) < (1 << 7)) { // The last 7 bits are not + // significant + // precise enough + } + \endcode + + \sa qFuzzyCompare() + \relates +*/ +Q_CORE_EXPORT quint32 qFloatDistance(float a, float b) +{ + static const quint32 smallestPositiveFloatAsBits = 0x00000001; // denormalized, (SMALLEST), (1.4E-45) + /* Assumes: + * IEE754 format. + * Integers and floats have the same endian + */ + Q_STATIC_ASSERT(sizeof(quint32) == sizeof(float)); + Q_ASSERT(qIsFinite(a) && qIsFinite(b)); + if (a == b) + return 0; + if ((a < 0) != (b < 0)) { + // if they have different signs + if (a < 0) + a = -a; + else /*if (b < 0)*/ + b = -b; + return qFloatDistance(0.0F, a) + qFloatDistance(0.0F, b); + } + if (a < 0) { + a = -a; + b = -b; + } + // at this point a and b should not be negative + + // 0 is special + if (!a) + return f2i(b) - smallestPositiveFloatAsBits + 1; + if (!b) + return f2i(a) - smallestPositiveFloatAsBits + 1; + + // finally do the common integer subtraction + return a > b ? f2i(a) - f2i(b) : f2i(b) - f2i(a); +} + + +/*! + \internal + */ +static inline quint64 d2i(double d) +{ + quint64 i; + memcpy(&i, &d, sizeof(d)); + return i; +} + +/*! + Returns the number of representable floating-point numbers between \a a and \a b. + + This function serves the same purpose as \c{qFloatDistance(float, float)}, but + returns the distance between two \c double numbers. Since the range is larger + than for two \c float numbers (\c{[-DBL_MAX,DBL_MAX]}), the return type is quint64. + + + \sa qFuzzyCompare() + \relates +*/ +Q_CORE_EXPORT quint64 qFloatDistance(double a, double b) +{ + static const quint64 smallestPositiveFloatAsBits = 0x1; // denormalized, (SMALLEST) + /* Assumes: + * IEE754 format double precision + * Integers and floats have the same endian + */ + Q_STATIC_ASSERT(sizeof(quint64) == sizeof(double)); + Q_ASSERT(qIsFinite(a) && qIsFinite(b)); + if (a == b) + return 0; + if ((a < 0) != (b < 0)) { + // if they have different signs + if (a < 0) + a = -a; + else /*if (b < 0)*/ + b = -b; + return qFloatDistance(0.0, a) + qFloatDistance(0.0, b); + } + if (a < 0) { + a = -a; + b = -b; + } + // at this point a and b should not be negative + + // 0 is special + if (!a) + return d2i(b) - smallestPositiveFloatAsBits + 1; + if (!b) + return d2i(a) - smallestPositiveFloatAsBits + 1; + + // finally do the common integer subtraction + return a > b ? d2i(a) - d2i(b) : d2i(b) - d2i(a); +} + + QT_END_NAMESPACE diff --git a/src/corelib/global/qnumeric.h b/src/corelib/global/qnumeric.h index 25db5443eb..633486dff1 100644 --- a/src/corelib/global/qnumeric.h +++ b/src/corelib/global/qnumeric.h @@ -57,6 +57,9 @@ Q_CORE_EXPORT double qSNaN(); Q_CORE_EXPORT double qQNaN(); Q_CORE_EXPORT double qInf(); +Q_CORE_EXPORT quint32 qFloatDistance(float a, float b); +Q_CORE_EXPORT quint64 qFloatDistance(double a, double b); + #define Q_INFINITY (QT_PREPEND_NAMESPACE(qInf)()) #define Q_SNAN (QT_PREPEND_NAMESPACE(qSNaN)()) #define Q_QNAN (QT_PREPEND_NAMESPACE(qQNaN)()) diff --git a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp index 20f99e9191..36e01a0ccd 100644 --- a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp +++ b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp @@ -44,6 +44,7 @@ #include #include +#include class tst_QNumeric: public QObject { @@ -53,6 +54,10 @@ private slots: void fuzzyCompare_data(); void fuzzyCompare(); void qNan(); + void floatDistance_data(); + void floatDistance(); + void floatDistance_double_data(); + void floatDistance_double(); }; void tst_QNumeric::fuzzyCompare_data() @@ -121,5 +126,93 @@ void tst_QNumeric::qNan() QVERIFY(qFuzzyCompare(1/inf, 0.0)); } +void tst_QNumeric::floatDistance_data() +{ + QTest::addColumn("val1"); + QTest::addColumn("val2"); + QTest::addColumn("expectedDistance"); + + // exponent: 8 bits + // mantissa: 23 bits + const quint32 number_of_denormals = (1 << 23) - 1; // Set to 0 if denormals are not included + + quint32 _0_to_1 = quint32((1 << 23) * 126 + 1 + number_of_denormals); // We need +1 to include the 0 + quint32 _1_to_2 = quint32(1 << 23); + + // We don't need +1 because FLT_MAX has all bits set in the mantissa. (Thus mantissa + // have not wrapped back to 0, which would be the case for 1 in _0_to_1 + quint32 _0_to_FLT_MAX = quint32((1 << 23) * 254) + number_of_denormals; + + quint32 _0_to_FLT_MIN = 1 + number_of_denormals; + QTest::newRow("[0,FLT_MIN]") << 0.F << FLT_MIN << _0_to_FLT_MIN; + QTest::newRow("[0,FLT_MAX]") << 0.F << FLT_MAX << _0_to_FLT_MAX; + QTest::newRow("[1,1.5]") << 1.0F << 1.5F << quint32(1 << 22); + QTest::newRow("[0,1]") << 0.F << 1.0F << _0_to_1; + QTest::newRow("[0.5,1]") << 0.5F << 1.0F << quint32(1 << 23); + QTest::newRow("[1,2]") << 1.F << 2.0F << _1_to_2; + QTest::newRow("[-1,+1]") << -1.F << +1.0F << 2 * _0_to_1; + QTest::newRow("[-1,0]") << -1.F << 0.0F << _0_to_1; + QTest::newRow("[-1,FLT_MAX]") << -1.F << FLT_MAX << _0_to_1 + _0_to_FLT_MAX; + QTest::newRow("[-2,-1") << -2.F << -1.F << _1_to_2; + QTest::newRow("[-1,-2") << -1.F << -2.F << _1_to_2; + QTest::newRow("[FLT_MIN,FLT_MAX]") << FLT_MIN << FLT_MAX << _0_to_FLT_MAX - _0_to_FLT_MIN; + QTest::newRow("[-FLT_MAX,FLT_MAX]") << -FLT_MAX << FLT_MAX << (2*_0_to_FLT_MAX); + float denormal = FLT_MIN; + denormal/=2.0F; + QTest::newRow("denormal") << 0.F << denormal << _0_to_FLT_MIN/2; +} + +void tst_QNumeric::floatDistance() +{ + QFETCH(float, val1); + QFETCH(float, val2); + QFETCH(quint32, expectedDistance); + QCOMPARE(qFloatDistance(val1, val2), expectedDistance); +} + +void tst_QNumeric::floatDistance_double_data() +{ + QTest::addColumn("val1"); + QTest::addColumn("val2"); + QTest::addColumn("expectedDistance"); + + // exponent: 11 bits + // mantissa: 52 bits + const quint64 number_of_denormals = (Q_UINT64_C(1) << 52) - 1; // Set to 0 if denormals are not included + + quint64 _0_to_1 = (Q_UINT64_C(1) << 52) * ((1 << (11-1)) - 2) + 1 + number_of_denormals; // We need +1 to include the 0 + quint64 _1_to_2 = Q_UINT64_C(1) << 52; + + // We don't need +1 because DBL_MAX has all bits set in the mantissa. (Thus mantissa + // have not wrapped back to 0, which would be the case for 1 in _0_to_1 + quint64 _0_to_DBL_MAX = quint64((Q_UINT64_C(1) << 52) * ((1 << 11) - 2)) + number_of_denormals; + + quint64 _0_to_DBL_MIN = 1 + number_of_denormals; + QTest::newRow("[0,DBL_MIN]") << 0.0 << DBL_MIN << _0_to_DBL_MIN; + QTest::newRow("[0,DBL_MAX]") << 0.0 << DBL_MAX << _0_to_DBL_MAX; + QTest::newRow("[1,1.5]") << 1.0 << 1.5 << (Q_UINT64_C(1) << 51); + QTest::newRow("[0,1]") << 0.0 << 1.0 << _0_to_1; + QTest::newRow("[0.5,1]") << 0.5 << 1.0 << (Q_UINT64_C(1) << 52); + QTest::newRow("[1,2]") << 1.0 << 2.0 << _1_to_2; + QTest::newRow("[-1,+1]") << -1.0 << +1.0 << 2 * _0_to_1; + QTest::newRow("[-1,0]") << -1.0 << 0.0 << _0_to_1; + QTest::newRow("[-1,DBL_MAX]") << -1.0 << DBL_MAX << _0_to_1 + _0_to_DBL_MAX; + QTest::newRow("[-2,-1") << -2.0 << -1.0 << _1_to_2; + QTest::newRow("[-1,-2") << -1.0 << -2.0 << _1_to_2; + QTest::newRow("[DBL_MIN,DBL_MAX]") << DBL_MIN << DBL_MAX << _0_to_DBL_MAX - _0_to_DBL_MIN; + QTest::newRow("[-DBL_MAX,DBL_MAX]") << -DBL_MAX << DBL_MAX << (2*_0_to_DBL_MAX); + double denormal = DBL_MIN; + denormal/=2.0; + QTest::newRow("denormal") << 0.0 << denormal << _0_to_DBL_MIN/2; +} + +void tst_QNumeric::floatDistance_double() +{ + QFETCH(double, val1); + QFETCH(double, val2); + QFETCH(quint64, expectedDistance); + QCOMPARE(qFloatDistance(val1, val2), expectedDistance); +} + QTEST_APPLESS_MAIN(tst_QNumeric) #include "tst_qnumeric.moc" From bd78389fc4fe0a4367696ba2fdcc6e8d09863698 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Fri, 13 Sep 2013 10:44:08 +0300 Subject: [PATCH 014/684] WinRT: Fix Widget builds Tweak pri files and preprocessor usage to support widgets under WinRT. Change-Id: I6dc7d160078c0da343d6d39d2a0d52112c6f9f59 Reviewed-by: Andrew Knight Reviewed-by: Friedemann Kleint --- src/widgets/dialogs/qfiledialog.cpp | 2 +- src/widgets/dialogs/qfilesystemmodel.cpp | 2 +- src/widgets/dialogs/qmessagebox.cpp | 4 ++-- src/widgets/itemviews/qfileiconprovider.cpp | 8 +++++--- src/widgets/kernel/qapplication_qpa.cpp | 4 ++-- src/widgets/kernel/qwidget.cpp | 2 +- src/widgets/kernel/qwidgetbackingstore.cpp | 6 +++--- src/widgets/kernel/win.pri | 2 +- src/widgets/styles/qwindowsstyle.cpp | 20 ++++++++++++-------- src/widgets/util/util.pri | 2 +- src/widgets/widgets/qsplashscreen.cpp | 4 +++- 11 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 62cec34b2b..c9394dd9f8 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -1644,7 +1644,7 @@ int QFileDialogPrivate::maxNameLength(const QString &path) { #if defined(Q_OS_UNIX) return ::pathconf(QFile::encodeName(path).data(), _PC_NAME_MAX); -#elif defined(Q_OS_WINCE) +#elif defined(Q_OS_WINCE) || defined(Q_OS_WINRT) Q_UNUSED(path); return MAX_PATH; #elif defined(Q_OS_WIN) diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index c86c7ff931..72dc8a5d05 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -1713,7 +1713,7 @@ QFileSystemModelPrivate::QFileSystemNode* QFileSystemModelPrivate::addNode(QFile #ifndef QT_NO_FILESYSTEMWATCHER node->populate(info); #endif -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) //The parentNode is "" so we are listing the drives if (parentNode->fileName.isEmpty()) { wchar_t name[MAX_PATH + 1]; diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp index da5ec8dc8a..90c8021d41 100644 --- a/src/widgets/dialogs/qmessagebox.cpp +++ b/src/widgets/dialogs/qmessagebox.cpp @@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) HMENU qt_getWindowsSystemMenu(const QWidget *w) { if (QWindow *window = QApplicationPrivate::windowForWidget(w)) @@ -1608,7 +1608,7 @@ void QMessageBox::showEvent(QShowEvent *e) QAccessibleEvent event(this, QAccessible::Alert); QAccessible::updateAccessibility(&event); #endif -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) if (const HMENU systemMenu = qt_getWindowsSystemMenu(this)) { EnableMenuItem(systemMenu, SC_CLOSE, d->detectedEscapeButton ? MF_BYCOMMAND|MF_ENABLED : MF_BYCOMMAND|MF_GRAYED); diff --git a/src/widgets/itemviews/qfileiconprovider.cpp b/src/widgets/itemviews/qfileiconprovider.cpp index 71697ddc40..b12ab736f4 100644 --- a/src/widgets/itemviews/qfileiconprovider.cpp +++ b/src/widgets/itemviews/qfileiconprovider.cpp @@ -53,8 +53,10 @@ #if defined(Q_OS_WIN) # include -# include -# include +# ifndef Q_OS_WINRT +# include +# include +# endif #endif #if defined(Q_OS_UNIX) && !defined(QT_NO_STYLE_GTK) @@ -313,7 +315,7 @@ QIcon QFileIconProvider::icon(const QFileInfo &info) const return retIcon; if (info.isRoot()) -#if defined (Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined (Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) { UINT type = GetDriveType((wchar_t *)info.absoluteFilePath().utf16()); diff --git a/src/widgets/kernel/qapplication_qpa.cpp b/src/widgets/kernel/qapplication_qpa.cpp index 1f8e950d00..7977ae3528 100644 --- a/src/widgets/kernel/qapplication_qpa.cpp +++ b/src/widgets/kernel/qapplication_qpa.cpp @@ -451,7 +451,7 @@ void qt_init(QApplicationPrivate *priv, int type) QApplicationPrivate::initializeWidgetFontHash(); } -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) // #fixme: Remove. static HDC displayDC = 0; // display device context @@ -470,7 +470,7 @@ void qt_cleanup() QColormap::cleanup(); QApplicationPrivate::active_window = 0; //### this should not be necessary -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) if (displayDC) { ReleaseDC(0, displayDC); displayDC = 0; diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 02d95d2fa5..6db52e1cbc 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -4174,7 +4174,7 @@ const QPalette &QWidget::palette() const if (!isEnabled()) { data->pal.setCurrentColorGroup(QPalette::Disabled); } else if ((!isVisible() || isActiveWindow()) -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) && !QApplicationPrivate::isBlockedByModal(const_cast(this)) #endif ) { diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 02fa80bef6..9fcd14e813 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -120,7 +120,7 @@ static inline void qt_flush(QWidget *widget, const QRegion ®ion, QBackingStor } #ifndef QT_NO_PAINT_DEBUG -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) static void showYellowThing_win(QWidget *widget, const QRegion ®ion, int msec) { @@ -160,7 +160,7 @@ static void showYellowThing_win(QWidget *widget, const QRegion ®ion, int msec QGuiApplication::platformNativeInterface()->nativeResourceForWindow(QByteArrayLiteral("releaseDC"), nativeWindow); ::Sleep(msec); } -#endif // Q_OS_WIN +#endif // defined(Q_OS_WIN) && !defined(Q_OS_WINRT) void QWidgetBackingStore::showYellowThing(QWidget *widget, const QRegion &toBePainted, int msec, bool unclipped) { @@ -175,7 +175,7 @@ void QWidgetBackingStore::showYellowThing(QWidget *widget, const QRegion &toBePa widget = nativeParent; } -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) Q_UNUSED(unclipped); showYellowThing_win(widget, paintRegion, msec); #else diff --git a/src/widgets/kernel/win.pri b/src/widgets/kernel/win.pri index dd47664c28..18bd692476 100644 --- a/src/widgets/kernel/win.pri +++ b/src/widgets/kernel/win.pri @@ -2,6 +2,6 @@ # -------------------------------------------------------------------- INCLUDEPATH += ../3rdparty/wintab -!wince* { +!wince*:!winrt { LIBS *= -lshell32 } diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index b153d05885..85f0461f48 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -252,7 +252,7 @@ void QWindowsStyle::polish(QApplication *app) d->inactiveGradientCaptionColor = app->palette().dark().color(); d->inactiveCaptionText = app->palette().background().color(); -#if defined(Q_OS_WIN) //fetch native title bar colors +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) //fetch native title bar colors if(app->desktopSettingsAware()){ DWORD activeCaption = GetSysColor(COLOR_ACTIVECAPTION); DWORD gradientActiveCaption = GetSysColor(COLOR_GRADIENTACTIVECAPTION); @@ -413,6 +413,7 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW #if defined(Q_OS_WIN) +#ifndef Q_OS_WINRT // There is no title bar in Windows Runtime applications case PM_TitleBarHeight: if (widget && (widget->windowType() == Qt::Tool)) { // MS always use one less than they say @@ -426,16 +427,17 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW } break; +#endif // !Q_OS_WINRT case PM_ScrollBarExtent: { -#ifndef Q_OS_WINCE +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) NONCLIENTMETRICS ncm; ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)) ret = qMax(ncm.iScrollHeight, ncm.iScrollWidth); else -#endif +#endif // !Q_OS_WINCE && !Q_OS_WINRT ret = QCommonStyle::pixelMetric(pm, opt, widget); } break; @@ -446,6 +448,7 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW break; #if defined(Q_OS_WIN) +#ifndef Q_OS_WINRT // Mdi concept not available for WinRT applications case PM_MdiSubWindowFrameWidth: #if defined(Q_OS_WINCE) ret = GetSystemMetrics(SM_CYDLGFRAME); @@ -453,7 +456,8 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW ret = GetSystemMetrics(SM_CYFRAME); #endif break; -#endif +#endif // !Q_OS_WINRT +#endif // Q_OS_WIN case PM_ToolBarItemMargin: ret = 1; break; @@ -477,7 +481,7 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW QPixmap QWindowsStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const { -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) QPixmap desktopIcon; switch(standardPixmap) { case SP_DriveCDIcon: @@ -516,7 +520,7 @@ QPixmap QWindowsStyle::standardPixmap(StandardPixmap standardPixmap, const QStyl if (!desktopIcon.isNull()) { return desktopIcon; } -#endif +#endif // Q_OS_WIN && !Q_OS_WINCE && !Q_OS_WINRT return QCommonStyle::standardPixmap(standardPixmap, opt, widget); } @@ -554,7 +558,7 @@ int QWindowsStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QWid ret = 0; break; -#if defined(Q_OS_WIN) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) // Option not used on WinRT -> common style case SH_UnderlineShortcut: { ret = 1; @@ -590,7 +594,7 @@ int QWindowsStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QWid #endif // QT_NO_ACCESSIBILITY break; } -#endif +#endif // Q_OS_WIN && !Q_OS_WINRT #ifndef QT_NO_RUBBERBAND case SH_RubberBand_Mask: if (const QStyleOptionRubberBand *rbOpt = qstyleoption_cast(opt)) { diff --git a/src/widgets/util/util.pri b/src/widgets/util/util.pri index 072c736f71..b4bbc5fc30 100644 --- a/src/widgets/util/util.pri +++ b/src/widgets/util/util.pri @@ -27,7 +27,7 @@ SOURCES += \ util/qundostack.cpp \ util/qundoview.cpp -win32:!wince* { +win32:!wince*:!winrt { SOURCES += util/qsystemtrayicon_win.cpp } else:contains(QT_CONFIG, xcb) { SOURCES += util/qsystemtrayicon_x11.cpp diff --git a/src/widgets/widgets/qsplashscreen.cpp b/src/widgets/widgets/qsplashscreen.cpp index b2a0d3f8b8..db9db68039 100644 --- a/src/widgets/widgets/qsplashscreen.cpp +++ b/src/widgets/widgets/qsplashscreen.cpp @@ -251,7 +251,9 @@ inline static bool waitForWindowExposed(QWindow *window, int timeout = 1000) break; QCoreApplication::processEvents(QEventLoop::AllEvents, remaining); QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); -#ifdef Q_OS_WIN +#if defined(Q_OS_WINRT) + WaitForSingleObjectEx(GetCurrentThread(), TimeOutMs, false); +#elif defined(Q_OS_WIN) Sleep(uint(TimeOutMs)); #else struct timespec ts = { TimeOutMs / 1000, (TimeOutMs % 1000) * 1000 * 1000 }; From 3e1c3a051dc12b222fcf3efa185ebd13f823bc8d Mon Sep 17 00:00:00 2001 From: Donald Carr Date: Wed, 2 Oct 2013 00:10:01 -0700 Subject: [PATCH 015/684] Fix clang build for libc++ Successfully builds Qt 5.2 with: QMAKE_CXXFLAGS_CXX11 += -std=c++11 -stdlib=libc++ QMAKE_LFLAGS_CXX11 += -stdlib=libc++ -lc++abi against: clang version 3.3 (tags/RELEASE_33/final) Change-Id: I778f9410c6563e78bc77ae4c20097fa561503ba1 Reviewed-by: Simon Hausmann --- .../platforminputcontexts/compose/generator/qtablegenerator.cpp | 1 + src/plugins/platforms/xcb/qxcbsessionmanager.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp index c222b62a36..4cfc2a6cc4 100644 --- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp +++ b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp @@ -57,6 +57,7 @@ #include // strchr, strncmp, etc. #include // strncasecmp +#include // LC_CTYPE TableGenerator::TableGenerator() : m_state(NoErrors), m_systemComposeDir(QString()) diff --git a/src/plugins/platforms/xcb/qxcbsessionmanager.cpp b/src/plugins/platforms/xcb/qxcbsessionmanager.cpp index 6abe24b7ab..a3d6a65695 100644 --- a/src/plugins/platforms/xcb/qxcbsessionmanager.cpp +++ b/src/plugins/platforms/xcb/qxcbsessionmanager.cpp @@ -49,6 +49,7 @@ #include #include +#include // ERANGE class QSmSocketReceiver : public QObject { From c097670bf8f9c3871ca12bf9a257702f8dc4e947 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Thu, 19 Sep 2013 13:04:49 +0200 Subject: [PATCH 016/684] WinRT: Added missing WIN32 define to qmake.conf Without that define here moc cannot handle qsystemdetection properly. While having to touch the mkspecs I also removed the no longer needed WINRT define. Change-Id: I0609bd173c7bc14ccdd862afc777d7793dda02b8 Reviewed-by: Joerg Bornemann Reviewed-by: Andrew Knight --- mkspecs/common/winrt_winphone/qmake.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mkspecs/common/winrt_winphone/qmake.conf b/mkspecs/common/winrt_winphone/qmake.conf index dd4b7f1b94..b5d724eef6 100644 --- a/mkspecs/common/winrt_winphone/qmake.conf +++ b/mkspecs/common/winrt_winphone/qmake.conf @@ -8,9 +8,9 @@ MAKEFILE_GENERATOR = MSBUILD QMAKE_COMPILER = msvc QMAKE_PLATFORM = winrt win32 CONFIG += incremental flat precompile_header autogen_precompile_source debug_and_release debug_and_release_target no_generated_target_info autogen_wmappmanifest rtti -DEFINES += UNICODE WINRT QT_LARGEFILE_SUPPORT Q_BYTE_ORDER=Q_LITTLE_ENDIAN \ +DEFINES += UNICODE WIN32 QT_LARGEFILE_SUPPORT Q_BYTE_ORDER=Q_LITTLE_ENDIAN \ QT_NO_PRINTER QT_NO_PRINTDIALOG # TODO: Remove when printing is re-enabled -QMAKE_COMPILER_DEFINES += _MSC_VER=1700 WINRT +QMAKE_COMPILER_DEFINES += _MSC_VER=1700 DEPLOYMENT_PLUGIN += qwinrt From c6af0a504f2acced8147a1dd78bc249da49d3d99 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Sun, 1 Sep 2013 19:05:46 +0300 Subject: [PATCH 017/684] WinRT: Fix various test compilations - Remove irrelevant test subdirs via .pro files - Follow WinCE codepaths where applicable - Replace unsupported Win32 APIs with WinRT equivalents This does not aim to fix any failures in the tests themselves; it only makes them compile. Change-Id: Ia82bc0cc402891f8f6238d4c261ee9152b51be80 Reviewed-by: Maurice Kalinowski Reviewed-by: Friedemann Kleint --- tests/auto/corelib/io/io.pro | 6 +++++ tests/auto/corelib/io/qfile/test/test.pro | 2 +- tests/auto/corelib/io/qfile/tst_qfile.cpp | 20 ++++++++++---- tests/auto/corelib/io/qfileinfo/qfileinfo.pro | 2 +- .../corelib/io/qfileinfo/tst_qfileinfo.cpp | 16 ++++++------ .../tst_qfilesystemwatcher.cpp | 6 +++++ .../corelib/io/qsettings/tst_qsettings.cpp | 8 +++--- .../io/qtemporarydir/tst_qtemporarydir.cpp | 4 +-- .../io/qtemporaryfile/tst_qtemporaryfile.cpp | 4 +-- tests/auto/corelib/kernel/kernel.pro | 2 +- .../corelib/kernel/qeventloop/qeventloop.pro | 2 +- .../corelib/kernel/qmetatype/qmetatype.pro | 4 +-- .../qreadwritelock/tst_qreadwritelock.cpp | 2 ++ .../qthreadstorage/tst_qthreadstorage.cpp | 2 +- .../tst_qcommandlineparser.cpp | 4 +++ .../corelib/tools/qdatetime/tst_qdatetime.cpp | 5 +++- .../corelib/tools/qlocale/tst_qlocale.cpp | 6 ++--- tests/auto/gui/image/qpixmap/qpixmap.pro | 2 +- tests/auto/gui/image/qpixmap/tst_qpixmap.cpp | 6 ++--- .../kernel/qhostaddress/tst_qhostaddress.cpp | 3 +++ .../kernel/qhostinfo/tst_qhostinfo.cpp | 2 +- .../sql/kernel/qsqldatabase/tst_databases.h | 7 +++-- .../testlib/selftests/crashes/tst_crashes.cpp | 2 +- .../qfilesystemmodel/tst_qfilesystemmodel.cpp | 7 +++++ .../qgraphicsitem/qgraphicsitem.pro | 2 +- .../qgraphicsitem/tst_qgraphicsitem.cpp | 2 +- .../qgraphicsscene/qgraphicsscene.pro | 2 +- .../qgraphicsscene/tst_qgraphicsscene.cpp | 2 +- .../itemviews/qitemdelegate/qitemdelegate.pro | 2 +- .../qitemdelegate/tst_qitemdelegate.cpp | 2 +- .../widgets/itemviews/qlistview/qlistview.pro | 2 +- .../itemviews/qlistview/tst_qlistview.cpp | 4 +-- .../kernel/qapplication/tst_qapplication.cpp | 2 +- tests/auto/widgets/kernel/qwidget/qwidget.pro | 2 +- .../widgets/kernel/qwidget/tst_qwidget.cpp | 24 +++++++++-------- .../qdatetimeedit/tst_qdatetimeedit.cpp | 2 +- .../widgets/widgets/qtabwidget/qtabwidget.pro | 2 +- .../widgets/qtabwidget/tst_qtabwidget.cpp | 2 +- .../shared/baselineprotocol.cpp | 6 +++++ .../io/qdir/10000/bench_qdir_10000.cpp | 5 ++++ .../corelib/io/qdiriterator/main.cpp | 5 ++++ .../io/qdiriterator/qfilesystemiterator.cpp | 5 ++++ tests/benchmarks/corelib/io/qfile/main.cpp | 26 +++++++++++++++++++ .../benchmarks/corelib/io/qfileinfo/main.cpp | 4 +-- .../corelib/thread/qmutex/tst_qmutex.cpp | 4 +++ tests/shared/filesystem.h | 2 +- 46 files changed, 165 insertions(+), 68 deletions(-) diff --git a/tests/auto/corelib/io/io.pro b/tests/auto/corelib/io/io.pro index 41d7e7e08b..d70737a53f 100644 --- a/tests/auto/corelib/io/io.pro +++ b/tests/auto/corelib/io/io.pro @@ -52,3 +52,9 @@ SUBDIRS=\ win32:!contains(QT_CONFIG, private_tests): SUBDIRS -= \ qfilesystementry + +winrt: SUBDIRS -= \ + qprocess \ + qprocess-noapplication \ + qprocessenvironment \ + qwinoverlappedionotifier diff --git a/tests/auto/corelib/io/qfile/test/test.pro b/tests/auto/corelib/io/qfile/test/test.pro index bc6922b4e9..e282bd091c 100644 --- a/tests/auto/corelib/io/qfile/test/test.pro +++ b/tests/auto/corelib/io/qfile/test/test.pro @@ -13,5 +13,5 @@ TESTDATA += ../dosfile.txt ../noendofline.txt ../testfile.txt \ ../Makefile ../forCopying.txt ../forRenaming.txt \ ../resources/file1.ext1 -win32: LIBS+=-lole32 -luuid +win32:!winrt: LIBS+=-lole32 -luuid DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp index 2b029203e9..78cb27ee30 100644 --- a/tests/auto/corelib/io/qfile/tst_qfile.cpp +++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp @@ -527,7 +527,7 @@ void tst_QFile::open_data() << false << QFile::OpenError; QTest::newRow("noreadfile") << QString::fromLatin1(noReadFile) << int(QIODevice::ReadOnly) << false << QFile::OpenError; -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) //opening devices requires administrative privileges (and elevation). HANDLE hTest = CreateFile(_T("\\\\.\\PhysicalDrive0"), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hTest != INVALID_HANDLE_VALUE) { @@ -1057,7 +1057,7 @@ void tst_QFile::ungetChar() QCOMPARE(buf[2], '4'); } -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) QString driveLetters() { wchar_t volumeName[MAX_PATH]; @@ -1094,7 +1094,7 @@ void tst_QFile::invalidFile_data() #if !defined(Q_OS_WIN) QTest::newRow( "x11" ) << QString( "qwe//" ); #else -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) QTest::newRow( "colon2" ) << invalidDriveLetter() + QString::fromLatin1(":ail:invalid"); #endif QTest::newRow( "colon3" ) << QString( ":failinvalid" ); @@ -1338,10 +1338,12 @@ void tst_QFile::copyFallback() #ifdef Q_OS_WIN #include +#ifndef Q_OS_WINPHONE #include #endif +#endif -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) static QString getWorkingDirectoryForLink(const QString &linkFileName) { bool neededCoInit = false; @@ -1400,7 +1402,7 @@ void tst_QFile::link() QCOMPARE(QFile::symLinkTarget("myLink.lnk"), referenceTarget); -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) QString wd = getWorkingDirectoryForLink(info2.absoluteFilePath()); QCOMPARE(QDir::fromNativeSeparators(wd), QDir::cleanPath(info1.absolutePath())); #endif @@ -2690,8 +2692,12 @@ void tst_QFile::nativeHandleLeaks() } #ifdef Q_OS_WIN +# ifndef Q_OS_WINRT handle1 = ::CreateFileA("qt_file.tmp", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); +# else + handle1 = ::CreateFile2(L"qt_file.tmp", GENERIC_READ, 0, OPEN_ALWAYS, NULL); +# endif QVERIFY( INVALID_HANDLE_VALUE != handle1 ); QVERIFY( ::CloseHandle(handle1) ); #endif @@ -2705,8 +2711,12 @@ void tst_QFile::nativeHandleLeaks() } #ifdef Q_OS_WIN +# ifndef Q_OS_WINRT handle2 = ::CreateFileA("qt_file.tmp", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); +# else + handle2 = ::CreateFile2(L"qt_file.tmp", GENERIC_READ, 0, OPEN_ALWAYS, NULL); +# endif QVERIFY( INVALID_HANDLE_VALUE != handle2 ); QVERIFY( ::CloseHandle(handle2) ); #endif diff --git a/tests/auto/corelib/io/qfileinfo/qfileinfo.pro b/tests/auto/corelib/io/qfileinfo/qfileinfo.pro index c4b37a8847..64d289bc3c 100644 --- a/tests/auto/corelib/io/qfileinfo/qfileinfo.pro +++ b/tests/auto/corelib/io/qfileinfo/qfileinfo.pro @@ -6,5 +6,5 @@ RESOURCES += qfileinfo.qrc TESTDATA += qfileinfo.qrc qfileinfo.pro tst_qfileinfo.cpp resources/file1 resources/file1.ext1 resources/file1.ext1.ext2 -win32*:!wince*:LIBS += -ladvapi32 -lnetapi32 +win32*:!wince*:!winrt:LIBS += -ladvapi32 -lnetapi32 DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp index d2171cc64a..74667a951f 100644 --- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp +++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp @@ -62,7 +62,7 @@ #ifdef Q_OS_WIN #include #include -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) #include #endif #endif @@ -176,7 +176,7 @@ private slots: void refresh(); -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) void ntfsJunctionPointsAndSymlinks_data(); void ntfsJunctionPointsAndSymlinks(); void brokenShortcut(); @@ -193,7 +193,7 @@ private slots: void detachingOperations(); -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) void owner(); #endif void group(); @@ -1058,7 +1058,7 @@ void tst_QFileInfo::fileTimes() //In Vista the last-access timestamp is not updated when the file is accessed/touched (by default). //To enable this the HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisableLastAccessUpdate //is set to 0, in the test machine. -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) HKEY key; if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\FileSystem", 0, KEY_READ, &key)) { @@ -1085,8 +1085,8 @@ void tst_QFileInfo::fileTimes() void tst_QFileInfo::fileTimes_oldFile() { - // This is not supported on WinCE -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) + // This is not supported on WinCE or WinRT +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) // All files are opened in share mode (both read and write). DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; @@ -1329,7 +1329,7 @@ void tst_QFileInfo::refresh() QCOMPARE(info2.size(), info.size()); } -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data() { QTest::addColumn("path"); @@ -1680,7 +1680,7 @@ void tst_QFileInfo::detachingOperations() QVERIFY(!info1.caching()); } -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) #if defined (Q_OS_WIN) BOOL IsUserAdmin() { diff --git a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp index 20ef7b5a76..b5115972d7 100644 --- a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp +++ b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp @@ -55,6 +55,7 @@ class tst_QFileSystemWatcher : public QObject public: tst_QFileSystemWatcher(); +#ifndef QT_NO_FILESYSTEMWATCHER private slots: void basicTest_data(); void basicTest(); @@ -83,16 +84,20 @@ private slots: private: QString m_tempDirPattern; +#endif // QT_NO_FILESYSTEMWATCHER }; tst_QFileSystemWatcher::tst_QFileSystemWatcher() { +#ifndef QT_NO_FILESYSTEMWATCHER m_tempDirPattern = QDir::tempPath(); if (!m_tempDirPattern.endsWith(QLatin1Char('/'))) m_tempDirPattern += QLatin1Char('/'); m_tempDirPattern += QStringLiteral("tst_qfilesystemwatcherXXXXXX"); +#endif // QT_NO_FILESYSTEMWATCHER } +#ifndef QT_NO_FILESYSTEMWATCHER void tst_QFileSystemWatcher::basicTest_data() { QTest::addColumn("backend"); @@ -676,6 +681,7 @@ void tst_QFileSystemWatcher::signalsEmittedAfterFileMoved() QTRY_COMPARE(changedSpy.count(), 10); } +#endif // QT_NO_FILESYSTEMWATCHER QTEST_MAIN(tst_QFileSystemWatcher) #include "tst_qfilesystemwatcher.moc" diff --git a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp index 290d4ac240..186e7b1a3f 100644 --- a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp +++ b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp @@ -118,7 +118,7 @@ private slots: #if !defined(Q_OS_WIN) && !defined(QT_QSETTINGS_ALWAYS_CASE_SENSITIVE_AND_FORGET_ORIGINAL_KEY_ORDER) void dontReorderIniKeysNeedlessly(); #endif -#if defined(Q_OS_WIN) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) void consistentRegistryStorage(); #endif @@ -273,7 +273,7 @@ void tst_QSettings::init() QSettings::setSystemIniPath(settingsPath("__system__")); QSettings::setUserIniPath(settingsPath("__user__")); -#if defined(Q_OS_WIN) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) QSettings("HKEY_CURRENT_USER\\Software\\software.org", QSettings::NativeFormat).clear(); QSettings("HKEY_LOCAL_MACHINE\\Software\\software.org", QSettings::NativeFormat).clear(); QSettings("HKEY_CURRENT_USER\\Software\\other.software.org", QSettings::NativeFormat).clear(); @@ -1501,7 +1501,7 @@ void tst_QSettings::sync() // Now "some other app" will change other.software.org.ini QString userConfDir = settingsPath("__user__") + QDir::separator(); -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) unlink((userConfDir + "other.software.org.ini").toLatin1()); rename((userConfDir + "software.org.ini").toLatin1(), (userConfDir + "other.software.org.ini").toLatin1()); @@ -3189,7 +3189,7 @@ void tst_QSettings::recursionBug() } } -#if defined(Q_OS_WIN) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) static DWORD readKeyType(HKEY handle, const QString &rSubKey) { diff --git a/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp b/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp index 713d0c5c17..a6cc083d9c 100644 --- a/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp +++ b/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp @@ -257,7 +257,7 @@ void tst_QTemporaryDir::nonWritableCurrentDir() void tst_QTemporaryDir::openOnRootDrives() { -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) unsigned int lastErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS); #endif // If it's possible to create a file in the root directory, it @@ -271,7 +271,7 @@ void tst_QTemporaryDir::openOnRootDrives() QVERIFY(dir.isValid()); } } -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) SetErrorMode(lastErrorMode); #endif } diff --git a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp index 6eb6f83d2a..5ad798ae1f 100644 --- a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp +++ b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp @@ -371,7 +371,7 @@ void tst_QTemporaryFile::resize() void tst_QTemporaryFile::openOnRootDrives() { -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) unsigned int lastErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS); #endif // If it's possible to create a file in the root directory, it @@ -385,7 +385,7 @@ void tst_QTemporaryFile::openOnRootDrives() QVERIFY(file.open()); } } -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) SetErrorMode(lastErrorMode); #endif } diff --git a/tests/auto/corelib/kernel/kernel.pro b/tests/auto/corelib/kernel/kernel.pro index a283f5343d..2f3c02332d 100644 --- a/tests/auto/corelib/kernel/kernel.pro +++ b/tests/auto/corelib/kernel/kernel.pro @@ -31,6 +31,6 @@ SUBDIRS=\ qsharedmemory # This test is only applicable on Windows -!win32*:SUBDIRS -= qwineventnotifier +!win32*|winrt: SUBDIRS -= qwineventnotifier android|qnx: SUBDIRS -= qsharedmemory qsystemsemaphore diff --git a/tests/auto/corelib/kernel/qeventloop/qeventloop.pro b/tests/auto/corelib/kernel/qeventloop/qeventloop.pro index e5bcc31e6a..5593aa2430 100644 --- a/tests/auto/corelib/kernel/qeventloop/qeventloop.pro +++ b/tests/auto/corelib/kernel/qeventloop/qeventloop.pro @@ -4,7 +4,7 @@ TARGET = tst_qeventloop QT = core network testlib core-private SOURCES = $$PWD/tst_qeventloop.cpp -win32:!wince*:LIBS += -luser32 +win32:!wince*:!winrt:LIBS += -luser32 DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 contains(QT_CONFIG, glib): DEFINES += HAVE_GLIB diff --git a/tests/auto/corelib/kernel/qmetatype/qmetatype.pro b/tests/auto/corelib/kernel/qmetatype/qmetatype.pro index 23a8e6d23a..d19ec23760 100644 --- a/tests/auto/corelib/kernel/qmetatype/qmetatype.pro +++ b/tests/auto/corelib/kernel/qmetatype/qmetatype.pro @@ -6,11 +6,11 @@ SOURCES = tst_qmetatype.cpp TESTDATA=./typeFlags.bin DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 -win32-msvc*|wince { +win32-msvc*|wince|winrt { # Prevents "fatal error C1128: number of sections exceeded object file format limit". QMAKE_CXXFLAGS += /bigobj # Reduce compile time - win32-msvc2012|wince { + win32-msvc2012|wince|winrt { QMAKE_CXXFLAGS_RELEASE -= -O2 QMAKE_CFLAGS_RELEASE -= -O2 } diff --git a/tests/auto/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp b/tests/auto/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp index 7d041e69cb..0d51f69559 100644 --- a/tests/auto/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp +++ b/tests/auto/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp @@ -52,6 +52,8 @@ #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) #include #define sleep(X) Sleep(X) +#elif defined(Q_OS_WINRT) +#define sleep(X) WaitForSingleObjectEx(GetCurrentThread(), X, FALSE); #endif //on solaris, threads that loop on the release bool variable diff --git a/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp b/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp index 2072034f5f..c96de29b98 100644 --- a/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp +++ b/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp @@ -232,7 +232,7 @@ void tst_QThreadStorage::adoptedThreads() const int state = pthread_create(&thread, 0, testAdoptedThreadStorageUnix, &pointers); QCOMPARE(state, 0); pthread_join(thread, 0); -#elif defined Q_OS_WIN +#elif defined Q_OS_WIN && !defined(Q_OS_WINRT) HANDLE thread; #if defined(Q_OS_WINCE) thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)testAdoptedThreadStorageWin, &pointers, 0, NULL); diff --git a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp index d8965dee5d..1ee6cacd97 100644 --- a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp +++ b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp @@ -546,6 +546,9 @@ void tst_QCommandLineParser::testHelpOption() void tst_QCommandLineParser::testQuoteEscaping() { +#ifdef QT_NO_PROCESS + QSKIP("This test requires QProcess support"); +#else QCoreApplication app(empty_argc, empty_argv); QProcess process; process.start("testhelper/qcommandlineparser_test_helper", QStringList() << @@ -561,6 +564,7 @@ void tst_QCommandLineParser::testQuoteEscaping() QVERIFY2(output.contains("KEY2=\\\"VALUE2\\\""), qPrintable(output)); QVERIFY2(output.contains("QTBUG-15379=C:\\path\\'file.ext"), qPrintable(output)); QVERIFY2(output.contains("QTBUG-30628=C:\\temp\\'file'.ext"), qPrintable(output)); +#endif // !QT_NO_PROCESS } QTEST_APPLESS_MAIN(tst_QCommandLineParser) diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp index a282fcabd3..039f5cbc44 100644 --- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp @@ -49,6 +49,9 @@ #ifdef Q_OS_WIN # include +# if defined(Q_OS_WINRT) +# define tzset() +# endif #endif class tst_QDateTime : public QObject @@ -173,7 +176,7 @@ void tst_QDateTime::init() { #if defined(Q_OS_WINCE) SetUserDefaultLCID(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)); -#elif defined(Q_OS_WIN) +#elif defined(Q_OS_WIN32) SetThreadLocale(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)); #endif } diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp index d6dea05755..f11e632b2e 100644 --- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp +++ b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp @@ -133,7 +133,7 @@ public: private slots: void initTestCase(); void cleanupTestCase(); -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) void windowsDefaultLocale(); #endif #ifdef Q_OS_MAC @@ -1472,7 +1472,7 @@ void tst_QLocale::macDefaultLocale() } #endif // Q_OS_MAC -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) #include static QString getWinLocaleInfo(LCTYPE type) @@ -1526,7 +1526,7 @@ public: #endif // Q_OS_WIN -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) void tst_QLocale::windowsDefaultLocale() { RestoreLocaleHelper systemLocale; diff --git a/tests/auto/gui/image/qpixmap/qpixmap.pro b/tests/auto/gui/image/qpixmap/qpixmap.pro index bdd0c15788..33c301a500 100644 --- a/tests/auto/gui/image/qpixmap/qpixmap.pro +++ b/tests/auto/gui/image/qpixmap/qpixmap.pro @@ -5,7 +5,7 @@ QT += core-private gui-private testlib qtHaveModule(widgets): QT += widgets widgets-private SOURCES += tst_qpixmap.cpp -!wince* { +!wince*:!winrt { win32:LIBS += -lgdi32 -luser32 } diff --git a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp index cb5d836291..79dc3f311a 100644 --- a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp +++ b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp @@ -116,7 +116,7 @@ private slots: void convertFromImageDetach(); void convertFromImageCacheKey(); -#if defined(Q_OS_WIN) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) void toWinHBITMAP_data(); void toWinHBITMAP(); void fromWinHBITMAP_data(); @@ -805,7 +805,7 @@ void tst_QPixmap::convertFromImageCacheKey() QCOMPARE(copy.cacheKey(), pix.cacheKey()); } -#if defined(Q_OS_WIN) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) QT_BEGIN_NAMESPACE Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap); @@ -1024,7 +1024,7 @@ void tst_QPixmap::fromWinHICON() #endif // Q_OS_WINCE } -#endif // Q_OS_WIN +#endif // Q_OS_WIN && !Q_OS_WINRT void tst_QPixmap::onlyNullPixmapsOutsideGuiThread() { diff --git a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp index dd9202c748..acb921b34a 100644 --- a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp +++ b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp @@ -50,6 +50,9 @@ #include #ifdef Q_OS_WIN # include +# if defined(Q_OS_WINRT) +# include +# endif #endif class tst_QHostAddress : public QObject diff --git a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp index e81c7f71db..e3156ceb3f 100644 --- a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp +++ b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp @@ -67,7 +67,7 @@ #include #include -#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) #include #else #include diff --git a/tests/auto/sql/kernel/qsqldatabase/tst_databases.h b/tests/auto/sql/kernel/qsqldatabase/tst_databases.h index f87493205f..69ecbcb019 100644 --- a/tests/auto/sql/kernel/qsqldatabase/tst_databases.h +++ b/tests/auto/sql/kernel/qsqldatabase/tst_databases.h @@ -55,11 +55,14 @@ #include #include -#if defined (Q_OS_WIN) || defined (Q_OS_WIN32) +#if defined(Q_OS_WIN) # include -# if defined (Q_OS_WINCE) +# if defined(Q_OS_WINCE) || defined(Q_OS_WINRT) # include # endif +# if defined(Q_OS_WINRT) && !defined(Q_OS_WINPHONE) +static inline int gethostname(char *name, int len) { qstrcpy(name, "localhost"); return 9; } +# endif #else #include #endif diff --git a/tests/auto/testlib/selftests/crashes/tst_crashes.cpp b/tests/auto/testlib/selftests/crashes/tst_crashes.cpp index 067c2a9f4f..3b73d87876 100644 --- a/tests/auto/testlib/selftests/crashes/tst_crashes.cpp +++ b/tests/auto/testlib/selftests/crashes/tst_crashes.cpp @@ -57,7 +57,7 @@ private slots: void tst_Crashes::crash() { -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) //we avoid the error dialogbox to appear on windows SetErrorMode( SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); #endif diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp index 0b9fb5c168..e24a1dfc96 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -416,7 +416,14 @@ bool tst_QFileSystemModel::createFiles(const QString &test_path, const QStringLi wchar_t nativeHiddenFile[MAX_PATH]; memset(nativeHiddenFile, 0, sizeof(nativeHiddenFile)); hiddenFile.toWCharArray(nativeHiddenFile); +#ifndef Q_OS_WINRT DWORD currentAttributes = ::GetFileAttributes(nativeHiddenFile); +#else // !Q_OS_WINRT + WIN32_FILE_ATTRIBUTE_DATA attributeData; + if (!::GetFileAttributesEx(nativeHiddenFile, GetFileExInfoStandard, &attributeData)) + attributeData.dwFileAttributes = 0xFFFFFFFF; + DWORD currentAttributes = attributeData.dwFileAttributes; +#endif // Q_OS_WINRT if (currentAttributes == 0xFFFFFFFF) { qErrnoWarning("failed to get file attributes: %s", qPrintable(hiddenFile)); return false; diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro b/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro index 0c3b46c5d5..527f62b22d 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro +++ b/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro @@ -5,5 +5,5 @@ QT += core-private gui-private SOURCES += tst_qgraphicsitem.cpp DEFINES += QT_NO_CAST_TO_ASCII -win32:!wince*: LIBS += -luser32 +win32:!wince*:!winrt: LIBS += -luser32 DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp index 2c03850181..70cfbc8856 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp @@ -71,7 +71,7 @@ Q_DECLARE_METATYPE(QPainterPath) #include "../../../qtest-config.h" -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) #include #define Q_CHECK_PAINTEVENTS \ if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \ diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro b/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro index 8d00931ef1..a6022e0d7d 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro +++ b/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro @@ -4,7 +4,7 @@ QT += widgets widgets-private testlib QT += core-private gui-private SOURCES += tst_qgraphicsscene.cpp RESOURCES += images.qrc -win32:!wince*: LIBS += -luser32 +win32:!wince*:!winrt: LIBS += -luser32 !wince*:DEFINES += SRCDIR=\\\"$$PWD\\\" DEFINES += QT_NO_CAST_TO_ASCII diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp index fe1df6c8f0..b3fba29f81 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp @@ -54,7 +54,7 @@ #include "../../../shared/platforminputcontext.h" #include -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) #include #define Q_CHECK_PAINTEVENTS \ if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \ diff --git a/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro b/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro index cb935fd2fd..313cadd6a1 100644 --- a/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro +++ b/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro @@ -3,4 +3,4 @@ TARGET = tst_qitemdelegate QT += widgets testlib SOURCES += tst_qitemdelegate.cpp -win32:!wince*: LIBS += -luser32 +win32:!wince*:!winrt: LIBS += -luser32 diff --git a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp index 439725b257..addb226101 100644 --- a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp +++ b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp @@ -66,7 +66,7 @@ Q_DECLARE_METATYPE(QAbstractItemDelegate::EndEditHint) -#if defined (Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined (Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) #include #define Q_CHECK_PAINTEVENTS \ if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \ diff --git a/tests/auto/widgets/itemviews/qlistview/qlistview.pro b/tests/auto/widgets/itemviews/qlistview/qlistview.pro index 413304bdcf..1ea8beb8df 100644 --- a/tests/auto/widgets/itemviews/qlistview/qlistview.pro +++ b/tests/auto/widgets/itemviews/qlistview/qlistview.pro @@ -2,4 +2,4 @@ CONFIG += testcase TARGET = tst_qlistview QT += widgets gui-private widgets-private core-private testlib SOURCES += tst_qlistview.cpp -win32:!wince*: LIBS += -luser32 +win32:!wince*:!winrt: LIBS += -luser32 diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp index 268276bd4a..9f5484983d 100644 --- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp +++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp @@ -1484,7 +1484,7 @@ void tst_QListView::wordWrap() QTRY_COMPARE(lv.verticalScrollBar()->isVisible(), true); } -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) class SetCurrentIndexAfterAppendRowCrashDialog : public QDialog { Q_OBJECT @@ -1525,7 +1525,7 @@ private: }; #endif -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && WINVER >= 0x0500 +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) && WINVER >= 0x0500 // This test only makes sense on windows 2000 and higher. void tst_QListView::setCurrentIndexAfterAppendRowCrash() { diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp index 8d75298673..fee8b6aee5 100644 --- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp @@ -1891,7 +1891,7 @@ void tst_QApplication::windowsCommandLine_data() void tst_QApplication::windowsCommandLine() { -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) QFETCH(QString, args); QFETCH(QString, expected); diff --git a/tests/auto/widgets/kernel/qwidget/qwidget.pro b/tests/auto/widgets/kernel/qwidget/qwidget.pro index a4fcde8a34..3eedfa1d3a 100644 --- a/tests/auto/widgets/kernel/qwidget/qwidget.pro +++ b/tests/auto/widgets/kernel/qwidget/qwidget.pro @@ -20,7 +20,7 @@ x11 { LIBS += $$QMAKE_LIBS_X11 } -!wince*:win32: LIBS += -luser32 -lgdi32 +!wince*:win32:!winrt: LIBS += -luser32 -lgdi32 mac:CONFIG+=insignificant_test # QTBUG-25300, QTBUG-23695 linux-*:system(". /etc/lsb-release && [ $DISTRIB_CODENAME = oneiric ]"):DEFINES+=UBUNTU_ONEIRIC # QTBUG-30566 \ No newline at end of file diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 227f61b0a3..2da8df6116 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -116,11 +116,13 @@ static bool qt_wince_is_platform(const QString &platformString) { } static inline bool qt_wince_is_smartphone() { return qt_wince_is_platform(QString::fromLatin1("Smartphone")); } # endif // Q_OS_WINCE_WM -# else // Q_OS_WINCE +# elif !defined(Q_OS_WINRT) // Q_OS_WINCE # define Q_CHECK_PAINTEVENTS \ if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \ QSKIP("desktop is not visible, this test would fail"); -# endif // !Q_OS_WINCE +# else // !Q_OS_WINCE && !Q_OS_WINRT +# define Q_CHECK_PAINTEVENTS +# endif // Q_OS_WINRT #else // Q_OS_WIN # define Q_CHECK_PAINTEVENTS #endif // else Q_OS_WIN @@ -285,7 +287,7 @@ private slots: void subtractOpaqueSiblings(); #endif -#if defined (Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined (Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) void setGeometry_win(); #endif @@ -355,7 +357,7 @@ private slots: void quitOnCloseAttribute(); void moveRect(); -#if defined (Q_OS_WIN) +#if defined (Q_OS_WIN) && !defined(Q_OS_WINRT) void gdiPainting(); void paintOnScreenPossible(); #endif @@ -572,7 +574,7 @@ void tst_QWidget::getSetCheck() QCOMPARE(true, obj1.autoFillBackground()); var1.reset(); -#if defined (Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined (Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) obj1.setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint); const HWND handle = reinterpret_cast(obj1.winId()); // explicitly create window handle QVERIFY(GetWindowLong(handle, GWL_STYLE) & WS_POPUP); @@ -1257,7 +1259,7 @@ void tst_QWidget::visible_setWindowOpacity() testWidget->hide(); QVERIFY( !testWidget->isVisible() ); testWidget->setWindowOpacity(0.5); -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) QVERIFY(!::IsWindowVisible(winHandleOf(testWidget))); #endif testWidget->setWindowOpacity(1.0); @@ -3597,7 +3599,7 @@ void tst_QWidget::optimizedResize_topLevel() topLevel.partial = false; topLevel.paintedRegion = QRegion(); -#ifndef Q_OS_WIN +#if !defined(Q_OS_WIN32) && !defined(Q_OS_WINCE) topLevel.resize(topLevel.size() + QSize(10, 10)); #else // Static contents does not work when programmatically resizing @@ -4529,7 +4531,7 @@ void tst_QWidget::setWindowGeometry() } } -#if defined (Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined (Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) void tst_QWidget::setGeometry_win() { QWidget widget; @@ -4548,7 +4550,7 @@ void tst_QWidget::setGeometry_win() QEXPECT_FAIL("", "QTBUG-26424", Continue); QVERIFY(rt.top <= 0); } -#endif // defined (Q_OS_WIN) && !defined(Q_OS_WINCE) +#endif // defined (Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) // Since X11 WindowManager operation are all async, and we have no way to know if the window // manager has finished playing with the window geometry, this test can't be reliable on X11. @@ -8047,7 +8049,7 @@ void tst_QWidget::moveRect() child.move(10, 10); // Don't crash. } -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) class GDIWidget : public QDialog { Q_OBJECT @@ -8114,7 +8116,7 @@ void tst_QWidget::paintOnScreenPossible() w2.setAttribute(Qt::WA_PaintOnScreen); QVERIFY(w2.testAttribute(Qt::WA_PaintOnScreen)); } -#endif // Q_OS_WIN +#endif // Q_OS_WIN && !Q_OS_WINRT void tst_QWidget::reparentStaticWidget() { diff --git a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp index bfffa357a8..ded3e55283 100644 --- a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp +++ b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp @@ -346,7 +346,7 @@ void tst_QDateTimeEdit::cleanupTestCase() void tst_QDateTimeEdit::init() { QLocale::setDefault(QLocale(QLocale::C)); -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) SetThreadLocale(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)); #endif testWidget->setDisplayFormat("dd/MM/yyyy"); // Nice default to have diff --git a/tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro b/tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro index 72956a6867..c367959cbc 100644 --- a/tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro +++ b/tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro @@ -8,4 +8,4 @@ INCLUDEPATH += ../ HEADERS += SOURCES += tst_qtabwidget.cpp -win32:!wince*:LIBS += -luser32 +win32:!wince*:!winrt:LIBS += -luser32 diff --git a/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp b/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp index fa518e6afd..e55438f3d3 100644 --- a/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp +++ b/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp @@ -48,7 +48,7 @@ #include #include -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) # include #define Q_CHECK_PAINTEVENTS \ if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \ diff --git a/tests/baselineserver/shared/baselineprotocol.cpp b/tests/baselineserver/shared/baselineprotocol.cpp index cbe3ec8798..f6190f20c4 100644 --- a/tests/baselineserver/shared/baselineprotocol.cpp +++ b/tests/baselineserver/shared/baselineprotocol.cpp @@ -76,7 +76,11 @@ const QString PI_PulseTestrBranch(QLS("PulseTestrBranch")); void BaselineProtocol::sysSleep(int ms) { #if defined(Q_OS_WIN) +# ifndef Q_OS_WINRT Sleep(DWORD(ms)); +# else + WaitForSingleObjectEx(GetCurrentThread(), ms, false); +# endif #else struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; nanosleep(&ts, NULL); @@ -116,6 +120,7 @@ PlatformInfo PlatformInfo::localHostInfo() pi.insert(PI_OSName, QLS("Other")); #endif +#ifndef QT_NO_PROCESS QProcess git; QString cmd; QStringList args; @@ -151,6 +156,7 @@ PlatformInfo PlatformInfo::localHostInfo() pi.insert(PI_PulseGitBranch, QString::fromLatin1(gb)); } } +#endif // !QT_NO_PROCESS return pi; } diff --git a/tests/benchmarks/corelib/io/qdir/10000/bench_qdir_10000.cpp b/tests/benchmarks/corelib/io/qdir/10000/bench_qdir_10000.cpp index 49672a90bf..b2380b0e58 100644 --- a/tests/benchmarks/corelib/io/qdir/10000/bench_qdir_10000.cpp +++ b/tests/benchmarks/corelib/io/qdir/10000/bench_qdir_10000.cpp @@ -176,7 +176,12 @@ private slots: wcscat(appendedPath, L"\\*"); WIN32_FIND_DATA fd; +#ifndef Q_OS_WINRT HANDLE hSearch = FindFirstFileW(appendedPath, &fd); +#else + HANDLE hSearch = FindFirstFileEx(appendedPath, FindExInfoStandard, &fd, + FindExSearchNameMatch, NULL, FIND_FIRST_EX_LARGE_FETCH); +#endif QVERIFY(hSearch != INVALID_HANDLE_VALUE); QBENCHMARK { diff --git a/tests/benchmarks/corelib/io/qdiriterator/main.cpp b/tests/benchmarks/corelib/io/qdiriterator/main.cpp index 5188658bdb..691e822379 100644 --- a/tests/benchmarks/corelib/io/qdiriterator/main.cpp +++ b/tests/benchmarks/corelib/io/qdiriterator/main.cpp @@ -106,7 +106,12 @@ static int posix_helper(const wchar_t *dirpath) wchar_t appendedPath[MAX_PATH]; wcscpy(appendedPath, dirpath); wcscat(appendedPath, L"\\*"); +#ifndef Q_OS_WINRT hSearch = FindFirstFile(appendedPath, &fd); +#else + hSearch = FindFirstFileEx(appendedPath, FindExInfoStandard, &fd, + FindExSearchNameMatch, NULL, FIND_FIRST_EX_LARGE_FETCH); +#endif appendedPath[origDirPathLength] = 0; if (hSearch == INVALID_HANDLE_VALUE) { diff --git a/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.cpp b/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.cpp index bb4a921fc7..82bca1541d 100644 --- a/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.cpp +++ b/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.cpp @@ -230,7 +230,12 @@ void QFileSystemIteratorPrivate::pushSubDirectory(const QByteArray &path) wchar_t szSearchPath[MAX_PATH]; QString::fromLatin1(path).toWCharArray(szSearchPath); wcscat(szSearchPath, L"\\*"); +#ifndef Q_OS_WINRT HANDLE dir = FindFirstFile(szSearchPath, &m_fileSearchResult); +#else + HANDLE dir = FindFirstFileEx(szSearchPath, FindExInfoStandard, &m_fileSearchResult, + FindExSearchLimitToDirectories, NULL, FIND_FIRST_EX_LARGE_FETCH); +#endif m_bFirstSearchResult = true; #else DIR *dir = ::opendir(path.constData()); diff --git a/tests/benchmarks/corelib/io/qfile/main.cpp b/tests/benchmarks/corelib/io/qfile/main.cpp index 0beffebfb7..e0ae29fbee 100644 --- a/tests/benchmarks/corelib/io/qfile/main.cpp +++ b/tests/benchmarks/corelib/io/qfile/main.cpp @@ -310,7 +310,11 @@ void tst_qfile::readBigFile() // ensure we don't account string conversion wchar_t* cfilename = (wchar_t*)filename.utf16(); +#ifndef Q_OS_WINRT hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); +#else + hndl = CreateFile2(cfilename, GENERIC_READ, 0, OPEN_EXISTING, 0); +#endif Q_ASSERT(hndl); wchar_t* nativeBuffer = new wchar_t[BUFSIZE]; DWORD numberOfBytesRead; @@ -319,7 +323,12 @@ void tst_qfile::readBigFile() do { ReadFile(hndl, nativeBuffer, blockSize, &numberOfBytesRead, NULL); } while(numberOfBytesRead != 0); +#ifndef Q_OS_WINRT SetFilePointer(hndl, 0, NULL, FILE_BEGIN); +#else + LARGE_INTEGER offset = { 0 }; + SetFilePointerEx(hndl, offset, NULL, FILE_BEGIN); +#endif } delete[] nativeBuffer; CloseHandle(hndl); @@ -400,11 +409,20 @@ void tst_qfile::seek() // ensure we don't account string conversion wchar_t* cfilename = (wchar_t*)filename.utf16(); +#ifndef Q_OS_WINRT hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); +#else + hndl = CreateFile2(cfilename, GENERIC_READ, 0, OPEN_EXISTING, 0); +#endif Q_ASSERT(hndl); QBENCHMARK { i=(i+1)%sp_size; +#ifndef Q_OS_WINRT SetFilePointer(hndl, seekpos[i], NULL, 0); +#else + LARGE_INTEGER offset = { seekpos[i] }; + SetFilePointerEx(hndl, offset, NULL, FILE_BEGIN); +#endif } CloseHandle(hndl); #else @@ -489,7 +507,11 @@ void tst_qfile::open() wchar_t* cfilename = (wchar_t*)filename.utf16(); QBENCHMARK { +#ifndef Q_OS_WINRT hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); +#else + hndl = CreateFile2(cfilename, GENERIC_READ, 0, OPEN_EXISTING, 0); +#endif Q_ASSERT(hndl); CloseHandle(hndl); } @@ -698,7 +720,11 @@ void tst_qfile::readSmallFiles() // ensure we don't account string conversion wchar_t* cfilename = (wchar_t*)filename.utf16(); +#ifndef Q_OS_WINRT hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); +#else + hndl = CreateFile2(cfilename, GENERIC_READ, 0, OPEN_EXISTING, 0); +#endif Q_ASSERT(hndl); wchar_t* nativeBuffer = new wchar_t[BUFSIZE]; DWORD numberOfBytesRead; diff --git a/tests/benchmarks/corelib/io/qfileinfo/main.cpp b/tests/benchmarks/corelib/io/qfileinfo/main.cpp index 594e5b7478..de1aaea177 100644 --- a/tests/benchmarks/corelib/io/qfileinfo/main.cpp +++ b/tests/benchmarks/corelib/io/qfileinfo/main.cpp @@ -54,7 +54,7 @@ class qfileinfo : public QObject private slots: void existsTemporary(); void existsStatic(); -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) void symLinkTargetPerformanceLNK(); void symLinkTargetPerformanceMounpoint(); #endif @@ -84,7 +84,7 @@ void qfileinfo::existsStatic() QBENCHMARK { QFileInfo::exists(appPath); } } -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) void qfileinfo::symLinkTargetPerformanceLNK() { QVERIFY(QFile::link("file","link.lnk")); diff --git a/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp b/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp index a7480e6afe..37fa571f8c 100644 --- a/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp +++ b/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp @@ -93,7 +93,11 @@ void NativeMutexUnlock(NativeMutexType *mutex) typedef CRITICAL_SECTION NativeMutexType; void NativeMutexInitialize(NativeMutexType *mutex) { +#ifndef Q_OS_WINRT InitializeCriticalSection(mutex); +#else + InitializeCriticalSectionEx(mutex, 0, 0); +#endif } void NativeMutexDestroy(NativeMutexType *mutex) { diff --git a/tests/shared/filesystem.h b/tests/shared/filesystem.h index 7aa72cc28e..a68130a324 100644 --- a/tests/shared/filesystem.h +++ b/tests/shared/filesystem.h @@ -92,7 +92,7 @@ public: return file.isNull() ? qint64(-1) : file->write(relativeFileName.toUtf8()); } -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) static void createNtfsJunction(QString target, QString linkName) { typedef struct { From ffb92a56916580d6948722dee13b0cf99b201e5b Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Mon, 27 May 2013 15:55:12 +0200 Subject: [PATCH 018/684] Winrt: tst_qthread: Added QEXPECT_FAIL where needed Change-Id: I88d98421978e0f5c55af8647f3f74c265b45bd37 Reviewed-by: Andrew Knight Reviewed-by: Maurice Kalinowski --- tests/auto/corelib/thread/qthread/tst_qthread.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/auto/corelib/thread/qthread/tst_qthread.cpp b/tests/auto/corelib/thread/qthread/tst_qthread.cpp index 4ebdd63b99..42424f23c4 100644 --- a/tests/auto/corelib/thread/qthread/tst_qthread.cpp +++ b/tests/auto/corelib/thread/qthread/tst_qthread.cpp @@ -869,6 +869,9 @@ void tst_QThread::adoptedThreadFinished() nativeThread.join(); QTestEventLoop::instance().enterLoop(5); +#if defined(Q_OS_WINRT) + QEXPECT_FAIL("", "QTBUG-31397: Known not to work on WinRT", Abort); +#endif QVERIFY(!QTestEventLoop::instance().timeout()); } @@ -884,6 +887,9 @@ void tst_QThread::adoptedThreadExecFinished() nativeThread.join(); QTestEventLoop::instance().enterLoop(5); +#if defined(Q_OS_WINRT) + QEXPECT_FAIL("", "QTBUG-31397: Known not to work on WinRT", Abort); +#endif QVERIFY(!QTestEventLoop::instance().timeout()); } @@ -920,6 +926,9 @@ void tst_QThread::adoptMultipleThreads() } QTestEventLoop::instance().enterLoop(5); +#if defined(Q_OS_WINRT) + QEXPECT_FAIL("", "QTBUG-31397: Known not to work on WinRT", Abort); +#endif QVERIFY(!QTestEventLoop::instance().timeout()); QCOMPARE(recorder.activationCount.load(), numThreads); } @@ -962,6 +971,9 @@ void tst_QThread::adoptMultipleThreadsOverlap() } QTestEventLoop::instance().enterLoop(5); +#if defined(Q_OS_WINRT) + QEXPECT_FAIL("", "QTBUG-31397: Known not to work on WinRT", Abort); +#endif QVERIFY(!QTestEventLoop::instance().timeout()); QCOMPARE(recorder.activationCount.load(), numThreads); } From 8cbc90ffb238146f2a9c3217bdf687c9535c5f9b Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Mon, 27 May 2013 15:54:06 +0200 Subject: [PATCH 019/684] Winrt: Skip qthread autotests, which are not supported (yet) Change-Id: Ib1047731667ba8a7b9db2f62924eb42a6b85b4fd Reviewed-by: Andrew Knight Reviewed-by: Maurice Kalinowski --- tests/auto/corelib/thread/qthread/tst_qthread.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/auto/corelib/thread/qthread/tst_qthread.cpp b/tests/auto/corelib/thread/qthread/tst_qthread.cpp index 42424f23c4..0e53139414 100644 --- a/tests/auto/corelib/thread/qthread/tst_qthread.cpp +++ b/tests/auto/corelib/thread/qthread/tst_qthread.cpp @@ -328,6 +328,9 @@ void tst_QThread::isRunning() void tst_QThread::setPriority() { +#if defined(Q_OS_WINRT) + QSKIP("Thread priority is not supported on WinRT"); +#endif Simple_Thread thread; // cannot change the priority, since the thread is not running @@ -478,6 +481,9 @@ void tst_QThread::start() void tst_QThread::terminate() { +#if defined(Q_OS_WINRT) + QSKIP("Terminate is not supported on WinRT"); +#endif Terminate_Thread thread; { QMutexLocker locker(&thread.mutex); @@ -541,6 +547,9 @@ void tst_QThread::finished() void tst_QThread::terminated() { +#if defined(Q_OS_WINRT) + QSKIP("Terminate is not supported on WinRT"); +#endif SignalRecorder recorder; Terminate_Thread thread; connect(&thread, SIGNAL(finished()), &recorder, SLOT(slot()), Qt::DirectConnection); @@ -792,6 +801,9 @@ void tst_QThread::adoptedThreadAffinity() void tst_QThread::adoptedThreadSetPriority() { +#if defined(Q_OS_WINRT) + QSKIP("Thread priority is not supported on WinRT"); +#endif NativeThreadWrapper nativeThread; nativeThread.setWaitForStop(); From 11a2226cfe336a0d3cbed5ff090dcc657911a8ef Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Tue, 1 Oct 2013 09:44:12 +0300 Subject: [PATCH 020/684] ANGLE: Support WinRT This enables EGL for WinRT's native types, and adjusts some codepaths to accommodate differences in between desktop Windows and WinRT. - WinRT native handles added to eglplatform.h - References to native handles in libEGL/libGLESv2 follow eglplatform.h - D3D 11.1 structures and methods used when necessary - TLS replaced with thread attribute - LocalAlloc/Free replaced with Heap API Change-Id: Ia90377e700d335a1c569c2145008dd4b0dfd84d3 Reviewed-by: Friedemann Kleint --- src/3rdparty/angle/include/EGL/eglplatform.h | 10 +- src/3rdparty/angle/src/compiler/osinclude.h | 35 +- .../angle/src/compiler/ossource_posix.cpp | 8 + .../angle/src/compiler/ossource_win.cpp | 8 + .../angle/src/compiler/ossource_winrt.cpp | 75 ++ src/3rdparty/angle/src/libEGL/Display.cpp | 8 +- src/3rdparty/angle/src/libEGL/Display.h | 4 +- src/3rdparty/angle/src/libEGL/Surface.cpp | 35 +- src/3rdparty/angle/src/libEGL/Surface.h | 7 +- src/3rdparty/angle/src/libEGL/libEGL.cpp | 4 +- src/3rdparty/angle/src/libEGL/main.cpp | 40 +- src/3rdparty/angle/src/libGLESv2/main.cpp | 39 +- .../angle/src/libGLESv2/precompiled.h | 15 + .../angle/src/libGLESv2/renderer/Renderer.cpp | 23 +- .../angle/src/libGLESv2/renderer/Renderer.h | 27 +- .../src/libGLESv2/renderer/Renderer11.cpp | 10 +- .../angle/src/libGLESv2/renderer/Renderer11.h | 2 +- .../angle/src/libGLESv2/renderer/SwapChain.h | 4 +- .../src/libGLESv2/renderer/SwapChain11.cpp | 29 +- .../src/libGLESv2/renderer/SwapChain11.h | 2 +- .../angle/src/libGLESv2/utilities.cpp | 53 + .../patches/0012-ANGLE-Support-WinRT.patch | 1131 +++++++++++++++++ src/angle/src/common/common.pri | 2 +- src/angle/src/compiler/translator_common.pro | 7 +- src/angle/src/config.pri | 5 +- 25 files changed, 1517 insertions(+), 66 deletions(-) create mode 100644 src/3rdparty/angle/src/compiler/ossource_winrt.cpp create mode 100644 src/angle/patches/0012-ANGLE-Support-WinRT.patch diff --git a/src/3rdparty/angle/include/EGL/eglplatform.h b/src/3rdparty/angle/include/EGL/eglplatform.h index 34283f2e90..eb15ae569d 100644 --- a/src/3rdparty/angle/include/EGL/eglplatform.h +++ b/src/3rdparty/angle/include/EGL/eglplatform.h @@ -67,7 +67,15 @@ * implementations. */ -#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */ +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) /* Windows Runtime */ + +struct IUnknown; + +typedef int EGLNativeDisplayType; +typedef void *EGLNativePixmapType; +typedef IUnknown *EGLNativeWindowType; + +#elif defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN 1 #endif diff --git a/src/3rdparty/angle/src/compiler/osinclude.h b/src/3rdparty/angle/src/compiler/osinclude.h index d8bb1a797c..60177d5fe5 100644 --- a/src/3rdparty/angle/src/compiler/osinclude.h +++ b/src/3rdparty/angle/src/compiler/osinclude.h @@ -13,27 +13,26 @@ // #if defined(_WIN32) || defined(_WIN64) +#define STRICT +#define VC_EXTRALEAN 1 +#include +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) +#define ANGLE_OS_WINRT +#else #define ANGLE_OS_WIN +#endif #elif defined(__APPLE__) || defined(__linux__) || \ defined(__FreeBSD__) || defined(__OpenBSD__) || \ defined(__sun) || defined(ANDROID) || \ defined(__GLIBC__) || defined(__GNU__) || \ defined(__QNX__) #define ANGLE_OS_POSIX -#else -#error Unsupported platform. -#endif - -#if defined(ANGLE_OS_WIN) -#define STRICT -#define VC_EXTRALEAN 1 -#include -#elif defined(ANGLE_OS_POSIX) #include #include #include -#endif // ANGLE_OS_WIN - +#else +#error Unsupported platform. +#endif #include "compiler/debug.h" @@ -43,23 +42,17 @@ #if defined(ANGLE_OS_WIN) typedef DWORD OS_TLSIndex; #define OS_INVALID_TLS_INDEX (TLS_OUT_OF_INDEXES) +#elif defined(ANGLE_OS_WINRT) +typedef size_t OS_TLSIndex; +#define OS_INVALID_TLS_INDEX ((DWORD)0xFFFFFF) #elif defined(ANGLE_OS_POSIX) typedef pthread_key_t OS_TLSIndex; #define OS_INVALID_TLS_INDEX (static_cast(-1)) #endif // ANGLE_OS_WIN OS_TLSIndex OS_AllocTLSIndex(); +void *OS_GetTLSValue(OS_TLSIndex nIndex); bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue); bool OS_FreeTLSIndex(OS_TLSIndex nIndex); -inline void* OS_GetTLSValue(OS_TLSIndex nIndex) -{ - ASSERT(nIndex != OS_INVALID_TLS_INDEX); -#if defined(ANGLE_OS_WIN) - return TlsGetValue(nIndex); -#elif defined(ANGLE_OS_POSIX) - return pthread_getspecific(nIndex); -#endif // ANGLE_OS_WIN -} - #endif // __OSINCLUDE_H diff --git a/src/3rdparty/angle/src/compiler/ossource_posix.cpp b/src/3rdparty/angle/src/compiler/ossource_posix.cpp index 1e1e699aeb..35510c1af5 100644 --- a/src/3rdparty/angle/src/compiler/ossource_posix.cpp +++ b/src/3rdparty/angle/src/compiler/ossource_posix.cpp @@ -33,6 +33,14 @@ OS_TLSIndex OS_AllocTLSIndex() } +void *OS_GetTLSValue(OS_TLSIndex nIndex) +{ + ASSERT(nIndex != OS_INVALID_TLS_INDEX); + + return pthread_getspecific(nIndex); +} + + bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) { if (nIndex == OS_INVALID_TLS_INDEX) { diff --git a/src/3rdparty/angle/src/compiler/ossource_win.cpp b/src/3rdparty/angle/src/compiler/ossource_win.cpp index 89922fef3f..708a1ad311 100644 --- a/src/3rdparty/angle/src/compiler/ossource_win.cpp +++ b/src/3rdparty/angle/src/compiler/ossource_win.cpp @@ -29,6 +29,14 @@ OS_TLSIndex OS_AllocTLSIndex() } +void *OS_GetTLSValue(OS_TLSIndex nIndex) +{ + ASSERT(nIndex != OS_INVALID_TLS_INDEX); + + return TlsGetValue(nIndex); +} + + bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) { if (nIndex == OS_INVALID_TLS_INDEX) { diff --git a/src/3rdparty/angle/src/compiler/ossource_winrt.cpp b/src/3rdparty/angle/src/compiler/ossource_winrt.cpp new file mode 100644 index 0000000000..84443abc02 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/ossource_winrt.cpp @@ -0,0 +1,75 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/osinclude.h" +// +// This file contains contains Windows Runtime specific functions +// + +#if !defined(ANGLE_OS_WINRT) +#error Trying to build a WinRT specific file in a non-WinRT build. +#endif + +#include + + +// +// Thread Local Storage Operations +// +__declspec(thread) std::vector *tls = nullptr; +__declspec(thread) std::vector *freeIndices = nullptr; + +OS_TLSIndex OS_AllocTLSIndex() +{ + if (!tls) + tls = new std::vector; + + if (freeIndices && !freeIndices->empty()) { + OS_TLSIndex index = freeIndices->back(); + freeIndices->pop_back(); + return index; + } else { + tls->push_back(nullptr); + return tls->size() - 1; + } +} + + +void *OS_GetTLSValue(OS_TLSIndex nIndex) +{ + ASSERT(nIndex != OS_INVALID_TLS_INDEX); + ASSERT(tls); + + return tls->at(nIndex); +} + + +bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) +{ + if (!tls || nIndex >= tls->size() || nIndex == OS_INVALID_TLS_INDEX) { + ASSERT(0 && "OS_SetTLSValue(): Invalid TLS Index"); + return false; + } + + tls->at(nIndex) = lpvValue; + return true; +} + + +bool OS_FreeTLSIndex(OS_TLSIndex nIndex) +{ + if (!tls || nIndex >= tls->size() || nIndex == OS_INVALID_TLS_INDEX) { + ASSERT(0 && "OS_SetTLSValue(): Invalid TLS Index"); + return false; + } + + if (!freeIndices) + freeIndices = new std::vector; + + freeIndices->push_back(nIndex); + + return true; +} diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp index a382c3b1eb..14973aff30 100644 --- a/src/3rdparty/angle/src/libEGL/Display.cpp +++ b/src/3rdparty/angle/src/libEGL/Display.cpp @@ -186,7 +186,7 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) -EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList) +EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList) { const Config *configuration = mConfigSet.get(config); EGLint postSubBufferSupported = EGL_FALSE; @@ -456,7 +456,7 @@ bool Display::isValidSurface(egl::Surface *surface) return mSurfaceSet.find(surface) != mSurfaceSet.end(); } -bool Display::hasExistingWindowSurface(HWND window) +bool Display::hasExistingWindowSurface(EGLNativeWindowType window) { for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) { @@ -471,7 +471,6 @@ bool Display::hasExistingWindowSurface(HWND window) void Display::initExtensionString() { - HMODULE swiftShader = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); bool shareHandleSupported = mRenderer->getShareHandleSupport(); mExtensionString = ""; @@ -487,10 +486,13 @@ void Display::initExtensionString() mExtensionString += "EGL_ANGLE_query_surface_pointer "; +#if !defined(ANGLE_OS_WINRT) + HMODULE swiftShader = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); if (swiftShader) { mExtensionString += "EGL_ANGLE_software_display "; } +#endif if (shareHandleSupported) { diff --git a/src/3rdparty/angle/src/libEGL/Display.h b/src/3rdparty/angle/src/libEGL/Display.h index 58c3940331..5d55410440 100644 --- a/src/3rdparty/angle/src/libEGL/Display.h +++ b/src/3rdparty/angle/src/libEGL/Display.h @@ -40,7 +40,7 @@ class Display bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig); bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value); - EGLSurface createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList); + EGLSurface createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList); EGLSurface createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList); EGLContext createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess); @@ -51,7 +51,7 @@ class Display bool isValidConfig(EGLConfig config); bool isValidContext(gl::Context *context); bool isValidSurface(egl::Surface *surface); - bool hasExistingWindowSurface(HWND window); + bool hasExistingWindowSurface(EGLNativeWindowType window); rx::Renderer *getRenderer() { return mRenderer; }; diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp index b47a7bcc20..abc6d7d3b9 100644 --- a/src/3rdparty/angle/src/libEGL/Surface.cpp +++ b/src/3rdparty/angle/src/libEGL/Surface.cpp @@ -20,10 +20,15 @@ #include "libEGL/main.h" #include "libEGL/Display.h" +#if defined(ANGLE_OS_WINRT) +#include +#include +#endif + namespace egl { -Surface::Surface(Display *display, const Config *config, HWND window, EGLint postSubBufferSupported) +Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint postSubBufferSupported) : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported) { mRenderer = mDisplay->getRenderer(); @@ -96,6 +101,7 @@ bool Surface::resetSwapChain() if (mWindow) { +#if !defined(ANGLE_OS_WINRT) RECT windowRect; if (!GetClientRect(getWindowHandle(), &windowRect)) { @@ -107,6 +113,14 @@ bool Surface::resetSwapChain() width = windowRect.right - windowRect.left; height = windowRect.bottom - windowRect.top; +#else + ABI::Windows::Foundation::Rect windowRect; + ABI::Windows::UI::Core::ICoreWindow *window; + ASSERT(SUCCEEDED(mWindow->QueryInterface(IID_PPV_ARGS(&window)))); + window->get_Bounds(&windowRect); + width = windowRect.Width; + height = windowRect.Height; +#endif } else { @@ -226,7 +240,7 @@ bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) return true; } -HWND Surface::getWindowHandle() +EGLNativeWindowType Surface::getWindowHandle() { return mWindow; } @@ -235,6 +249,7 @@ HWND Surface::getWindowHandle() #define kSurfaceProperty _TEXT("Egl::SurfaceOwner") #define kParentWndProc _TEXT("Egl::SurfaceParentWndProc") +#if !defined(ANGLE_OS_WINRT) static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { if (message == WM_SIZE) @@ -248,9 +263,13 @@ static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam WNDPROC prevWndFunc = reinterpret_cast(GetProp(hwnd, kParentWndProc)); return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam); } +#endif void Surface::subclassWindow() { +#if defined(ANGLE_OS_WINRT) + mWindowSubclassed = false; +#else if (!mWindow) { return; @@ -274,10 +293,12 @@ void Surface::subclassWindow() SetProp(mWindow, kSurfaceProperty, reinterpret_cast(this)); SetProp(mWindow, kParentWndProc, reinterpret_cast(oldWndProc)); mWindowSubclassed = true; +#endif } void Surface::unsubclassWindow() { +#if !defined(ANGLE_OS_WINRT) if(!mWindowSubclassed) { return; @@ -300,10 +321,12 @@ void Surface::unsubclassWindow() RemoveProp(mWindow, kSurfaceProperty); RemoveProp(mWindow, kParentWndProc); mWindowSubclassed = false; +#endif } bool Surface::checkForOutOfDateSwapChain() { +#if !defined(ANGLE_OS_WINRT) RECT client; if (!GetClientRect(getWindowHandle(), &client)) { @@ -314,6 +337,14 @@ bool Surface::checkForOutOfDateSwapChain() // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information. int clientWidth = client.right - client.left; int clientHeight = client.bottom - client.top; +#else + ABI::Windows::Foundation::Rect windowRect; + ABI::Windows::UI::Core::ICoreWindow *window; + ASSERT(SUCCEEDED(mWindow->QueryInterface(IID_PPV_ARGS(&window)))); + window->get_Bounds(&windowRect); + int clientWidth = windowRect.Width; + int clientHeight = windowRect.Height; +#endif bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); if (mSwapIntervalDirty) diff --git a/src/3rdparty/angle/src/libEGL/Surface.h b/src/3rdparty/angle/src/libEGL/Surface.h index 938b800cdd..ae9a380858 100644 --- a/src/3rdparty/angle/src/libEGL/Surface.h +++ b/src/3rdparty/angle/src/libEGL/Surface.h @@ -15,6 +15,7 @@ #include #include "common/angleutils.h" +#include "windows.h" namespace gl { @@ -34,7 +35,7 @@ class Config; class Surface { public: - Surface(Display *display, const egl::Config *config, HWND window, EGLint postSubBufferSupported); + Surface(Display *display, const egl::Config *config, EGLNativeWindowType window, EGLint postSubBufferSupported); Surface(Display *display, const egl::Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget); ~Surface(); @@ -43,7 +44,7 @@ class Surface void release(); bool resetSwapChain(); - HWND getWindowHandle(); + EGLNativeWindowType getWindowHandle(); bool swap(); bool postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height); @@ -79,7 +80,7 @@ private: bool resetSwapChain(int backbufferWidth, int backbufferHeight); bool swapRect(EGLint x, EGLint y, EGLint width, EGLint height); - const HWND mWindow; // Window that the surface is created for. + const EGLNativeWindowType mWindow; // Window that the surface is created for. bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking const egl::Config *mConfig; // EGL config surface was created with EGLint mHeight; // Height of surface diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp index 6e10c3926d..5bcb5d5959 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL.cpp +++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp @@ -308,14 +308,16 @@ EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EG return EGL_NO_SURFACE; } +#if !defined(ANGLE_OS_WINRT) HWND window = (HWND)win; if (!IsWindow(window)) { return egl::error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); } +#endif - return display->createWindowSurface(window, config, attrib_list); + return display->createWindowSurface(win, config, attrib_list); } catch(std::bad_alloc&) { diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp index 7dea5fc74b..964b4b21fd 100644 --- a/src/3rdparty/angle/src/libEGL/main.cpp +++ b/src/3rdparty/angle/src/libEGL/main.cpp @@ -1,3 +1,4 @@ +#include "../libGLESv2/precompiled.h" // // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -12,7 +13,13 @@ #ifndef QT_OPENGL_ES_2_ANGLE_STATIC +#if !defined(ANGLE_OS_WINRT) static DWORD currentTLS = TLS_OUT_OF_INDEXES; +#else +static __declspec(thread) void *currentTLS = 0; +#endif + +namespace egl { Current *getCurrent(); } extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) { @@ -35,22 +42,25 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved } #endif +#if !defined(ANGLE_OS_WINRT) currentTLS = TlsAlloc(); if (currentTLS == TLS_OUT_OF_INDEXES) { return FALSE; } +#endif } // Fall throught to initialize index case DLL_THREAD_ATTACH: { - egl::Current *current = (egl::Current*)LocalAlloc(LPTR, sizeof(egl::Current)); + egl::Current *current = egl::getCurrent(); if (current) { +#if !defined(ANGLE_OS_WINRT) TlsSetValue(currentTLS, current); - +#endif current->error = EGL_SUCCESS; current->API = EGL_OPENGL_ES_API; current->display = EGL_NO_DISPLAY; @@ -61,24 +71,35 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved break; case DLL_THREAD_DETACH: { - void *current = TlsGetValue(currentTLS); + egl::Current *current = egl::getCurrent(); if (current) { +#if !defined(ANGLE_OS_WINRT) LocalFree((HLOCAL)current); +#else + HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, current); + currentTLS = 0; +#endif } } break; case DLL_PROCESS_DETACH: { - void *current = TlsGetValue(currentTLS); + egl::Current *current = egl::getCurrent(); if (current) { +#if !defined(ANGLE_OS_WINRT) LocalFree((HLOCAL)current); } TlsFree(currentTLS); +#else + HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, current); + currentTLS = 0; + } +#endif } break; default: @@ -95,7 +116,16 @@ namespace egl Current *getCurrent() { #ifndef QT_OPENGL_ES_2_ANGLE_STATIC - return (Current*)TlsGetValue(currentTLS); +#if !defined(ANGLE_OS_WINRT) + Current *current = (Current*)TlsGetValue(currentTLS); + if (!current) + current = (Current*)LocalAlloc(LPTR, sizeof(Current)); + return current; +#else + if (!currentTLS) + currentTLS = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY, sizeof(Current)); + return (Current*)currentTLS; +#endif #else // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. static Current curr = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE }; diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp index 730a6ac022..defdf35f77 100644 --- a/src/3rdparty/angle/src/libGLESv2/main.cpp +++ b/src/3rdparty/angle/src/libGLESv2/main.cpp @@ -13,7 +13,13 @@ #ifndef QT_OPENGL_ES_2_ANGLE_STATIC +#if !defined(ANGLE_OS_WINRT) static DWORD currentTLS = TLS_OUT_OF_INDEXES; +#else +static __declspec(thread) void *currentTLS = 0; +#endif + +namespace gl { Current *getCurrent(); } extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) { @@ -21,22 +27,25 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved { case DLL_PROCESS_ATTACH: { +#if !defined(ANGLE_OS_WINRT) currentTLS = TlsAlloc(); if (currentTLS == TLS_OUT_OF_INDEXES) { return FALSE; } +#endif } // Fall throught to initialize index case DLL_THREAD_ATTACH: { - gl::Current *current = (gl::Current*)LocalAlloc(LPTR, sizeof(gl::Current)); + gl::Current *current = gl::getCurrent(); if (current) { +#if !defined(ANGLE_OS_WINRT) TlsSetValue(currentTLS, current); - +#endif current->context = NULL; current->display = NULL; } @@ -44,24 +53,35 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved break; case DLL_THREAD_DETACH: { - void *current = TlsGetValue(currentTLS); + gl::Current *current = gl::getCurrent(); if (current) { +#if !defined(ANGLE_OS_WINRT) LocalFree((HLOCAL)current); +#else + HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, current); + currentTLS = 0; +#endif } } break; case DLL_PROCESS_DETACH: { - void *current = TlsGetValue(currentTLS); + gl::Current *current = gl::getCurrent(); if (current) { +#if !defined(ANGLE_OS_WINRT) LocalFree((HLOCAL)current); } TlsFree(currentTLS); +#else + HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, current); + currentTLS = 0; + } +#endif } break; default: @@ -78,7 +98,16 @@ namespace gl Current *getCurrent() { #ifndef QT_OPENGL_ES_2_ANGLE_STATIC - return (Current*)TlsGetValue(currentTLS); +#if !defined(ANGLE_OS_WINRT) + Current *current = (Current*)TlsGetValue(currentTLS); + if (!current) + current = (Current*)LocalAlloc(LPTR, sizeof(Current)); + return current; +#else + if (!currentTLS) + currentTLS = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY, sizeof(Current)); + return (Current*)currentTLS; +#endif #else // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. static gl::Current curr = { 0, 0 }; diff --git a/src/3rdparty/angle/src/libGLESv2/precompiled.h b/src/3rdparty/angle/src/libGLESv2/precompiled.h index 50dec6b084..823d27bb60 100644 --- a/src/3rdparty/angle/src/libGLESv2/precompiled.h +++ b/src/3rdparty/angle/src/libGLESv2/precompiled.h @@ -32,13 +32,28 @@ #include #include +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) +#define ANGLE_OS_WINRT +#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP +#define ANGLE_OS_WINPHONE +#endif +#endif + #ifndef ANGLE_ENABLE_D3D11 #include #else +#if !defined(ANGLE_OS_WINRT) #include +#else +#include +#define Sleep(x) WaitForSingleObjectEx(GetCurrentThread(), x, FALSE) +#define GetVersion() WINVER +#endif #include #endif +#ifndef ANGLE_OS_WINPHONE #include +#endif #ifdef _MSC_VER #include diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp index 21ad223467..7ba183d250 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp @@ -28,13 +28,18 @@ #define D3DERR_OUTOFVIDEOMEMORY MAKE_HRESULT(1, 0x876, 380) #endif -#ifdef __MINGW32__ - #ifndef D3DCOMPILER_DLL +#ifndef ANGLE_OS_WINPHONE +#define D3DCOMPILER_DLL L"d3dcompiler_43.dll" // Lowest common denominator +#else +#define D3DCOMPILER_DLL L"qtd3dcompiler.dll" // Placeholder DLL for phone +#endif // ANGLE_OS_WINPHONE +#endif // D3DCOMPILER_DLL + +#if defined(__MINGW32__) || defined(ANGLE_OS_WINPHONE) //Add define + typedefs for older MinGW-w64 headers (pre 5783) - -#define D3DCOMPILER_DLL L"d3dcompiler_43.dll" +//Also define these on Windows Phone, which doesn't have a shader compiler HRESULT WINAPI D3DCompile(const void *data, SIZE_T data_size, const char *filename, const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, @@ -43,9 +48,7 @@ typedef HRESULT (WINAPI *pD3DCompile)(const void *data, SIZE_T data_size, const const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages); -#endif // D3DCOMPILER_DLL - -#endif // __MINGW32__ +#endif // __MINGW32__ || ANGLE_OS_WINPHONE namespace rx { @@ -81,7 +84,11 @@ bool Renderer::initializeCompiler() } #else // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. +#if !defined(ANGLE_OS_WINRT) mD3dCompilerModule = LoadLibrary(D3DCOMPILER_DLL); +#else + mD3dCompilerModule = LoadPackagedLibrary(D3DCOMPILER_DLL, NULL); +#endif #endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES if (!mD3dCompilerModule) @@ -225,4 +232,4 @@ void glDestroyRenderer(rx::Renderer *renderer) delete renderer; } -} \ No newline at end of file +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h index 04e877ba9e..ac67c27e71 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h @@ -1,3 +1,4 @@ +#include "../precompiled.h" // // Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -13,6 +14,30 @@ #include "libGLESv2/Uniform.h" #include "libGLESv2/angletypes.h" +#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL0 +#define D3DCOMPILE_OPTIMIZATION_LEVEL0 (1 << 14) +#endif +#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL1 +#define D3DCOMPILE_OPTIMIZATION_LEVEL1 0 +#endif +#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL2 +#define D3DCOMPILE_OPTIMIZATION_LEVEL2 ((1 << 14) | (1 << 15)) +#endif +#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL3 +#define D3DCOMPILE_OPTIMIZATION_LEVEL3 (1 << 15) +#endif +#ifndef D3DCOMPILE_DEBUG +#define D3DCOMPILE_DEBUG (1 << 0) +#endif +#ifndef D3DCOMPILE_SKIP_OPTIMIZATION +#define D3DCOMPILE_SKIP_OPTIMIZATION (1 << 2) +#endif +#ifndef D3DCOMPILE_AVOID_FLOW_CONTROL +#define D3DCOMPILE_AVOID_FLOW_CONTROL (1 << 9) +#endif +#ifndef D3DCOMPILE_PREFER_FLOW_CONTROL +#define D3DCOMPILE_PREFER_FLOW_CONTROL (1 << 10) +#endif #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) #define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 #endif @@ -107,7 +132,7 @@ class Renderer virtual void sync(bool block) = 0; - virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0; + virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0; virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler) = 0; virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp index a43101807a..d04467b2a0 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp @@ -137,6 +137,7 @@ EGLint Renderer11::initialize() return EGL_NOT_INITIALIZED; } +#if !defined(ANGLE_OS_WINRT) mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); @@ -155,6 +156,7 @@ EGLint Renderer11::initialize() ERR("Could not retrieve D3D11CreateDevice address - aborting!\n"); return EGL_NOT_INITIALIZED; } +#endif D3D_FEATURE_LEVEL featureLevels[] = { @@ -203,8 +205,12 @@ EGLint Renderer11::initialize() } } +#if !defined(ANGLE_OS_WINRT) IDXGIDevice *dxgiDevice = NULL; - result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); +#else + IDXGIDevice1 *dxgiDevice = NULL; +#endif + result = mDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice)); if (FAILED(result)) { @@ -524,7 +530,7 @@ void Renderer11::sync(bool block) } } -SwapChain *Renderer11::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) +SwapChain *Renderer11::createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) { return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat); } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h index f024855f97..a7f5a397e5 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h @@ -52,7 +52,7 @@ class Renderer11 : public Renderer virtual void sync(bool block); - virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); + virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler); virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h index 14c0515fc8..a6870ebedc 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h @@ -18,7 +18,7 @@ namespace rx class SwapChain { public: - SwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) + SwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) : mWindow(window), mShareHandle(shareHandle), mBackBufferFormat(backBufferFormat), mDepthBufferFormat(depthBufferFormat) { } @@ -33,7 +33,7 @@ class SwapChain virtual HANDLE getShareHandle() {return mShareHandle;}; protected: - const HWND mWindow; // Window that the surface is created for. + const EGLNativeWindowType mWindow; // Window that the surface is created for. const GLenum mBackBufferFormat; const GLenum mDepthBufferFormat; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp index 0da58cbe2e..0797fd7d82 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp @@ -17,7 +17,7 @@ namespace rx { -SwapChain11::SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle, +SwapChain11::SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat) { @@ -468,6 +468,7 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap if (mWindow) { +#if !defined(ANGLE_OS_WINRT) // We cannot create a swap chain for an HWND that is owned by a different process DWORD currentProcessId = GetCurrentProcessId(); DWORD wndProcessId; @@ -491,14 +492,34 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; + swapChainDesc.Windowed = TRUE; + swapChainDesc.OutputWindow = mWindow; +#else + IDXGIFactory2 *factory; + HRESULT result = mRenderer->getDxgiFactory()->QueryInterface(IID_PPV_ARGS(&factory)); + ASSERT(SUCCEEDED(result)); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; + swapChainDesc.BufferCount = 2; + swapChainDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); + swapChainDesc.Width = backbufferWidth; + swapChainDesc.Height = backbufferHeight; + swapChainDesc.Stereo = FALSE; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; +#endif + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.Flags = 0; - swapChainDesc.OutputWindow = mWindow; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; - swapChainDesc.Windowed = TRUE; - HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain); +#if !defined(ANGLE_OS_WINRT) + result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain); +#else + IDXGISwapChain1 *swapChain; + result = factory->CreateSwapChainForCoreWindow(device, mWindow, &swapChainDesc, NULL, &swapChain); + mSwapChain = swapChain; +#endif if (FAILED(result)) { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.h index 800104602e..2a030c839d 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.h @@ -19,7 +19,7 @@ class Renderer11; class SwapChain11 : public SwapChain { public: - SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle, + SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); virtual ~SwapChain11(); diff --git a/src/3rdparty/angle/src/libGLESv2/utilities.cpp b/src/3rdparty/angle/src/libGLESv2/utilities.cpp index 32df49e672..8fd193b164 100644 --- a/src/3rdparty/angle/src/libGLESv2/utilities.cpp +++ b/src/3rdparty/angle/src/libGLESv2/utilities.cpp @@ -10,6 +10,14 @@ #include "libGLESv2/utilities.h" #include "libGLESv2/mathutil.h" +#if defined(ANGLE_OS_WINRT) +#include +#include +#include +#include +using namespace ABI::Windows::Storage; +#endif + namespace gl { @@ -737,7 +745,50 @@ bool IsTriangleMode(GLenum drawMode) std::string getTempPath() { +#if defined(ANGLE_OS_WINRT) + + static std::string path; + + while (path.empty()) { + IApplicationDataStatics *applicationDataFactory; + HRESULT result = RoGetActivationFactory(Microsoft::WRL::Wrappers::HStringReference(RuntimeClass_Windows_Storage_ApplicationData).Get(), + IID_PPV_ARGS(&applicationDataFactory)); + if (FAILED(result)) + break; + + IApplicationData *applicationData; + result = applicationDataFactory->get_Current(&applicationData); + if (FAILED(result)) + break; + + IStorageFolder *storageFolder; + result = applicationData->get_LocalFolder(&storageFolder); + if (FAILED(result)) + break; + + IStorageItem *localFolder; + result = storageFolder->QueryInterface(IID_PPV_ARGS(&localFolder)); + if (FAILED(result)) + break; + + HSTRING localFolderPath; + result = localFolder->get_Path(&localFolderPath); + if (FAILED(result)) + break; + + std::wstring_convert< std::codecvt_utf8 > converter; + path = converter.to_bytes(WindowsGetStringRawBuffer(localFolderPath, NULL)); + if (path.empty()) + { + UNREACHABLE(); + break; + } + } + +#else + char path[MAX_PATH]; + DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path); if (pathLen == 0) { @@ -751,6 +802,8 @@ std::string getTempPath() UNREACHABLE(); return std::string(); } + +#endif return path; } diff --git a/src/angle/patches/0012-ANGLE-Support-WinRT.patch b/src/angle/patches/0012-ANGLE-Support-WinRT.patch new file mode 100644 index 0000000000..8a5b96c7c0 --- /dev/null +++ b/src/angle/patches/0012-ANGLE-Support-WinRT.patch @@ -0,0 +1,1131 @@ +From 67c318c7b9c6d95d3170d11956dbec56494511ca Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Tue, 1 Oct 2013 09:43:29 +0300 +Subject: [PATCH] ANGLE: Support WinRT + +This enables EGL for WinRT's native types, and adjusts some codepaths +to accommodate differences in between desktop Windows and WinRT. + +- WinRT native handles added to eglplatform.h +- References to native handles in libEGL/libGLESv2 follow eglplatform.h +- D3D 11.1 structures and methods used when necessary +- TLS replaced with thread attribute +- LocalAlloc/Free replaced with Heap API + +Change-Id: Ia90377e700d335a1c569c2145008dd4b0dfd84d3 +Reviewed-by: Friedemann Kleint +--- + src/3rdparty/angle/include/EGL/eglplatform.h | 10 ++- + src/3rdparty/angle/src/compiler/osinclude.h | 35 ++++------ + src/3rdparty/angle/src/compiler/ossource_posix.cpp | 8 +++ + src/3rdparty/angle/src/compiler/ossource_win.cpp | 8 +++ + src/3rdparty/angle/src/compiler/ossource_winrt.cpp | 75 ++++++++++++++++++++++ + src/3rdparty/angle/src/libEGL/Display.cpp | 8 ++- + src/3rdparty/angle/src/libEGL/Display.h | 4 +- + src/3rdparty/angle/src/libEGL/Surface.cpp | 35 +++++++++- + src/3rdparty/angle/src/libEGL/Surface.h | 7 +- + src/3rdparty/angle/src/libEGL/libEGL.cpp | 4 +- + src/3rdparty/angle/src/libEGL/main.cpp | 40 ++++++++++-- + src/3rdparty/angle/src/libGLESv2/main.cpp | 39 +++++++++-- + src/3rdparty/angle/src/libGLESv2/precompiled.h | 15 +++++ + .../angle/src/libGLESv2/renderer/Renderer.cpp | 23 ++++--- + .../angle/src/libGLESv2/renderer/Renderer.h | 27 +++++++- + .../angle/src/libGLESv2/renderer/Renderer11.cpp | 10 ++- + .../angle/src/libGLESv2/renderer/Renderer11.h | 2 +- + .../angle/src/libGLESv2/renderer/SwapChain.h | 4 +- + .../angle/src/libGLESv2/renderer/SwapChain11.cpp | 29 +++++++-- + .../angle/src/libGLESv2/renderer/SwapChain11.h | 2 +- + src/3rdparty/angle/src/libGLESv2/utilities.cpp | 53 +++++++++++++++ + src/angle/src/common/common.pri | 2 +- + src/angle/src/compiler/translator_common.pro | 7 +- + src/angle/src/config.pri | 5 +- + 24 files changed, 386 insertions(+), 66 deletions(-) + create mode 100644 src/3rdparty/angle/src/compiler/ossource_winrt.cpp + +diff --git a/src/3rdparty/angle/include/EGL/eglplatform.h b/src/3rdparty/angle/include/EGL/eglplatform.h +index 34283f2..eb15ae5 100644 +--- a/src/3rdparty/angle/include/EGL/eglplatform.h ++++ b/src/3rdparty/angle/include/EGL/eglplatform.h +@@ -67,7 +67,15 @@ + * implementations. + */ + +-#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */ ++#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) /* Windows Runtime */ ++ ++struct IUnknown; ++ ++typedef int EGLNativeDisplayType; ++typedef void *EGLNativePixmapType; ++typedef IUnknown *EGLNativeWindowType; ++ ++#elif defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */ + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN 1 + #endif +diff --git a/src/3rdparty/angle/src/compiler/osinclude.h b/src/3rdparty/angle/src/compiler/osinclude.h +index d8bb1a7..60177d5 100644 +--- a/src/3rdparty/angle/src/compiler/osinclude.h ++++ b/src/3rdparty/angle/src/compiler/osinclude.h +@@ -13,27 +13,26 @@ + // + + #if defined(_WIN32) || defined(_WIN64) ++#define STRICT ++#define VC_EXTRALEAN 1 ++#include ++#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) ++#define ANGLE_OS_WINRT ++#else + #define ANGLE_OS_WIN ++#endif + #elif defined(__APPLE__) || defined(__linux__) || \ + defined(__FreeBSD__) || defined(__OpenBSD__) || \ + defined(__sun) || defined(ANDROID) || \ + defined(__GLIBC__) || defined(__GNU__) || \ + defined(__QNX__) + #define ANGLE_OS_POSIX +-#else +-#error Unsupported platform. +-#endif +- +-#if defined(ANGLE_OS_WIN) +-#define STRICT +-#define VC_EXTRALEAN 1 +-#include +-#elif defined(ANGLE_OS_POSIX) + #include + #include + #include +-#endif // ANGLE_OS_WIN +- ++#else ++#error Unsupported platform. ++#endif + + #include "compiler/debug.h" + +@@ -43,23 +42,17 @@ + #if defined(ANGLE_OS_WIN) + typedef DWORD OS_TLSIndex; + #define OS_INVALID_TLS_INDEX (TLS_OUT_OF_INDEXES) ++#elif defined(ANGLE_OS_WINRT) ++typedef size_t OS_TLSIndex; ++#define OS_INVALID_TLS_INDEX ((DWORD)0xFFFFFF) + #elif defined(ANGLE_OS_POSIX) + typedef pthread_key_t OS_TLSIndex; + #define OS_INVALID_TLS_INDEX (static_cast(-1)) + #endif // ANGLE_OS_WIN + + OS_TLSIndex OS_AllocTLSIndex(); ++void *OS_GetTLSValue(OS_TLSIndex nIndex); + bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue); + bool OS_FreeTLSIndex(OS_TLSIndex nIndex); + +-inline void* OS_GetTLSValue(OS_TLSIndex nIndex) +-{ +- ASSERT(nIndex != OS_INVALID_TLS_INDEX); +-#if defined(ANGLE_OS_WIN) +- return TlsGetValue(nIndex); +-#elif defined(ANGLE_OS_POSIX) +- return pthread_getspecific(nIndex); +-#endif // ANGLE_OS_WIN +-} +- + #endif // __OSINCLUDE_H +diff --git a/src/3rdparty/angle/src/compiler/ossource_posix.cpp b/src/3rdparty/angle/src/compiler/ossource_posix.cpp +index 1e1e699..35510c1 100644 +--- a/src/3rdparty/angle/src/compiler/ossource_posix.cpp ++++ b/src/3rdparty/angle/src/compiler/ossource_posix.cpp +@@ -33,6 +33,14 @@ OS_TLSIndex OS_AllocTLSIndex() + } + + ++void *OS_GetTLSValue(OS_TLSIndex nIndex) ++{ ++ ASSERT(nIndex != OS_INVALID_TLS_INDEX); ++ ++ return pthread_getspecific(nIndex); ++} ++ ++ + bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) + { + if (nIndex == OS_INVALID_TLS_INDEX) { +diff --git a/src/3rdparty/angle/src/compiler/ossource_win.cpp b/src/3rdparty/angle/src/compiler/ossource_win.cpp +index 89922fe..708a1ad 100644 +--- a/src/3rdparty/angle/src/compiler/ossource_win.cpp ++++ b/src/3rdparty/angle/src/compiler/ossource_win.cpp +@@ -29,6 +29,14 @@ OS_TLSIndex OS_AllocTLSIndex() + } + + ++void *OS_GetTLSValue(OS_TLSIndex nIndex) ++{ ++ ASSERT(nIndex != OS_INVALID_TLS_INDEX); ++ ++ return TlsGetValue(nIndex); ++} ++ ++ + bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) + { + if (nIndex == OS_INVALID_TLS_INDEX) { +diff --git a/src/3rdparty/angle/src/compiler/ossource_winrt.cpp b/src/3rdparty/angle/src/compiler/ossource_winrt.cpp +new file mode 100644 +index 0000000..84443ab +--- /dev/null ++++ b/src/3rdparty/angle/src/compiler/ossource_winrt.cpp +@@ -0,0 +1,75 @@ ++// ++// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++// ++ ++#include "compiler/osinclude.h" ++// ++// This file contains contains Windows Runtime specific functions ++// ++ ++#if !defined(ANGLE_OS_WINRT) ++#error Trying to build a WinRT specific file in a non-WinRT build. ++#endif ++ ++#include ++ ++ ++// ++// Thread Local Storage Operations ++// ++__declspec(thread) std::vector *tls = nullptr; ++__declspec(thread) std::vector *freeIndices = nullptr; ++ ++OS_TLSIndex OS_AllocTLSIndex() ++{ ++ if (!tls) ++ tls = new std::vector; ++ ++ if (freeIndices && !freeIndices->empty()) { ++ OS_TLSIndex index = freeIndices->back(); ++ freeIndices->pop_back(); ++ return index; ++ } else { ++ tls->push_back(nullptr); ++ return tls->size() - 1; ++ } ++} ++ ++ ++void *OS_GetTLSValue(OS_TLSIndex nIndex) ++{ ++ ASSERT(nIndex != OS_INVALID_TLS_INDEX); ++ ASSERT(tls); ++ ++ return tls->at(nIndex); ++} ++ ++ ++bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) ++{ ++ if (!tls || nIndex >= tls->size() || nIndex == OS_INVALID_TLS_INDEX) { ++ ASSERT(0 && "OS_SetTLSValue(): Invalid TLS Index"); ++ return false; ++ } ++ ++ tls->at(nIndex) = lpvValue; ++ return true; ++} ++ ++ ++bool OS_FreeTLSIndex(OS_TLSIndex nIndex) ++{ ++ if (!tls || nIndex >= tls->size() || nIndex == OS_INVALID_TLS_INDEX) { ++ ASSERT(0 && "OS_SetTLSValue(): Invalid TLS Index"); ++ return false; ++ } ++ ++ if (!freeIndices) ++ freeIndices = new std::vector; ++ ++ freeIndices->push_back(nIndex); ++ ++ return true; ++} +diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp +index a382c3b..14973af 100644 +--- a/src/3rdparty/angle/src/libEGL/Display.cpp ++++ b/src/3rdparty/angle/src/libEGL/Display.cpp +@@ -186,7 +186,7 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) + + + +-EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList) ++EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList) + { + const Config *configuration = mConfigSet.get(config); + EGLint postSubBufferSupported = EGL_FALSE; +@@ -456,7 +456,7 @@ bool Display::isValidSurface(egl::Surface *surface) + return mSurfaceSet.find(surface) != mSurfaceSet.end(); + } + +-bool Display::hasExistingWindowSurface(HWND window) ++bool Display::hasExistingWindowSurface(EGLNativeWindowType window) + { + for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) + { +@@ -471,7 +471,6 @@ bool Display::hasExistingWindowSurface(HWND window) + + void Display::initExtensionString() + { +- HMODULE swiftShader = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); + bool shareHandleSupported = mRenderer->getShareHandleSupport(); + + mExtensionString = ""; +@@ -487,10 +486,13 @@ void Display::initExtensionString() + + mExtensionString += "EGL_ANGLE_query_surface_pointer "; + ++#if !defined(ANGLE_OS_WINRT) ++ HMODULE swiftShader = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); + if (swiftShader) + { + mExtensionString += "EGL_ANGLE_software_display "; + } ++#endif + + if (shareHandleSupported) + { +diff --git a/src/3rdparty/angle/src/libEGL/Display.h b/src/3rdparty/angle/src/libEGL/Display.h +index 58c3940..5d55410 100644 +--- a/src/3rdparty/angle/src/libEGL/Display.h ++++ b/src/3rdparty/angle/src/libEGL/Display.h +@@ -40,7 +40,7 @@ class Display + bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig); + bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value); + +- EGLSurface createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList); ++ EGLSurface createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList); + EGLSurface createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList); + EGLContext createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess); + +@@ -51,7 +51,7 @@ class Display + bool isValidConfig(EGLConfig config); + bool isValidContext(gl::Context *context); + bool isValidSurface(egl::Surface *surface); +- bool hasExistingWindowSurface(HWND window); ++ bool hasExistingWindowSurface(EGLNativeWindowType window); + + rx::Renderer *getRenderer() { return mRenderer; }; + +diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp +index b47a7bc..abc6d7d 100644 +--- a/src/3rdparty/angle/src/libEGL/Surface.cpp ++++ b/src/3rdparty/angle/src/libEGL/Surface.cpp +@@ -20,10 +20,15 @@ + #include "libEGL/main.h" + #include "libEGL/Display.h" + ++#if defined(ANGLE_OS_WINRT) ++#include ++#include ++#endif ++ + namespace egl + { + +-Surface::Surface(Display *display, const Config *config, HWND window, EGLint postSubBufferSupported) ++Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint postSubBufferSupported) + : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported) + { + mRenderer = mDisplay->getRenderer(); +@@ -96,6 +101,7 @@ bool Surface::resetSwapChain() + + if (mWindow) + { ++#if !defined(ANGLE_OS_WINRT) + RECT windowRect; + if (!GetClientRect(getWindowHandle(), &windowRect)) + { +@@ -107,6 +113,14 @@ bool Surface::resetSwapChain() + + width = windowRect.right - windowRect.left; + height = windowRect.bottom - windowRect.top; ++#else ++ ABI::Windows::Foundation::Rect windowRect; ++ ABI::Windows::UI::Core::ICoreWindow *window; ++ ASSERT(SUCCEEDED(mWindow->QueryInterface(IID_PPV_ARGS(&window)))); ++ window->get_Bounds(&windowRect); ++ width = windowRect.Width; ++ height = windowRect.Height; ++#endif + } + else + { +@@ -226,7 +240,7 @@ bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) + return true; + } + +-HWND Surface::getWindowHandle() ++EGLNativeWindowType Surface::getWindowHandle() + { + return mWindow; + } +@@ -235,6 +249,7 @@ HWND Surface::getWindowHandle() + #define kSurfaceProperty _TEXT("Egl::SurfaceOwner") + #define kParentWndProc _TEXT("Egl::SurfaceParentWndProc") + ++#if !defined(ANGLE_OS_WINRT) + static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) + { + if (message == WM_SIZE) +@@ -248,9 +263,13 @@ static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam + WNDPROC prevWndFunc = reinterpret_cast(GetProp(hwnd, kParentWndProc)); + return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam); + } ++#endif + + void Surface::subclassWindow() + { ++#if defined(ANGLE_OS_WINRT) ++ mWindowSubclassed = false; ++#else + if (!mWindow) + { + return; +@@ -274,10 +293,12 @@ void Surface::subclassWindow() + SetProp(mWindow, kSurfaceProperty, reinterpret_cast(this)); + SetProp(mWindow, kParentWndProc, reinterpret_cast(oldWndProc)); + mWindowSubclassed = true; ++#endif + } + + void Surface::unsubclassWindow() + { ++#if !defined(ANGLE_OS_WINRT) + if(!mWindowSubclassed) + { + return; +@@ -300,10 +321,12 @@ void Surface::unsubclassWindow() + RemoveProp(mWindow, kSurfaceProperty); + RemoveProp(mWindow, kParentWndProc); + mWindowSubclassed = false; ++#endif + } + + bool Surface::checkForOutOfDateSwapChain() + { ++#if !defined(ANGLE_OS_WINRT) + RECT client; + if (!GetClientRect(getWindowHandle(), &client)) + { +@@ -314,6 +337,14 @@ bool Surface::checkForOutOfDateSwapChain() + // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information. + int clientWidth = client.right - client.left; + int clientHeight = client.bottom - client.top; ++#else ++ ABI::Windows::Foundation::Rect windowRect; ++ ABI::Windows::UI::Core::ICoreWindow *window; ++ ASSERT(SUCCEEDED(mWindow->QueryInterface(IID_PPV_ARGS(&window)))); ++ window->get_Bounds(&windowRect); ++ int clientWidth = windowRect.Width; ++ int clientHeight = windowRect.Height; ++#endif + bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); + + if (mSwapIntervalDirty) +diff --git a/src/3rdparty/angle/src/libEGL/Surface.h b/src/3rdparty/angle/src/libEGL/Surface.h +index 938b800..ae9a380 100644 +--- a/src/3rdparty/angle/src/libEGL/Surface.h ++++ b/src/3rdparty/angle/src/libEGL/Surface.h +@@ -15,6 +15,7 @@ + #include + + #include "common/angleutils.h" ++#include "windows.h" + + namespace gl + { +@@ -34,7 +35,7 @@ class Config; + class Surface + { + public: +- Surface(Display *display, const egl::Config *config, HWND window, EGLint postSubBufferSupported); ++ Surface(Display *display, const egl::Config *config, EGLNativeWindowType window, EGLint postSubBufferSupported); + Surface(Display *display, const egl::Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget); + + ~Surface(); +@@ -43,7 +44,7 @@ class Surface + void release(); + bool resetSwapChain(); + +- HWND getWindowHandle(); ++ EGLNativeWindowType getWindowHandle(); + bool swap(); + bool postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height); + +@@ -79,7 +80,7 @@ private: + bool resetSwapChain(int backbufferWidth, int backbufferHeight); + bool swapRect(EGLint x, EGLint y, EGLint width, EGLint height); + +- const HWND mWindow; // Window that the surface is created for. ++ const EGLNativeWindowType mWindow; // Window that the surface is created for. + bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking + const egl::Config *mConfig; // EGL config surface was created with + EGLint mHeight; // Height of surface +diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp +index 6e10c39..5bcb5d5 100644 +--- a/src/3rdparty/angle/src/libEGL/libEGL.cpp ++++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp +@@ -308,14 +308,16 @@ EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EG + return EGL_NO_SURFACE; + } + ++#if !defined(ANGLE_OS_WINRT) + HWND window = (HWND)win; + + if (!IsWindow(window)) + { + return egl::error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); + } ++#endif + +- return display->createWindowSurface(window, config, attrib_list); ++ return display->createWindowSurface(win, config, attrib_list); + } + catch(std::bad_alloc&) + { +diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp +index 7dea5fc..964b4b2 100644 +--- a/src/3rdparty/angle/src/libEGL/main.cpp ++++ b/src/3rdparty/angle/src/libEGL/main.cpp +@@ -1,3 +1,4 @@ ++#include "../libGLESv2/precompiled.h" + // + // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. + // Use of this source code is governed by a BSD-style license that can be +@@ -12,7 +13,13 @@ + + #ifndef QT_OPENGL_ES_2_ANGLE_STATIC + ++#if !defined(ANGLE_OS_WINRT) + static DWORD currentTLS = TLS_OUT_OF_INDEXES; ++#else ++static __declspec(thread) void *currentTLS = 0; ++#endif ++ ++namespace egl { Current *getCurrent(); } + + extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) + { +@@ -35,22 +42,25 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved + } + #endif + ++#if !defined(ANGLE_OS_WINRT) + currentTLS = TlsAlloc(); + + if (currentTLS == TLS_OUT_OF_INDEXES) + { + return FALSE; + } ++#endif + } + // Fall throught to initialize index + case DLL_THREAD_ATTACH: + { +- egl::Current *current = (egl::Current*)LocalAlloc(LPTR, sizeof(egl::Current)); ++ egl::Current *current = egl::getCurrent(); + + if (current) + { ++#if !defined(ANGLE_OS_WINRT) + TlsSetValue(currentTLS, current); +- ++#endif + current->error = EGL_SUCCESS; + current->API = EGL_OPENGL_ES_API; + current->display = EGL_NO_DISPLAY; +@@ -61,24 +71,35 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved + break; + case DLL_THREAD_DETACH: + { +- void *current = TlsGetValue(currentTLS); ++ egl::Current *current = egl::getCurrent(); + + if (current) + { ++#if !defined(ANGLE_OS_WINRT) + LocalFree((HLOCAL)current); ++#else ++ HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, current); ++ currentTLS = 0; ++#endif + } + } + break; + case DLL_PROCESS_DETACH: + { +- void *current = TlsGetValue(currentTLS); ++ egl::Current *current = egl::getCurrent(); + + if (current) + { ++#if !defined(ANGLE_OS_WINRT) + LocalFree((HLOCAL)current); + } + + TlsFree(currentTLS); ++#else ++ HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, current); ++ currentTLS = 0; ++ } ++#endif + } + break; + default: +@@ -95,7 +116,16 @@ namespace egl + Current *getCurrent() + { + #ifndef QT_OPENGL_ES_2_ANGLE_STATIC +- return (Current*)TlsGetValue(currentTLS); ++#if !defined(ANGLE_OS_WINRT) ++ Current *current = (Current*)TlsGetValue(currentTLS); ++ if (!current) ++ current = (Current*)LocalAlloc(LPTR, sizeof(Current)); ++ return current; ++#else ++ if (!currentTLS) ++ currentTLS = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY, sizeof(Current)); ++ return (Current*)currentTLS; ++#endif + #else + // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. + static Current curr = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE }; +diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp +index 730a6ac..defdf35 100644 +--- a/src/3rdparty/angle/src/libGLESv2/main.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/main.cpp +@@ -13,7 +13,13 @@ + + #ifndef QT_OPENGL_ES_2_ANGLE_STATIC + ++#if !defined(ANGLE_OS_WINRT) + static DWORD currentTLS = TLS_OUT_OF_INDEXES; ++#else ++static __declspec(thread) void *currentTLS = 0; ++#endif ++ ++namespace gl { Current *getCurrent(); } + + extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) + { +@@ -21,22 +27,25 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved + { + case DLL_PROCESS_ATTACH: + { ++#if !defined(ANGLE_OS_WINRT) + currentTLS = TlsAlloc(); + + if (currentTLS == TLS_OUT_OF_INDEXES) + { + return FALSE; + } ++#endif + } + // Fall throught to initialize index + case DLL_THREAD_ATTACH: + { +- gl::Current *current = (gl::Current*)LocalAlloc(LPTR, sizeof(gl::Current)); ++ gl::Current *current = gl::getCurrent(); + + if (current) + { ++#if !defined(ANGLE_OS_WINRT) + TlsSetValue(currentTLS, current); +- ++#endif + current->context = NULL; + current->display = NULL; + } +@@ -44,24 +53,35 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved + break; + case DLL_THREAD_DETACH: + { +- void *current = TlsGetValue(currentTLS); ++ gl::Current *current = gl::getCurrent(); + + if (current) + { ++#if !defined(ANGLE_OS_WINRT) + LocalFree((HLOCAL)current); ++#else ++ HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, current); ++ currentTLS = 0; ++#endif + } + } + break; + case DLL_PROCESS_DETACH: + { +- void *current = TlsGetValue(currentTLS); ++ gl::Current *current = gl::getCurrent(); + + if (current) + { ++#if !defined(ANGLE_OS_WINRT) + LocalFree((HLOCAL)current); + } + + TlsFree(currentTLS); ++#else ++ HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, current); ++ currentTLS = 0; ++ } ++#endif + } + break; + default: +@@ -78,7 +98,16 @@ namespace gl + Current *getCurrent() + { + #ifndef QT_OPENGL_ES_2_ANGLE_STATIC +- return (Current*)TlsGetValue(currentTLS); ++#if !defined(ANGLE_OS_WINRT) ++ Current *current = (Current*)TlsGetValue(currentTLS); ++ if (!current) ++ current = (Current*)LocalAlloc(LPTR, sizeof(Current)); ++ return current; ++#else ++ if (!currentTLS) ++ currentTLS = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY, sizeof(Current)); ++ return (Current*)currentTLS; ++#endif + #else + // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. + static gl::Current curr = { 0, 0 }; +diff --git a/src/3rdparty/angle/src/libGLESv2/precompiled.h b/src/3rdparty/angle/src/libGLESv2/precompiled.h +index 50dec6b..823d27b 100644 +--- a/src/3rdparty/angle/src/libGLESv2/precompiled.h ++++ b/src/3rdparty/angle/src/libGLESv2/precompiled.h +@@ -32,13 +32,28 @@ + #include + #include + ++#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) ++#define ANGLE_OS_WINRT ++#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP ++#define ANGLE_OS_WINPHONE ++#endif ++#endif ++ + #ifndef ANGLE_ENABLE_D3D11 + #include + #else ++#if !defined(ANGLE_OS_WINRT) + #include ++#else ++#include ++#define Sleep(x) WaitForSingleObjectEx(GetCurrentThread(), x, FALSE) ++#define GetVersion() WINVER ++#endif + #include + #endif ++#ifndef ANGLE_OS_WINPHONE + #include ++#endif + + #ifdef _MSC_VER + #include +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp +index 21ad223..7ba183d 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp +@@ -28,13 +28,18 @@ + #define D3DERR_OUTOFVIDEOMEMORY MAKE_HRESULT(1, 0x876, 380) + #endif + +-#ifdef __MINGW32__ +- + #ifndef D3DCOMPILER_DLL ++#ifndef ANGLE_OS_WINPHONE ++#define D3DCOMPILER_DLL L"d3dcompiler_43.dll" // Lowest common denominator ++#else ++#define D3DCOMPILER_DLL L"qtd3dcompiler.dll" // Placeholder DLL for phone ++#endif // ANGLE_OS_WINPHONE ++#endif // D3DCOMPILER_DLL + +-//Add define + typedefs for older MinGW-w64 headers (pre 5783) ++#if defined(__MINGW32__) || defined(ANGLE_OS_WINPHONE) + +-#define D3DCOMPILER_DLL L"d3dcompiler_43.dll" ++//Add define + typedefs for older MinGW-w64 headers (pre 5783) ++//Also define these on Windows Phone, which doesn't have a shader compiler + + HRESULT WINAPI D3DCompile(const void *data, SIZE_T data_size, const char *filename, + const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, +@@ -43,9 +48,7 @@ typedef HRESULT (WINAPI *pD3DCompile)(const void *data, SIZE_T data_size, const + const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, + const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages); + +-#endif // D3DCOMPILER_DLL +- +-#endif // __MINGW32__ ++#endif // __MINGW32__ || ANGLE_OS_WINPHONE + + namespace rx + { +@@ -81,7 +84,11 @@ bool Renderer::initializeCompiler() + } + #else + // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. ++#if !defined(ANGLE_OS_WINRT) + mD3dCompilerModule = LoadLibrary(D3DCOMPILER_DLL); ++#else ++ mD3dCompilerModule = LoadPackagedLibrary(D3DCOMPILER_DLL, NULL); ++#endif + #endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES + + if (!mD3dCompilerModule) +@@ -225,4 +232,4 @@ void glDestroyRenderer(rx::Renderer *renderer) + delete renderer; + } + +-} +\ No newline at end of file ++} +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h +index 04e877b..ac67c27 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h +@@ -1,3 +1,4 @@ ++#include "../precompiled.h" + // + // Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. + // Use of this source code is governed by a BSD-style license that can be +@@ -13,6 +14,30 @@ + #include "libGLESv2/Uniform.h" + #include "libGLESv2/angletypes.h" + ++#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL0 ++#define D3DCOMPILE_OPTIMIZATION_LEVEL0 (1 << 14) ++#endif ++#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL1 ++#define D3DCOMPILE_OPTIMIZATION_LEVEL1 0 ++#endif ++#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL2 ++#define D3DCOMPILE_OPTIMIZATION_LEVEL2 ((1 << 14) | (1 << 15)) ++#endif ++#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL3 ++#define D3DCOMPILE_OPTIMIZATION_LEVEL3 (1 << 15) ++#endif ++#ifndef D3DCOMPILE_DEBUG ++#define D3DCOMPILE_DEBUG (1 << 0) ++#endif ++#ifndef D3DCOMPILE_SKIP_OPTIMIZATION ++#define D3DCOMPILE_SKIP_OPTIMIZATION (1 << 2) ++#endif ++#ifndef D3DCOMPILE_AVOID_FLOW_CONTROL ++#define D3DCOMPILE_AVOID_FLOW_CONTROL (1 << 9) ++#endif ++#ifndef D3DCOMPILE_PREFER_FLOW_CONTROL ++#define D3DCOMPILE_PREFER_FLOW_CONTROL (1 << 10) ++#endif + #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) + #define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 + #endif +@@ -107,7 +132,7 @@ class Renderer + + virtual void sync(bool block) = 0; + +- virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0; ++ virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0; + + virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler) = 0; + virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0; +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp +index a431018..d04467b 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp +@@ -137,6 +137,7 @@ EGLint Renderer11::initialize() + return EGL_NOT_INITIALIZED; + } + ++#if !defined(ANGLE_OS_WINRT) + mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); + mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); + +@@ -155,6 +156,7 @@ EGLint Renderer11::initialize() + ERR("Could not retrieve D3D11CreateDevice address - aborting!\n"); + return EGL_NOT_INITIALIZED; + } ++#endif + + D3D_FEATURE_LEVEL featureLevels[] = + { +@@ -203,8 +205,12 @@ EGLint Renderer11::initialize() + } + } + ++#if !defined(ANGLE_OS_WINRT) + IDXGIDevice *dxgiDevice = NULL; +- result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); ++#else ++ IDXGIDevice1 *dxgiDevice = NULL; ++#endif ++ result = mDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice)); + + if (FAILED(result)) + { +@@ -524,7 +530,7 @@ void Renderer11::sync(bool block) + } + } + +-SwapChain *Renderer11::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) ++SwapChain *Renderer11::createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) + { + return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat); + } +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h +index f024855..a7f5a39 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h +@@ -52,7 +52,7 @@ class Renderer11 : public Renderer + + virtual void sync(bool block); + +- virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); ++ virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); + + virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler); + virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture); +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h +index 14c0515..a6870eb 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h +@@ -18,7 +18,7 @@ namespace rx + class SwapChain + { + public: +- SwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) ++ SwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) + : mWindow(window), mShareHandle(shareHandle), mBackBufferFormat(backBufferFormat), mDepthBufferFormat(depthBufferFormat) + { + } +@@ -33,7 +33,7 @@ class SwapChain + virtual HANDLE getShareHandle() {return mShareHandle;}; + + protected: +- const HWND mWindow; // Window that the surface is created for. ++ const EGLNativeWindowType mWindow; // Window that the surface is created for. + const GLenum mBackBufferFormat; + const GLenum mDepthBufferFormat; + +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp +index 0da58cb..0797fd7 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp +@@ -17,7 +17,7 @@ + namespace rx + { + +-SwapChain11::SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle, ++SwapChain11::SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle, + GLenum backBufferFormat, GLenum depthBufferFormat) + : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat) + { +@@ -468,6 +468,7 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap + + if (mWindow) + { ++#if !defined(ANGLE_OS_WINRT) + // We cannot create a swap chain for an HWND that is owned by a different process + DWORD currentProcessId = GetCurrentProcessId(); + DWORD wndProcessId; +@@ -491,14 +492,34 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap + swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; + swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; ++ swapChainDesc.Windowed = TRUE; ++ swapChainDesc.OutputWindow = mWindow; ++#else ++ IDXGIFactory2 *factory; ++ HRESULT result = mRenderer->getDxgiFactory()->QueryInterface(IID_PPV_ARGS(&factory)); ++ ASSERT(SUCCEEDED(result)); ++ ++ DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; ++ swapChainDesc.BufferCount = 2; ++ swapChainDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); ++ swapChainDesc.Width = backbufferWidth; ++ swapChainDesc.Height = backbufferHeight; ++ swapChainDesc.Stereo = FALSE; ++ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; ++#endif ++ + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.Flags = 0; +- swapChainDesc.OutputWindow = mWindow; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; +- swapChainDesc.Windowed = TRUE; + +- HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain); ++#if !defined(ANGLE_OS_WINRT) ++ result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain); ++#else ++ IDXGISwapChain1 *swapChain; ++ result = factory->CreateSwapChainForCoreWindow(device, mWindow, &swapChainDesc, NULL, &swapChain); ++ mSwapChain = swapChain; ++#endif + + if (FAILED(result)) + { +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.h +index 8001046..2a030c8 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.h ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.h +@@ -19,7 +19,7 @@ class Renderer11; + class SwapChain11 : public SwapChain + { + public: +- SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle, ++ SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle, + GLenum backBufferFormat, GLenum depthBufferFormat); + virtual ~SwapChain11(); + +diff --git a/src/3rdparty/angle/src/libGLESv2/utilities.cpp b/src/3rdparty/angle/src/libGLESv2/utilities.cpp +index 32df49e..8fd193b 100644 +--- a/src/3rdparty/angle/src/libGLESv2/utilities.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/utilities.cpp +@@ -10,6 +10,14 @@ + #include "libGLESv2/utilities.h" + #include "libGLESv2/mathutil.h" + ++#if defined(ANGLE_OS_WINRT) ++#include ++#include ++#include ++#include ++using namespace ABI::Windows::Storage; ++#endif ++ + namespace gl + { + +@@ -737,7 +745,50 @@ bool IsTriangleMode(GLenum drawMode) + + std::string getTempPath() + { ++#if defined(ANGLE_OS_WINRT) ++ ++ static std::string path; ++ ++ while (path.empty()) { ++ IApplicationDataStatics *applicationDataFactory; ++ HRESULT result = RoGetActivationFactory(Microsoft::WRL::Wrappers::HStringReference(RuntimeClass_Windows_Storage_ApplicationData).Get(), ++ IID_PPV_ARGS(&applicationDataFactory)); ++ if (FAILED(result)) ++ break; ++ ++ IApplicationData *applicationData; ++ result = applicationDataFactory->get_Current(&applicationData); ++ if (FAILED(result)) ++ break; ++ ++ IStorageFolder *storageFolder; ++ result = applicationData->get_LocalFolder(&storageFolder); ++ if (FAILED(result)) ++ break; ++ ++ IStorageItem *localFolder; ++ result = storageFolder->QueryInterface(IID_PPV_ARGS(&localFolder)); ++ if (FAILED(result)) ++ break; ++ ++ HSTRING localFolderPath; ++ result = localFolder->get_Path(&localFolderPath); ++ if (FAILED(result)) ++ break; ++ ++ std::wstring_convert< std::codecvt_utf8 > converter; ++ path = converter.to_bytes(WindowsGetStringRawBuffer(localFolderPath, NULL)); ++ if (path.empty()) ++ { ++ UNREACHABLE(); ++ break; ++ } ++ } ++ ++#else ++ + char path[MAX_PATH]; ++ + DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path); + if (pathLen == 0) + { +@@ -751,6 +802,8 @@ std::string getTempPath() + UNREACHABLE(); + return std::string(); + } ++ ++#endif + + return path; + } +diff --git a/src/angle/src/common/common.pri b/src/angle/src/common/common.pri +index a94b9a6..12e26a9 100644 +--- a/src/angle/src/common/common.pri ++++ b/src/angle/src/common/common.pri +@@ -7,7 +7,7 @@ INCLUDEPATH += \ + LIBS = $$QMAKE_LIBS_CORE $$QMAKE_LIBS_GUI + + # DirectX is included in the Windows 8 Kit, but everything else requires the DX SDK. +-win32-msvc2012 { ++win32-msvc2012|winrt { + FXC = fxc.exe + } else { + DX_DIR = $$(DXSDK_DIR) +diff --git a/src/angle/src/compiler/translator_common.pro b/src/angle/src/compiler/translator_common.pro +index b281215..5581c9d 100644 +--- a/src/angle/src/compiler/translator_common.pro ++++ b/src/angle/src/compiler/translator_common.pro +@@ -78,7 +78,6 @@ SOURCES += \ + $$ANGLE_DIR/src/compiler/intermOut.cpp \ + $$ANGLE_DIR/src/compiler/IntermTraverse.cpp \ + $$ANGLE_DIR/src/compiler/MapLongVariableNames.cpp \ +- $$ANGLE_DIR/src/compiler/ossource_win.cpp \ + $$ANGLE_DIR/src/compiler/parseConst.cpp \ + $$ANGLE_DIR/src/compiler/ParseHelper.cpp \ + $$ANGLE_DIR/src/compiler/PoolAlloc.cpp \ +@@ -98,6 +97,12 @@ SOURCES += \ + $$ANGLE_DIR/src/compiler/timing/RestrictVertexShaderTiming.cpp \ + $$ANGLE_DIR/src/third_party/compiler/ArrayBoundsClamper.cpp + ++winrt { ++ SOURCES += $$ANGLE_DIR/src/compiler/ossource_winrt.cpp ++} else { ++ SOURCES += $$ANGLE_DIR/src/compiler/ossource_win.cpp ++} ++ + # NOTE: 'win_flex' and 'bison' can be found in qt5/gnuwin32/bin + flex.commands = $$addGnuPath(win_flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}_lex.cpp ${QMAKE_FILE_NAME} + flex.output = ${QMAKE_FILE_BASE}_lex.cpp +diff --git a/src/angle/src/config.pri b/src/angle/src/config.pri +index 1c6d8b0..ed25581 100644 +--- a/src/angle/src/config.pri ++++ b/src/angle/src/config.pri +@@ -37,8 +37,9 @@ DEFINES += _WINDOWS \ + NOMINMAX \ + WIN32_LEAN_AND_MEAN=1 + +-# Defines specifying the API version (0x0600 = Vista) +-DEFINES += _WIN32_WINNT=0x0600 WINVER=0x0600 ++# Defines specifying the API version (0x0600 = Vista, 0x0602 = Win8)) ++winrt: DEFINES += _WIN32_WINNT=0x0602 WINVER=0x0602 ++else: DEFINES += _WIN32_WINNT=0x0600 WINVER=0x0600 + + # ANGLE specific defines + DEFINES += ANGLE_DISABLE_TRACE \ +-- +1.8.4.msysgit.0 + diff --git a/src/angle/src/common/common.pri b/src/angle/src/common/common.pri index a94b9a6fc3..12e26a9a68 100644 --- a/src/angle/src/common/common.pri +++ b/src/angle/src/common/common.pri @@ -7,7 +7,7 @@ INCLUDEPATH += \ LIBS = $$QMAKE_LIBS_CORE $$QMAKE_LIBS_GUI # DirectX is included in the Windows 8 Kit, but everything else requires the DX SDK. -win32-msvc2012 { +win32-msvc2012|winrt { FXC = fxc.exe } else { DX_DIR = $$(DXSDK_DIR) diff --git a/src/angle/src/compiler/translator_common.pro b/src/angle/src/compiler/translator_common.pro index b2812158e1..5581c9dc58 100644 --- a/src/angle/src/compiler/translator_common.pro +++ b/src/angle/src/compiler/translator_common.pro @@ -78,7 +78,6 @@ SOURCES += \ $$ANGLE_DIR/src/compiler/intermOut.cpp \ $$ANGLE_DIR/src/compiler/IntermTraverse.cpp \ $$ANGLE_DIR/src/compiler/MapLongVariableNames.cpp \ - $$ANGLE_DIR/src/compiler/ossource_win.cpp \ $$ANGLE_DIR/src/compiler/parseConst.cpp \ $$ANGLE_DIR/src/compiler/ParseHelper.cpp \ $$ANGLE_DIR/src/compiler/PoolAlloc.cpp \ @@ -98,6 +97,12 @@ SOURCES += \ $$ANGLE_DIR/src/compiler/timing/RestrictVertexShaderTiming.cpp \ $$ANGLE_DIR/src/third_party/compiler/ArrayBoundsClamper.cpp +winrt { + SOURCES += $$ANGLE_DIR/src/compiler/ossource_winrt.cpp +} else { + SOURCES += $$ANGLE_DIR/src/compiler/ossource_win.cpp +} + # NOTE: 'win_flex' and 'bison' can be found in qt5/gnuwin32/bin flex.commands = $$addGnuPath(win_flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}_lex.cpp ${QMAKE_FILE_NAME} flex.output = ${QMAKE_FILE_BASE}_lex.cpp diff --git a/src/angle/src/config.pri b/src/angle/src/config.pri index 1c6d8b0167..ed2558117e 100644 --- a/src/angle/src/config.pri +++ b/src/angle/src/config.pri @@ -37,8 +37,9 @@ DEFINES += _WINDOWS \ NOMINMAX \ WIN32_LEAN_AND_MEAN=1 -# Defines specifying the API version (0x0600 = Vista) -DEFINES += _WIN32_WINNT=0x0600 WINVER=0x0600 +# Defines specifying the API version (0x0600 = Vista, 0x0602 = Win8)) +winrt: DEFINES += _WIN32_WINNT=0x0602 WINVER=0x0602 +else: DEFINES += _WIN32_WINNT=0x0600 WINVER=0x0600 # ANGLE specific defines DEFINES += ANGLE_DISABLE_TRACE \ From fc0f784e54d5dce72cc6a7e4b1fad243dadfcd76 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Mon, 30 Sep 2013 01:31:27 +0300 Subject: [PATCH 021/684] Windows RT and Windows Phone QPA Change-Id: I6ab8af31f73439172e43fb709831821482b1cc99 Done-with: Kamil Trzcinski Done-with: Oliver Wolff Reviewed-by: Friedemann Kleint --- mkspecs/common/winrt_winphone/qmake.conf | 7 +- src/plugins/platforms/platforms.pro | 3 +- src/plugins/platforms/winrt/blit.hlsl | 14 + src/plugins/platforms/winrt/main.cpp | 74 ++ .../platforms/winrt/qwinrtbackingstore.cpp | 393 +++++++ .../platforms/winrt/qwinrtbackingstore.h | 77 ++ src/plugins/platforms/winrt/qwinrtcursor.cpp | 153 +++ src/plugins/platforms/winrt/qwinrtcursor.h | 77 ++ .../platforms/winrt/qwinrteglcontext.cpp | 63 + .../platforms/winrt/qwinrteglcontext.h | 63 + .../platforms/winrt/qwinrteventdispatcher.cpp | 79 ++ .../platforms/winrt/qwinrteventdispatcher.h | 80 ++ .../platforms/winrt/qwinrtfontdatabase.cpp | 64 ++ .../platforms/winrt/qwinrtfontdatabase.h | 57 + .../platforms/winrt/qwinrtinputcontext.cpp | 300 +++++ .../platforms/winrt/qwinrtinputcontext.h | 121 ++ .../platforms/winrt/qwinrtintegration.cpp | 192 ++++ .../platforms/winrt/qwinrtintegration.h | 86 ++ src/plugins/platforms/winrt/qwinrtscreen.cpp | 1012 +++++++++++++++++ src/plugins/platforms/winrt/qwinrtscreen.h | 163 +++ .../platforms/winrt/qwinrtservices.cpp | 138 +++ src/plugins/platforms/winrt/qwinrtservices.h | 80 ++ src/plugins/platforms/winrt/qwinrtwindow.cpp | 119 ++ src/plugins/platforms/winrt/qwinrtwindow.h | 72 ++ src/plugins/platforms/winrt/winrt.json | 3 + src/plugins/platforms/winrt/winrt.pro | 55 + tools/configure/configureapp.cpp | 6 +- 27 files changed, 3545 insertions(+), 6 deletions(-) create mode 100644 src/plugins/platforms/winrt/blit.hlsl create mode 100644 src/plugins/platforms/winrt/main.cpp create mode 100644 src/plugins/platforms/winrt/qwinrtbackingstore.cpp create mode 100644 src/plugins/platforms/winrt/qwinrtbackingstore.h create mode 100644 src/plugins/platforms/winrt/qwinrtcursor.cpp create mode 100644 src/plugins/platforms/winrt/qwinrtcursor.h create mode 100644 src/plugins/platforms/winrt/qwinrteglcontext.cpp create mode 100644 src/plugins/platforms/winrt/qwinrteglcontext.h create mode 100644 src/plugins/platforms/winrt/qwinrteventdispatcher.cpp create mode 100644 src/plugins/platforms/winrt/qwinrteventdispatcher.h create mode 100644 src/plugins/platforms/winrt/qwinrtfontdatabase.cpp create mode 100644 src/plugins/platforms/winrt/qwinrtfontdatabase.h create mode 100644 src/plugins/platforms/winrt/qwinrtinputcontext.cpp create mode 100644 src/plugins/platforms/winrt/qwinrtinputcontext.h create mode 100644 src/plugins/platforms/winrt/qwinrtintegration.cpp create mode 100644 src/plugins/platforms/winrt/qwinrtintegration.h create mode 100644 src/plugins/platforms/winrt/qwinrtscreen.cpp create mode 100644 src/plugins/platforms/winrt/qwinrtscreen.h create mode 100644 src/plugins/platforms/winrt/qwinrtservices.cpp create mode 100644 src/plugins/platforms/winrt/qwinrtservices.h create mode 100644 src/plugins/platforms/winrt/qwinrtwindow.cpp create mode 100644 src/plugins/platforms/winrt/qwinrtwindow.h create mode 100644 src/plugins/platforms/winrt/winrt.json create mode 100644 src/plugins/platforms/winrt/winrt.pro diff --git a/mkspecs/common/winrt_winphone/qmake.conf b/mkspecs/common/winrt_winphone/qmake.conf index b5d724eef6..67831c435b 100644 --- a/mkspecs/common/winrt_winphone/qmake.conf +++ b/mkspecs/common/winrt_winphone/qmake.conf @@ -75,9 +75,12 @@ QMAKE_LFLAGS_DLL = /WINMD /MANIFEST:NO /DLL /WINMDFILE:$(DESTDIR_TARGET). QMAKE_LFLAGS_LTCG = /LTCG QMAKE_EXTENSION_STATICLIB = lib -QMAKE_LIBS_CORE += runtimeobject.lib -QMAKE_LIBS_GUI = d3d11.lib +QMAKE_LIBS += runtimeobject.lib +QMAKE_LIBS_CORE = +QMAKE_LIBS_GUI = QMAKE_LIBS_NETWORK = +QMAKE_LIBS_OPENGL_ES2 = libEGL.lib libGLESv2.lib +QMAKE_LIBS_OPENGL_ES2_DEBUG = libEGLd.lib libGLESv2d.lib QMAKE_LIBS_QT_ENTRY = -lqtmain /ENTRY:wmainCRTStartup diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro index 377ca32e64..4a7c3b279f 100644 --- a/src/plugins/platforms/platforms.pro +++ b/src/plugins/platforms/platforms.pro @@ -15,7 +15,8 @@ mac { else: SUBDIRS += cocoa } -win32: SUBDIRS += windows +win32:!winrt: SUBDIRS += windows +winrt: SUBDIRS += winrt qnx { SUBDIRS += qnx diff --git a/src/plugins/platforms/winrt/blit.hlsl b/src/plugins/platforms/winrt/blit.hlsl new file mode 100644 index 0000000000..170e7f40ca --- /dev/null +++ b/src/plugins/platforms/winrt/blit.hlsl @@ -0,0 +1,14 @@ +uniform SamplerState Sampler : register(s0); +uniform Texture2D Texture : register(t0); + +void blitvs(in float4 pos0 : TEXCOORD0, in float2 tex0 : TEXCOORD1, + out float4 gl_Position : SV_POSITION, out float2 coord : TEXCOORD0) +{ + coord = tex0; + gl_Position = pos0 * float4(1.0, -1.0, 1.0, 1.0); +} + +float4 blitps(in float4 gl_Position : SV_POSITION, in float2 coord : TEXCOORD0) : SV_TARGET0 +{ + return Texture.Sample(Sampler, coord); +} diff --git a/src/plugins/platforms/winrt/main.cpp b/src/plugins/platforms/winrt/main.cpp new file mode 100644 index 0000000000..89d560dbe3 --- /dev/null +++ b/src/plugins/platforms/winrt/main.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** 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 "qwinrtintegration.h" + +#include + +QT_BEGIN_NAMESPACE + +class QWinRTIntegrationPlugin : public QPlatformIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "winrt.json") + +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QWinRTIntegrationPlugin::keys() const +{ + return QStringList(QStringLiteral("WinRT")); +} + +QPlatformIntegration *QWinRTIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (!system.compare(QLatin1String("winrt"), Qt::CaseInsensitive)) + return QWinRTIntegration::create(); + + return 0; +} + +QT_END_NAMESPACE + +#include "main.moc" diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp new file mode 100644 index 0000000000..b219548788 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp @@ -0,0 +1,393 @@ +/**************************************************************************** +** +** 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 "qwinrtbackingstore.h" + +#include "qwinrtscreen.h" +#include "qwinrtwindow.h" +#include "qwinrteglcontext.h" +#include + +#include +#include + +#include + +// Generated shader headers +#include "blitps.h" +#include "blitvs.h" + +namespace { // Utility namespace for writing out an ANGLE-compatible binary blob + +// Must match packaged ANGLE +enum : quint32 { + AngleMajorVersion = 1, + AngleMinorVersion = 2, + AngleBuildRevision = 2446, + AngleVersion = ((AngleMajorVersion << 24) | (AngleMinorVersion << 16) | AngleBuildRevision), + AngleOptimizationLevel = (1 << 14) +}; + +struct ShaderString +{ + ShaderString(const char *data = 0) : data(data) { } + const char *data; +}; + +// ANGLE stream compatibility - when size_t is 32-bit, QDataStream::writeBytes() also works +QDataStream &operator<<(QDataStream &stream, const ShaderString &shaderString) +{ + if (!shaderString.data) + return stream << size_t(0); + + size_t len = strlen(shaderString.data); + stream << len; + stream.writeRawData(shaderString.data, int(len)); + return stream; +} + +struct Attribute +{ + Attribute(GLenum type = 0, const char *name = 0, quint32 index = 0) + : type(type), name(name), index(index) { } + GLenum type; + ShaderString name; + quint32 index; +}; + +struct Sampler +{ + enum TextureType { Texture2D, TextureCube }; + Sampler(bool active = false, GLint unit = 0, TextureType type = Texture2D) + : active(active), unit(unit), type(type) { } + bool active; + GLint unit; + TextureType type; +}; + +struct Uniform +{ + Uniform() { } + Uniform(GLenum type, quint32 precision, const char *name, quint32 arraySize, + quint32 psRegisterIndex, quint32 vsRegisterIndex, quint32 registerCount) + : type(type), precision(precision), name(name), arraySize(arraySize) + , psRegisterIndex(psRegisterIndex), vsRegisterIndex(vsRegisterIndex), registerCount(registerCount) { } + GLenum type; + quint32 precision; + ShaderString name; + quint32 arraySize; + quint32 psRegisterIndex; + quint32 vsRegisterIndex; + quint32 registerCount; +}; + +struct UniformIndex +{ + UniformIndex(const char *name = 0, quint32 element = 0, quint32 index = 0) + : name(name), element(element), index(index) { } + ShaderString name; + quint32 element; + quint32 index; +}; + +static const QByteArray createAngleBinary( + const QVector &attributes, + const QVector &textureSamplers, + const QVector &vertexSamplers, + const QVector &uniforms, + const QVector &uniformIndex, + const QByteArray &pixelShader, + const QByteArray &vertexShader, + const QByteArray &geometryShader = QByteArray(), + bool usesPointSize = false) +{ + QByteArray binary; + + QDataStream stream(&binary, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + + stream << quint32(GL_PROGRAM_BINARY_ANGLE) + << quint32(AngleVersion) + << quint32(AngleOptimizationLevel); + + // Vertex attributes + for (int i = 0; i < 16; ++i) { + if (i < attributes.size()) + stream << quint32(attributes[i].type) << attributes[i].name << attributes[i].index; + else + stream << quint32(GL_NONE) << ShaderString() << qint32(-1); + } + + // Texture units + for (int i = 0; i < 16; ++i) { + if (i < textureSamplers.size()) + stream << textureSamplers[i].active << textureSamplers[i].unit << qint32(textureSamplers[i].type); + else + stream << false << qint32(0) << qint32(Sampler::Texture2D); + } + + // Vertex texture units + for (int i = 0; i < 16; ++i) { + if (i < vertexSamplers.size()) + stream << vertexSamplers[i].active << vertexSamplers[i].unit << qint32(vertexSamplers[i].type); + else + stream << false << qint32(0) << qint32(Sampler::Texture2D); + } + + stream << vertexSamplers.size() + << textureSamplers.size() + << usesPointSize; + + stream << size_t(uniforms.size()); + foreach (const Uniform &uniform, uniforms) { + stream << uniform.type << uniform.precision << uniform.name << uniform.arraySize + << uniform.psRegisterIndex << uniform.vsRegisterIndex << uniform.registerCount; + } + + stream << size_t(uniformIndex.size()); + foreach (const UniformIndex &index, uniformIndex) + stream << index.name << index.element << index.index; + + stream << quint32(pixelShader.size()) + << quint32(vertexShader.size()) + << quint32(geometryShader.size()); + + // ANGLE requires that we query the adapter for its LUID. Later on, it may be useful + // for checking feature level support, picking the best adapter on the system, etc. + IDXGIFactory1 *dxgiFactory; + if (FAILED(CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)))) { + qCritical("QWinRTBackingStore: failed to create DXGI factory."); + return QByteArray(); + } + IDXGIAdapter *dxgiAdapter; + if (FAILED(dxgiFactory->EnumAdapters(0, &dxgiAdapter))) { + qCritical("QWinRTBackingStore:: failed to enumerate adapter."); + dxgiFactory->Release(); + return QByteArray(); + } + DXGI_ADAPTER_DESC desc; + dxgiAdapter->GetDesc(&desc); + dxgiAdapter->Release(); + QByteArray guid(sizeof(GUID), '\0'); + memcpy(guid.data(), &desc.AdapterLuid, sizeof(LUID)); + stream.writeRawData(guid.constData(), guid.size()); + stream.writeRawData(pixelShader.constData(), pixelShader.size()); + stream.writeRawData(vertexShader.constData(), vertexShader.size()); + if (!geometryShader.isEmpty()) + stream.writeRawData(geometryShader.constData(), geometryShader.size()); + + return binary; +} + +} // namespace + +QT_BEGIN_NAMESPACE + +static const GLfloat normCoords[] = { -1, 1, 1, 1, 1, -1, -1, -1 }; +static const GLfloat quadCoords[] = { 0, 0, 1, 0, 1, 1, 0, 1 }; + +QWinRTBackingStore::QWinRTBackingStore(QWindow *window) + : QPlatformBackingStore(window) + , m_context(new QOpenGLContext) + , m_shaderProgram(0) + , m_fbo(0) + , m_texture(0) + , m_screen(static_cast(window->screen()->handle())) +{ + window->setSurfaceType(QSurface::OpenGLSurface); // Required for flipping, but could be done in the swap + + m_context->setFormat(window->requestedFormat()); + m_context->setScreen(window->screen()); + m_context->create(); + + m_context->makeCurrent(window); + glGenFramebuffers(1, &m_fbo); + glGenRenderbuffers(1, &m_rbo); + glGenTextures(1, &m_texture); + m_shaderProgram = glCreateProgram(); + +#if 0 // Standard GLES passthrough shader program + static const char *vertexShaderSource = + "attribute vec4 pos0;\n" + "attribute vec2 tex0;\n" + "varying vec2 coord;\n" + "void main() {\n" + " coord = tex0;\n" + " gl_Position = pos0;\n" + "}\n"; + static const char *fragmentShaderSource = + "uniform sampler2D texture;\n" + "varying highp vec2 coord;\n" + "void main() {\n" + " gl_FragColor = texture2D(texture, coord);\n" + "}\n"; + GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); + glCompileShader(vertexShader); + GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); + glCompileShader(fragmentShader); + glAttachShader(m_shaderProgram, vertexShader); + glAttachShader(m_shaderProgram, fragmentShader); + glLinkProgram(m_shaderProgram); +#else // Precompiled passthrough shader + QVector attributes = QVector() << Attribute(GL_FLOAT_VEC4, "pos0", 0) + << Attribute(GL_FLOAT_VEC2, "tex0", 1); + QVector textureSamplers = QVector() << Sampler(true, 0, Sampler::Texture2D); + QVector vertexSamplers; + QVector uniforms = QVector() << Uniform(GL_SAMPLER_2D, 0, "texture", 0, 0, -1, 1); + QVector uniformsIndex = QVector() << UniformIndex("texture", 0, 0); + QByteArray pixelShader(reinterpret_cast(q_blitps), sizeof(q_blitps)); + QByteArray vertexShader(reinterpret_cast(q_blitvs), sizeof(q_blitvs)); + QByteArray binary = createAngleBinary(attributes, textureSamplers, vertexSamplers, + uniforms, uniformsIndex, pixelShader, vertexShader); + glProgramBinaryOES(m_shaderProgram, GL_PROGRAM_BINARY_ANGLE, binary.constData(), binary.size()); +#endif + m_context->doneCurrent(); + resize(window->size(), QRegion()); +} + +QWinRTBackingStore::~QWinRTBackingStore() +{ + glDeleteBuffers(1, &m_fbo); + glDeleteRenderbuffers(1, &m_rbo); + glDeleteTextures(1, &m_texture); + glDeleteProgram(m_shaderProgram); +} + +QPaintDevice *QWinRTBackingStore::paintDevice() +{ + return m_paintDevice.data(); +} + +void QWinRTBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(offset) + + const QImage *image = static_cast(m_paintDevice.data()); + + m_context->makeCurrent(window); + + // Blitting the entire image width trades zero image copy/relayout for a larger texture upload. + // Since we're blitting the whole width anyway, the boundingRect() is used in the assumption that + // we don't repeat upload. This is of course dependent on the distance between update regions. + // Ideally, we would use the GL_EXT_unpack_subimage extension, which should be possible to implement + // since D3D11_MAPPED_SUBRESOURCE supports RowPitch (see below). + // Note that single-line blits in a loop are *very* slow, so reducing calls to glTexSubImage2D + // is probably a good idea anyway. + glBindTexture(GL_TEXTURE_2D, m_texture); + QRect bounds = region.boundingRect(); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, bounds.y(), m_size.width(), bounds.height(), + GL_BGRA_EXT, GL_UNSIGNED_BYTE, image->scanLine(bounds.y())); + // TODO: Implement GL_EXT_unpack_subimage in ANGLE for more minimal uploads + //glPixelStorei(GL_UNPACK_ROW_LENGTH, image->bytesPerLine()); + //glTexSubImage2D(GL_TEXTURE_2D, 0, bounds.x(), bounds.y(), bounds.width(), bounds.height(), + // GL_BGRA_EXT, GL_UNSIGNED_BYTE, image->scanLine(bounds.y()) + bounds.x() * 4); + + // Bind render buffer + glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo); + + // Bind position + glUseProgram(m_shaderProgram); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, normCoords); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, quadCoords); + + // Render + glViewport(0, 0, m_size.width(), m_size.height()); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + // Unbind + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(1); + glUseProgram(0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); + + // fast blit - TODO: perform the blit inside swap buffers instead + glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, m_fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, 0); + glBlitFramebufferANGLE(0, 0, m_size.width(), m_size.height(), // TODO: blit only the changed rectangle + 0, 0, m_size.width(), m_size.height(), + GL_COLOR_BUFFER_BIT, GL_NEAREST); + + m_context->swapBuffers(window); + m_context->doneCurrent(); +} + +void QWinRTBackingStore::resize(const QSize &size, const QRegion &staticContents) +{ + Q_UNUSED(staticContents) + if (m_size == size) + return; + + m_size = size; + m_paintDevice.reset(new QImage(m_size, QImage::Format_ARGB32_Premultiplied)); + + m_context->makeCurrent(window()); + // Input texture + glBindTexture(GL_TEXTURE_2D, m_texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, m_size.width(), m_size.height(), + 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glBindTexture(GL_TEXTURE_2D, 0); + // Render buffer + glBindRenderbuffer(GL_RENDERBUFFER, m_rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_BGRA8_EXT, m_size.width(), m_size.height()); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + m_context->doneCurrent(); +} + +void QWinRTBackingStore::beginPaint(const QRegion ®ion) +{ + Q_UNUSED(region) +} + +void QWinRTBackingStore::endPaint() +{ +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.h b/src/plugins/platforms/winrt/qwinrtbackingstore.h new file mode 100644 index 0000000000..8be549b441 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtbackingstore.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINRTBACKINGSTORE_H +#define QWINRTBACKINGSTORE_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QWinRTScreen; +class QOpenGLContext; + +class QWinRTBackingStore : public QPlatformBackingStore +{ +public: + explicit QWinRTBackingStore(QWindow *window); + ~QWinRTBackingStore(); + QPaintDevice *paintDevice(); + void beginPaint(const QRegion &); + void endPaint(); + void flush(QWindow *window, const QRegion ®ion, const QPoint &offset); + void resize(const QSize &size, const QRegion &staticContents); + +private: + QSize m_size; + QScopedPointer m_paintDevice; + QScopedPointer m_context; + quint32 m_shaderProgram; + quint32 m_fbo; + quint32 m_rbo; + quint32 m_texture; + QWinRTScreen *m_screen; +}; + +QT_END_NAMESPACE + +#endif // QWINRTBACKINGSTORE_H diff --git a/src/plugins/platforms/winrt/qwinrtcursor.cpp b/src/plugins/platforms/winrt/qwinrtcursor.cpp new file mode 100644 index 0000000000..8241560cef --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtcursor.cpp @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** 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 "qwinrtcursor.h" + +#include +#include +#include +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::UI::Core; +using namespace ABI::Windows::Foundation; + +QT_BEGIN_NAMESPACE + +QWinRTCursor::QWinRTCursor(ICoreWindow *window) : m_window(window), m_cursorFactory(nullptr) +{ +#ifndef Q_OS_WINPHONE + GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Core_CoreCursor).Get(), &m_cursorFactory); +#endif +} + +QWinRTCursor::~QWinRTCursor() +{ + if (m_cursorFactory) + m_cursorFactory->Release(); +} + +#ifndef QT_NO_CURSOR +void QWinRTCursor::changeCursor(QCursor *windowCursor, QWindow *) +{ +#ifndef Q_OS_WINPHONE + if (!m_cursorFactory) + return; + + CoreCursorType type; + switch (windowCursor ? windowCursor->shape() : Qt::ArrowCursor) { + case Qt::BlankCursor: + m_window->put_PointerCursor(nullptr); + return; + default: + case Qt::OpenHandCursor: + case Qt::ClosedHandCursor: + case Qt::DragCopyCursor: + case Qt::DragMoveCursor: + case Qt::DragLinkCursor: + // (unavailable) + case Qt::ArrowCursor: + type = CoreCursorType_Arrow; + break; + case Qt::UpArrowCursor: + type = CoreCursorType_UpArrow; + break; + case Qt::CrossCursor: + type = CoreCursorType_Cross; + break; + case Qt::WaitCursor: + case Qt::BusyCursor: + type = CoreCursorType_Wait; + break; + case Qt::IBeamCursor: + type = CoreCursorType_IBeam; + break; + case Qt::SizeVerCursor: + case Qt::SplitVCursor: + type = CoreCursorType_SizeNorthSouth; + break; + case Qt::SizeHorCursor: + case Qt::SplitHCursor: + type = CoreCursorType_SizeWestEast; + break; + case Qt::SizeBDiagCursor: + type = CoreCursorType_SizeNortheastSouthwest; + break; + case Qt::SizeFDiagCursor: + type = CoreCursorType_SizeNorthwestSoutheast; + break; + case Qt::SizeAllCursor: + type = CoreCursorType_SizeAll; + break; + case Qt::PointingHandCursor: + type = CoreCursorType_Hand; + break; + case Qt::ForbiddenCursor: + type = CoreCursorType_UniversalNo; + break; + case Qt::WhatsThisCursor: + type = CoreCursorType_Help; + break; + case Qt::BitmapCursor: + case Qt::CustomCursor: + // TODO: figure out if arbitrary bitmaps can be made into resource IDs + // For now, we don't get enough info from QCursor to set a custom cursor + type = CoreCursorType_Custom; + break; + } + + ICoreCursor *cursor; + if (SUCCEEDED(m_cursorFactory->CreateCursor(type, 0, &cursor))) + m_window->put_PointerCursor(cursor); +#endif // Q_OS_WINPHONE +} +#endif // QT_NO_CURSOR + +QPoint QWinRTCursor::pos() const +{ +#ifdef Q_OS_WINPHONE + return QPlatformCursor::pos(); +#else + Point point; + m_window->get_PointerPosition(&point); + return QPoint(point.X, point.Y); +#endif +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtcursor.h b/src/plugins/platforms/winrt/qwinrtcursor.h new file mode 100644 index 0000000000..f7b301a98b --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtcursor.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINRTCURSOR_H +#define QWINRTCURSOR_H + +#include + +namespace ABI { + namespace Windows { + namespace UI { + namespace Core { + struct ICoreWindow; + struct ICoreCursorFactory; + } + } + } +} + +QT_BEGIN_NAMESPACE + +class QWinRTCursor : public QPlatformCursor +{ +public: + explicit QWinRTCursor(ABI::Windows::UI::Core::ICoreWindow *window); + ~QWinRTCursor(); +#ifndef QT_NO_CURSOR + void changeCursor(QCursor * windowCursor, QWindow *); +#endif + QPoint pos() const; + +private: + ABI::Windows::UI::Core::ICoreWindow *m_window; + ABI::Windows::UI::Core::ICoreCursorFactory *m_cursorFactory; +}; + +QT_END_NAMESPACE + +#endif // QWINRTCURSOR_H diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.cpp b/src/plugins/platforms/winrt/qwinrteglcontext.cpp new file mode 100644 index 0000000000..014378f896 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrteglcontext.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** 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 "qwinrteglcontext.h" + +QT_BEGIN_NAMESPACE + +QWinRTEGLContext::QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLSurface surface) + : QEGLPlatformContext(format, share, display, EGL_OPENGL_ES_API), m_eglSurface(surface) +{ +} + +EGLSurface QWinRTEGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface) +{ + if (surface->surface()->surfaceClass() == QSurface::Window) { + // All windows use the same surface + return m_eglSurface; + } else { + // TODO: return EGL surfaces for offscreen surfaces + qWarning("This plugin does not support offscreen surfaces."); + return EGL_NO_SURFACE; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.h b/src/plugins/platforms/winrt/qwinrteglcontext.h new file mode 100644 index 0000000000..c065847374 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrteglcontext.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSEGLCONTEXT_H +#define QWINDOWSEGLCONTEXT_H + +#include + +QT_BEGIN_NAMESPACE + +class QWinRTEGLContext : public QEGLPlatformContext +{ +public: + explicit QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLSurface surface); + +protected: + EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface); + +private: + EGLSurface m_eglSurface; +}; + +QT_END_NAMESPACE + +#endif // QWINDOWSEGLCONTEXT_H diff --git a/src/plugins/platforms/winrt/qwinrteventdispatcher.cpp b/src/plugins/platforms/winrt/qwinrteventdispatcher.cpp new file mode 100644 index 0000000000..3fada75b25 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrteventdispatcher.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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 "qwinrteventdispatcher.h" +#include +#include +#include +#include +#include + +#include +#include + +using namespace ABI::Windows::ApplicationModel::Core; +using namespace ABI::Windows::UI::Core; +using namespace ABI::Windows::Foundation; + +QT_BEGIN_NAMESPACE + +QWinRTEventDispatcher::QWinRTEventDispatcher(ICoreDispatcher *dispatcher, QObject *parent) + : QEventDispatcherWinRT(parent) + , m_dispatcher(dispatcher) +{ +} + +bool QWinRTEventDispatcher::hasPendingEvents() +{ + return QEventDispatcherWinRT::hasPendingEvents() || QWindowSystemInterface::windowSystemEventsQueued(); +} + +bool QWinRTEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) +{ + if (m_dispatcher) + m_dispatcher->ProcessEvents(CoreProcessEventsOption_ProcessAllIfPresent); + + const bool didProcess = QWindowSystemInterface::sendWindowSystemEvents(flags); + + return QEventDispatcherWinRT::processEvents(flags & ~QEventLoop::WaitForMoreEvents) || didProcess; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrteventdispatcher.h b/src/plugins/platforms/winrt/qwinrteventdispatcher.h new file mode 100644 index 0000000000..275a508b3c --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrteventdispatcher.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINRTEVENTDISPATCHER_H +#define QWINRTEVENTDISPATCHER_H + +#include +#include + +#include + +namespace ABI { + namespace Windows { + namespace UI { + namespace Core { + struct ICoreDispatcher; + } + } + } +} + +QT_BEGIN_NAMESPACE + +class QWinRTEventDispatcher : public QEventDispatcherWinRT +{ + Q_OBJECT +public: + explicit QWinRTEventDispatcher(ABI::Windows::UI::Core::ICoreDispatcher *dispatcher, QObject *parent = 0); + +protected: + bool hasPendingEvents(); + bool processEvents(QEventLoop::ProcessEventsFlags flags); + +private: + ABI::Windows::UI::Core::ICoreDispatcher *m_dispatcher; + + friend class QWinRTIntegration; +}; + +QT_END_NAMESPACE + +#endif // QWINRTEVENTDISPATCHER_H diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp new file mode 100644 index 0000000000..c7fa339fad --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** 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 "qwinrtfontdatabase.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QString QWinRTFontDatabase::fontDir() const +{ + QString fontDirectory = QBasicFontDatabase::fontDir(); + if (!QFile::exists(fontDirectory)) { + // Fall back to app directory + fonts, and just app directory after that + const QString applicationDirPath = QCoreApplication::applicationDirPath(); + fontDirectory = applicationDirPath + QLatin1String("/fonts"); + if (!QFile::exists(fontDirectory)) { + qWarning("No fonts directory found in application package."); + fontDirectory = applicationDirPath; + } + } + return fontDirectory; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.h b/src/plugins/platforms/winrt/qwinrtfontdatabase.h new file mode 100644 index 0000000000..49e32470c2 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINRTFONTDATABASE_H +#define QWINRTFONTDATABASE_H + +#include + +QT_BEGIN_NAMESPACE + +class QWinRTFontDatabase : public QBasicFontDatabase +{ +public: + QString fontDir() const; +}; + +QT_END_NAMESPACE + +#endif // QWINRTFONTDATABASE_H diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp new file mode 100644 index 0000000000..bc15f1e448 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp @@ -0,0 +1,300 @@ +/**************************************************************************** +** +** 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 "qwinrtinputcontext.h" +#include + +#include +#include +#include +#include +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::UI::ViewManagement; +using namespace ABI::Windows::UI::Core; + +#ifdef Q_OS_WINPHONE +#include +using namespace ABI::Windows::Phone::UI::Core; +#endif + +typedef ITypedEventHandler InputPaneVisibilityHandler; + +QT_BEGIN_NAMESPACE + +/*! + \class QWinRTInputContext + \brief Manages Input Method visibility + \internal + \ingroup qt-qpa-winrt + + Listens to the native virtual keyboard for hide/show events and provides + hints to the OS for showing/hiding. On WinRT, showInputPanel()/hideInputPanel() + have no effect because WinRT dictates that keyboard presence is user-driven: + (http://msdn.microsoft.com/en-us/library/windows/apps/hh465404.aspx) + Windows Phone, however, supports direct hiding/showing of the keyboard. +*/ + +QWinRTInputContext::QWinRTInputContext(ICoreWindow *window) + : m_window(window) +{ + IInputPaneStatics *statics; + if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_InputPane).Get(), + &statics))) { + qWarning(Q_FUNC_INFO ": failed to retrieve input pane statics."); + return; + } + + IInputPane *inputPane; + statics->GetForCurrentView(&inputPane); + statics->Release(); + if (inputPane) { + EventRegistrationToken showToken, hideToken; + inputPane->add_Showing(Callback( + this, &QWinRTInputContext::onShowing).Get(), &showToken); + inputPane->add_Hiding(Callback( + this, &QWinRTInputContext::onHiding).Get(), &hideToken); + + Rect rect; + inputPane->get_OccludedRect(&rect); + m_keyboardRect = QRectF(rect.X, rect.Y, rect.Width, rect.Height); + m_isInputPanelVisible = !m_keyboardRect.isEmpty(); + } else { + qWarning(Q_FUNC_INFO ": failed to retrieve InputPane."); + } +} + +QRectF QWinRTInputContext::keyboardRect() const +{ + return m_keyboardRect; +} + +bool QWinRTInputContext::isInputPanelVisible() const +{ + return m_isInputPanelVisible; +} + +HRESULT QWinRTInputContext::onShowing(IInputPane *pane, IInputPaneVisibilityEventArgs *) +{ + m_isInputPanelVisible = true; + emitInputPanelVisibleChanged(); + + Rect rect; + pane->get_OccludedRect(&rect); + setKeyboardRect(QRectF(rect.X, rect.Y, rect.Width, rect.Height)); + + return S_OK; +} + +HRESULT QWinRTInputContext::onHiding(IInputPane *pane, IInputPaneVisibilityEventArgs *) +{ + m_isInputPanelVisible = false; + emitInputPanelVisibleChanged(); + + Rect rect; + pane->get_OccludedRect(&rect); + setKeyboardRect(QRectF(rect.X, rect.Y, rect.Width, rect.Height)); + + return S_OK; +} + +void QWinRTInputContext::setKeyboardRect(const QRectF rect) +{ + if (m_keyboardRect == rect) + return; + + m_keyboardRect = rect; + emitKeyboardRectChanged(); +} + +#ifdef Q_OS_WINPHONE + +void QWinRTInputContext::showInputPanel() +{ + ICoreWindowKeyboardInput *input; + if (SUCCEEDED(m_window->QueryInterface(IID_PPV_ARGS(&input)))) { + input->put_IsKeyboardInputEnabled(true); + input->Release(); + } +} + +void QWinRTInputContext::hideInputPanel() +{ + ICoreWindowKeyboardInput *input; + if (SUCCEEDED(m_window->QueryInterface(IID_PPV_ARGS(&input)))) { + input->put_IsKeyboardInputEnabled(false); + input->Release(); + } +} + +#else // Q_OS_WINPHONE + +// IRawElementProviderSimple +HRESULT QWinRTInputContext::get_ProviderOptions(ProviderOptions *retVal) +{ + *retVal = ProviderOptions_ServerSideProvider|ProviderOptions_UseComThreading; + return S_OK; +} + +HRESULT QWinRTInputContext::GetPatternProvider(PATTERNID id, IUnknown **retVal) +{ + switch (id) { + case 10002: //UIA_ValuePatternId + return QueryInterface(__uuidof(IValueProvider), (void**)retVal); + break; + case 10014: //UIA_TextPatternId: + return QueryInterface(__uuidof(ITextProvider), (void**)retVal); + case 10029: //UIA_TextChildPatternId: + *retVal = nullptr; + break; + default: + qWarning("Unhandled pattern ID: %d", id); + break; + } + return S_OK; +} + +HRESULT QWinRTInputContext::GetPropertyValue(PROPERTYID idProp, VARIANT *retVal) +{ + switch (idProp) { + case 30003: //UIA_ControlTypePropertyId + retVal->vt = VT_I4; + retVal->lVal = 50025; //UIA_CustomControlTypeId + break; + case 30008: //UIA_IsKeyboardFocusablePropertyId + case 30009: //UIA_HasKeyboardFocusPropertyId + // These are probably never actually called + case 30016: //UIA_IsControlElementPropertyId + case 30017: //UIA_IsContentElementPropertyId + retVal->vt = VT_BOOL; + retVal->boolVal = VARIANT_TRUE; + break; + case 30019: //UIA_IsPasswordPropertyId + retVal->vt = VT_BOOL; + retVal->boolVal = VARIANT_FALSE; + break; + case 30020: //UIA_NativeWindowHandlePropertyId + retVal->vt = VT_PTR; + retVal->punkVal = m_window; + break; + } + return S_OK; +} + +HRESULT QWinRTInputContext::get_HostRawElementProvider(IRawElementProviderSimple **retVal) +{ + // Return the window's element provider + IInspectable *hostProvider; + HRESULT hr = m_window->get_AutomationHostProvider(&hostProvider); + if (SUCCEEDED(hr)) { + hr = hostProvider->QueryInterface(IID_PPV_ARGS(retVal)); + hostProvider->Release(); + } + return hr; +} + +// ITextProvider +HRESULT QWinRTInputContext::GetSelection(SAFEARRAY **) +{ + // To be useful, requires listening to the focus object for a selection change and raising an event + return S_OK; +} + +HRESULT QWinRTInputContext::GetVisibleRanges(SAFEARRAY **) +{ + // To be useful, requires listening to the focus object for a selection change and raising an event + return S_OK; +} + +HRESULT QWinRTInputContext::RangeFromChild(IRawElementProviderSimple *,ITextRangeProvider **) +{ + // To be useful, requires listening to the focus object for a selection change and raising an event + return S_OK; +} + +HRESULT QWinRTInputContext::RangeFromPoint(UiaPoint, ITextRangeProvider **) +{ + // To be useful, requires listening to the focus object for a selection change and raising an event + return S_OK; +} + +HRESULT QWinRTInputContext::get_DocumentRange(ITextRangeProvider **) +{ + // To be useful, requires listening to the focus object for a selection change and raising an event + return S_OK; +} + +HRESULT QWinRTInputContext::get_SupportedTextSelection(SupportedTextSelection *) +{ + // To be useful, requires listening to the focus object for a selection change and raising an event + return S_OK; +} + +// IValueProvider +HRESULT QWinRTInputContext::SetValue(LPCWSTR) +{ + // To be useful, requires listening to the focus object for a value change and raising an event + // May be useful for inputPanel autocomplete, etc. + return S_OK; +} + +HRESULT QWinRTInputContext::get_Value(BSTR *) +{ + // To be useful, requires listening to the focus object for a value change and raising an event + // May be useful for inputPanel autocomplete, etc. + return S_OK; +} + +HRESULT QWinRTInputContext::get_IsReadOnly(BOOL *isReadOnly) +{ + // isReadOnly dictates keyboard opening behavior when view is tapped. + // We need to decide if the user tapped within a control which is about to receive focus... + // Since this isn't possible (this function gets called before we receive the touch event), + // the most platform-aligned option is to show the keyboard if an editable item has focus, + // and close the keyboard if it is already open. + *isReadOnly = m_isInputPanelVisible || !inputMethodAccepted(); + return S_OK; +} + +#endif // !Q_OS_WINPHONE + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.h b/src/plugins/platforms/winrt/qwinrtinputcontext.h new file mode 100644 index 0000000000..0a35f9b6e1 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtinputcontext.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINRTINPUTCONTEXT_H +#define QWINRTINPUTCONTEXT_H + +#include +#include + +#include +#ifndef Q_OS_WINPHONE +# include +#endif + +namespace ABI { + namespace Windows { + namespace UI { + namespace Core { + struct ICoreWindow; + } + namespace ViewManagement { + struct IInputPane; + struct IInputPaneVisibilityEventArgs; + } + } + } +} + +QT_BEGIN_NAMESPACE + +class QWinRTInputContext : public QPlatformInputContext +#ifndef Q_OS_WINPHONE + , public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags, + IRawElementProviderSimple, ITextProvider, IValueProvider> +#endif // !Q_OS_WINPHONE +{ +public: + explicit QWinRTInputContext(ABI::Windows::UI::Core::ICoreWindow *window); + + QRectF keyboardRect() const; + + bool isInputPanelVisible() const; + +#ifdef Q_OS_WINPHONE + void showInputPanel(); + void hideInputPanel(); +#else // Q_OS_WINPHONE + // IRawElementProviderSimple + HRESULT __stdcall get_ProviderOptions(ProviderOptions *retVal); + HRESULT __stdcall GetPatternProvider(PATTERNID, IUnknown **); + HRESULT __stdcall GetPropertyValue(PROPERTYID idProp, VARIANT *retVal); + HRESULT __stdcall get_HostRawElementProvider(IRawElementProviderSimple **retVal); + + // ITextProvider + HRESULT __stdcall GetSelection(SAFEARRAY **); + HRESULT __stdcall GetVisibleRanges(SAFEARRAY **); + HRESULT __stdcall RangeFromChild(IRawElementProviderSimple *,ITextRangeProvider **); + HRESULT __stdcall RangeFromPoint(UiaPoint, ITextRangeProvider **); + HRESULT __stdcall get_DocumentRange(ITextRangeProvider **); + HRESULT __stdcall get_SupportedTextSelection(SupportedTextSelection *); + + // IValueProvider + HRESULT __stdcall SetValue(LPCWSTR); + HRESULT __stdcall get_Value(BSTR *); + HRESULT __stdcall get_IsReadOnly(BOOL *); +#endif // !Q_OS_WINPHONE + +private: + HRESULT onShowing(ABI::Windows::UI::ViewManagement::IInputPane *, + ABI::Windows::UI::ViewManagement::IInputPaneVisibilityEventArgs *); + HRESULT onHiding(ABI::Windows::UI::ViewManagement::IInputPane *, + ABI::Windows::UI::ViewManagement::IInputPaneVisibilityEventArgs *); + void setKeyboardRect(const QRectF rect); + + ABI::Windows::UI::Core::ICoreWindow *m_window; + QRectF m_keyboardRect; + bool m_isInputPanelVisible; +}; + +QT_END_NAMESPACE + +#endif // QWINRTINPUTCONTEXT_H diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp new file mode 100644 index 0000000000..9113ffeb19 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp @@ -0,0 +1,192 @@ +/**************************************************************************** +** +** 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 "qwinrtintegration.h" +#include "qwinrtwindow.h" +#include "qwinrteventdispatcher.h" +#include "qwinrtbackingstore.h" +#include "qwinrtscreen.h" +#include "qwinrtinputcontext.h" +#include "qwinrtservices.h" +#include "qwinrteglcontext.h" +#include "qwinrtfontdatabase.h" + +#include + +#include +#include +#include +#include + +using namespace Microsoft::WRL; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::UI::Core; +using namespace ABI::Windows::UI::ViewManagement; +using namespace ABI::Windows::ApplicationModel::Core; + +static IUISettings *getSettings() +{ + static IUISettings *settings = 0; + if (!settings) { + if (FAILED(RoActivateInstance(Wrappers::HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_UISettings).Get(), + reinterpret_cast(&settings)))) { + qWarning("Could not activate UISettings."); + } + } + return settings; +} + +QT_BEGIN_NAMESPACE + +QWinRTIntegration::QWinRTIntegration() + : m_success(false) + , m_fontDatabase(new QWinRTFontDatabase) + , m_services(new QWinRTServices) +{ + // Obtain the WinRT Application, view, and window + ICoreApplication *application; + if (FAILED(RoGetActivationFactory(Wrappers::HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(), + IID_PPV_ARGS(&application)))) + qCritical("Could not attach to the application factory."); + + ICoreApplicationView *view; + if (FAILED(application->GetCurrentView(&view))) { + qCritical("Could not obtain the application view - have you started outside of WinRT?"); + return; + } + + // Get core window (will act as our screen) + ICoreWindow *window; + if (FAILED(view->get_CoreWindow(&window))) { + qCritical("Could not obtain the application window - have you started outside of WinRT?"); + return; + } + window->Activate(); + m_screen = new QWinRTScreen(window); + screenAdded(m_screen); + + // Get event dispatcher + ICoreDispatcher *dispatcher; + if (FAILED(window->get_Dispatcher(&dispatcher))) + qCritical("Could not capture UI Dispatcher"); + m_eventDispatcher = new QWinRTEventDispatcher(dispatcher); + + m_success = true; +} + +QWinRTIntegration::~QWinRTIntegration() +{ + Windows::Foundation::Uninitialize(); +} + +QAbstractEventDispatcher *QWinRTIntegration::guiThreadEventDispatcher() const +{ + return m_eventDispatcher; +} + +bool QWinRTIntegration::hasCapability(QPlatformIntegration::Capability cap) const +{ + switch (cap) { + case ThreadedPixmaps: + case OpenGL: + case ApplicationState: + return true; + default: + return QPlatformIntegration::hasCapability(cap); + } +} + +QVariant QWinRTIntegration::styleHint(StyleHint hint) const +{ + switch (hint) { + case CursorFlashTime: + if (IUISettings *settings = getSettings()) { + quint32 blinkRate; + settings->get_CaretBlinkRate(&blinkRate); + return blinkRate; + } + break; + case MouseDoubleClickInterval: + if (IUISettings *settings = getSettings()) { + quint32 doubleClickTime; + settings->get_DoubleClickTime(&doubleClickTime); + return doubleClickTime; + } + case ShowIsFullScreen: + return true; + default: + break; + } + return QPlatformIntegration::styleHint(hint); +} + +QPlatformWindow *QWinRTIntegration::createPlatformWindow(QWindow *window) const +{ + return new QWinRTWindow(window); +} + +QPlatformBackingStore *QWinRTIntegration::createPlatformBackingStore(QWindow *window) const +{ + return new QWinRTBackingStore(window); +} + +QPlatformOpenGLContext *QWinRTIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const +{ + QWinRTScreen *screen = static_cast(context->screen()->handle()); + return new QWinRTEGLContext(context->format(), context->handle(), screen->eglDisplay(), screen->eglSurface()); +} + +QPlatformFontDatabase *QWinRTIntegration::fontDatabase() const +{ + return m_fontDatabase; +} + +QPlatformInputContext *QWinRTIntegration::inputContext() const +{ + return m_screen->inputContext(); +} + +QPlatformServices *QWinRTIntegration::services() const +{ + return m_services; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtintegration.h b/src/plugins/platforms/winrt/qwinrtintegration.h new file mode 100644 index 0000000000..b53c1cf7d2 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtintegration.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINRTINTEGRATION_H +#define QWINRTINTEGRATION_H + +#include + +QT_BEGIN_NAMESPACE + +class QAbstractEventDispatcher; +class QWinRTScreen; + +class QWinRTIntegration : public QPlatformIntegration +{ +private: + explicit QWinRTIntegration(); +public: + ~QWinRTIntegration(); + + static QWinRTIntegration *create() + { + QWinRTIntegration *integration = new QWinRTIntegration; + return integration->m_success ? integration : 0; + } + + bool hasCapability(QPlatformIntegration::Capability cap) const; + QVariant styleHint(StyleHint hint) const; + + QPlatformWindow *createPlatformWindow(QWindow *window) const; + QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const; + QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const; + QAbstractEventDispatcher *guiThreadEventDispatcher() const; + QPlatformFontDatabase *fontDatabase() const; + QPlatformInputContext *inputContext() const; + QPlatformServices *services() const; + +private: + bool m_success; + QWinRTScreen *m_screen; + QAbstractEventDispatcher *m_eventDispatcher; + QPlatformFontDatabase *m_fontDatabase; + QPlatformServices *m_services; +}; + +QT_END_NAMESPACE + +#endif // QWINRTINTEGRATION_H diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp new file mode 100644 index 0000000000..93c2736238 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -0,0 +1,1012 @@ +/**************************************************************************** +** +** 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 "qwinrtscreen.h" + +#include "qwinrtbackingstore.h" +#include "qwinrtinputcontext.h" +#include "qwinrtcursor.h" +#include "qwinrteglcontext.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::System; +using namespace ABI::Windows::UI::Core; +using namespace ABI::Windows::UI::Input; +using namespace ABI::Windows::UI::ViewManagement; +using namespace ABI::Windows::Devices::Input; +using namespace ABI::Windows::Graphics::Display; + +typedef ITypedEventHandler ActivatedHandler; +typedef ITypedEventHandler ClosedHandler; +typedef ITypedEventHandler CharacterReceivedHandler; +typedef ITypedEventHandler InputEnabledHandler; +typedef ITypedEventHandler KeyHandler; +typedef ITypedEventHandler PointerHandler; +typedef ITypedEventHandler SizeChangedHandler; +typedef ITypedEventHandler VisibilityChangedHandler; +typedef ITypedEventHandler AutomationProviderRequestedHandler; + +QT_BEGIN_NAMESPACE + +static inline Qt::ScreenOrientation qOrientationFromNative(DisplayOrientations orientation) +{ + switch (orientation) { + default: + case DisplayOrientations_None: + return Qt::PrimaryOrientation; + case DisplayOrientations_Landscape: + return Qt::LandscapeOrientation; + case DisplayOrientations_LandscapeFlipped: + return Qt::InvertedLandscapeOrientation; + case DisplayOrientations_Portrait: + return Qt::PortraitOrientation; + case DisplayOrientations_PortraitFlipped: + return Qt::InvertedPortraitOrientation; + } +} + +static inline Qt::KeyboardModifiers qKeyModifiers(ICoreWindow *window) +{ + Qt::KeyboardModifiers mods; + CoreVirtualKeyStates mod; + window->GetAsyncKeyState(VirtualKey_Shift, &mod); + if (mod == CoreVirtualKeyStates_Down) + mods |= Qt::ShiftModifier; + window->GetAsyncKeyState(VirtualKey_Menu, &mod); + if (mod == CoreVirtualKeyStates_Down) + mods |= Qt::AltModifier; + window->GetAsyncKeyState(VirtualKey_Control, &mod); + if (mod == CoreVirtualKeyStates_Down) + mods |= Qt::ControlModifier; + window->GetAsyncKeyState(VirtualKey_LeftWindows, &mod); + if (mod == CoreVirtualKeyStates_Down) { + mods |= Qt::MetaModifier; + } else { + window->GetAsyncKeyState(VirtualKey_RightWindows, &mod); + if (mod == CoreVirtualKeyStates_Down) + mods |= Qt::MetaModifier; + } + return mods; +} + +// Return Qt meta key from VirtualKey (discard character keys) +static inline Qt::Key qMetaKeyFromVirtual(VirtualKey key) +{ + switch (key) { + + default: + return Qt::Key_unknown; + + // Modifiers + case VirtualKey_Shift: + case VirtualKey_LeftShift: + case VirtualKey_RightShift: + return Qt::Key_Shift; + case VirtualKey_Control: + case VirtualKey_LeftControl: + case VirtualKey_RightControl: + return Qt::Key_Control; + case VirtualKey_Menu: + case VirtualKey_LeftMenu: + case VirtualKey_RightMenu: + return Qt::Key_Alt; + case VirtualKey_LeftWindows: + case VirtualKey_RightWindows: + return Qt::Key_Meta; + + // Toggle keys + case VirtualKey_CapitalLock: + return Qt::Key_CapsLock; + case VirtualKey_NumberKeyLock: + return Qt::Key_NumLock; + case VirtualKey_Scroll: + return Qt::Key_ScrollLock; + + // East-Asian language keys + case VirtualKey_Kana: + //case VirtualKey_Hangul: // Same enum as Kana + return Qt::Key_Kana_Shift; + case VirtualKey_Junja: + return Qt::Key_Hangul_Jeonja; + case VirtualKey_Kanji: + //case VirtualKey_Hanja: // Same enum as Kanji + return Qt::Key_Kanji; + case VirtualKey_ModeChange: + return Qt::Key_Mode_switch; + case VirtualKey_Convert: + return Qt::Key_Henkan; + case VirtualKey_NonConvert: + return Qt::Key_Muhenkan; + + // Misc. keys + case VirtualKey_Cancel: + return Qt::Key_Cancel; + case VirtualKey_Back: + return Qt::Key_Back; + case VirtualKey_Clear: + return Qt::Key_Clear; + case VirtualKey_Application: + return Qt::Key_ApplicationLeft; + case VirtualKey_Sleep: + return Qt::Key_Sleep; + case VirtualKey_Pause: + return Qt::Key_Pause; + case VirtualKey_Space: + return Qt::Key_Space; + case VirtualKey_PageUp: + return Qt::Key_PageUp; + case VirtualKey_PageDown: + return Qt::Key_PageDown; + case VirtualKey_End: + return Qt::Key_End; + case VirtualKey_Home: + return Qt::Key_Home; + case VirtualKey_Left: + return Qt::Key_Left; + case VirtualKey_Up: + return Qt::Key_Up; + case VirtualKey_Right: + return Qt::Key_Right; + case VirtualKey_Down: + return Qt::Key_Down; + case VirtualKey_Select: + return Qt::Key_Select; + case VirtualKey_Print: + return Qt::Key_Print; + case VirtualKey_Execute: + return Qt::Key_Execute; + case VirtualKey_Insert: + return Qt::Key_Insert; + case VirtualKey_Delete: + return Qt::Key_Delete; + case VirtualKey_Help: + return Qt::Key_Help; + case VirtualKey_Snapshot: + return Qt::Key_Camera; + case VirtualKey_Escape: + return Qt::Key_Escape; + + // Function Keys + case VirtualKey_F1: + return Qt::Key_F1; + case VirtualKey_F2: + return Qt::Key_F2; + case VirtualKey_F3: + return Qt::Key_F3; + case VirtualKey_F4: + return Qt::Key_F4; + case VirtualKey_F5: + return Qt::Key_F5; + case VirtualKey_F6: + return Qt::Key_F6; + case VirtualKey_F7: + return Qt::Key_F7; + case VirtualKey_F8: + return Qt::Key_F8; + case VirtualKey_F9: + return Qt::Key_F9; + case VirtualKey_F10: + return Qt::Key_F10; + case VirtualKey_F11: + return Qt::Key_F11; + case VirtualKey_F12: + return Qt::Key_F12; + case VirtualKey_F13: + return Qt::Key_F13; + case VirtualKey_F14: + return Qt::Key_F14; + case VirtualKey_F15: + return Qt::Key_F15; + case VirtualKey_F16: + return Qt::Key_F16; + case VirtualKey_F17: + return Qt::Key_F17; + case VirtualKey_F18: + return Qt::Key_F18; + case VirtualKey_F19: + return Qt::Key_F19; + case VirtualKey_F20: + return Qt::Key_F20; + case VirtualKey_F21: + return Qt::Key_F21; + case VirtualKey_F22: + return Qt::Key_F22; + case VirtualKey_F23: + return Qt::Key_F23; + case VirtualKey_F24: + return Qt::Key_F24; + + /* Character keys - pass through. + case VirtualKey_Enter: + case VirtualKey_Tab: + case VirtualKey_Number0: + case VirtualKey_Number1: + case VirtualKey_Number2: + case VirtualKey_Number3: + case VirtualKey_Number4: + case VirtualKey_Number5: + case VirtualKey_Number6: + case VirtualKey_Number7: + case VirtualKey_Number8: + case VirtualKey_Number9: + case VirtualKey_A: + case VirtualKey_B: + case VirtualKey_C: + case VirtualKey_D: + case VirtualKey_E: + case VirtualKey_F: + case VirtualKey_G: + case VirtualKey_H: + case VirtualKey_I: + case VirtualKey_J: + case VirtualKey_K: + case VirtualKey_L: + case VirtualKey_M: + case VirtualKey_N: + case VirtualKey_O: + case VirtualKey_P: + case VirtualKey_Q: + case VirtualKey_R: + case VirtualKey_S: + case VirtualKey_T: + case VirtualKey_U: + case VirtualKey_V: + case VirtualKey_W: + case VirtualKey_X: + case VirtualKey_Y: + case VirtualKey_Z: + case VirtualKey_Multiply: + case VirtualKey_Add: + case VirtualKey_Separator: + case VirtualKey_Subtract: + case VirtualKey_Decimal: + case VirtualKey_Divide:*/ + + /* NumberPad keys. No special Alt handling is needed, as WinRT doesn't send events if Alt is pressed. + case VirtualKey_NumberPad0: + case VirtualKey_NumberPad1: + case VirtualKey_NumberPad2: + case VirtualKey_NumberPad3: + case VirtualKey_NumberPad4: + case VirtualKey_NumberPad5: + case VirtualKey_NumberPad6: + case VirtualKey_NumberPad7: + case VirtualKey_NumberPad8: + case VirtualKey_NumberPad9:*/ + + /* Keys with no matching Qt enum (?) + case VirtualKey_None: + case VirtualKey_LeftButton: + case VirtualKey_RightButton: + case VirtualKey_MiddleButton: + case VirtualKey_XButton1: + case VirtualKey_XButton2: + case VirtualKey_Final: + case VirtualKey_Accept:*/ + } +} + +// Map Qt keys from char +static inline Qt::Key qKeyFromChar(quint32 code, Qt::KeyboardModifiers mods = Qt::NoModifier) +{ + switch (code) { + case 0x1: + case 'a': + case 'A': + return Qt::Key_A; + case 0x2: + case 'b': + case 'B': + return Qt::Key_B; + case 0x3: + case 'c': + case 'C': + return Qt::Key_C; + case 0x4: + case 'd': + case 'D': + return Qt::Key_D; + case 0x5: + case 'e': + case 'E': + return Qt::Key_E; + case 0x6: + case 'f': + case 'F': + return Qt::Key_F; + case 0x7: + case 'g': + case 'G': + return Qt::Key_G; + case 0x8: + //case '\b': + return mods & Qt::ControlModifier ? Qt::Key_H : Qt::Key_Backspace; + case 'h': + case 'H': + return Qt::Key_H; + case 0x9: + //case '\t': + return mods & Qt::ControlModifier ? Qt::Key_I : Qt::Key_Tab; + case 'i': + case 'I': + return Qt::Key_I; + case 0xa: + //case '\n': + return mods & Qt::ControlModifier ? Qt::Key_J : Qt::Key_Enter; + case 'j': + case 'J': + return Qt::Key_J; + case 0xb: + case 'k': + case 'K': + return Qt::Key_K; + case 0xc: + case 'l': + case 'L': + return Qt::Key_L; + case 0xd: + case 'm': + case 'M': + return Qt::Key_M; + case 0xe: + case 'n': + case 'N': + return Qt::Key_N; + case 0xf: + case 'o': + case 'O': + return Qt::Key_O; + case 0x10: + case 'p': + case 'P': + return Qt::Key_P; + case 0x11: + case 'q': + case 'Q': + return Qt::Key_Q; + case 0x12: + case 'r': + case 'R': + return Qt::Key_R; + case 0x13: + case 's': + case 'S': + return Qt::Key_S; + case 0x14: + case 't': + case 'T': + return Qt::Key_T; + case 0x15: + case 'u': + case 'U': + return Qt::Key_U; + case 0x16: + case 'v': + case 'V': + return Qt::Key_V; + case 0x17: + case 'w': + case 'W': + return Qt::Key_W; + case 0x18: + case 'x': + case 'X': + return Qt::Key_X; + case 0x19: + case 'y': + case 'Y': + return Qt::Key_Y; + case 0x1A: + case 'z': + case 'Z': + return Qt::Key_Z; + } + return Qt::Key_unknown; +} + +QWinRTScreen::QWinRTScreen(ICoreWindow *window) + : m_coreWindow(window) + , m_depth(32) + , m_format(QImage::Format_ARGB32_Premultiplied) +#ifdef Q_OS_WINPHONE + , m_inputContext(new QWinRTInputContext(m_coreWindow)) +#else + , m_inputContext(Make(m_coreWindow).Detach()) +#endif + , m_cursor(new QWinRTCursor(window)) + , m_orientation(Qt::PrimaryOrientation) +{ +#ifdef Q_OS_WINPHONE // On phone, there can be only one touch device + QTouchDevice *touchDevice = new QTouchDevice; + touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure); + touchDevice->setType(QTouchDevice::TouchScreen); + touchDevice->setName(QStringLiteral("WinPhoneTouchScreen")); + Pointer pointer = { Pointer::TouchScreen, touchDevice }; + m_pointers.insert(0, pointer); + QWindowSystemInterface::registerTouchDevice(touchDevice); +#endif + + Rect rect; + window->get_Bounds(&rect); + m_geometry = QRect(0, 0, rect.Width, rect.Height); + + m_surfaceFormat.setAlphaBufferSize(0); + m_surfaceFormat.setRedBufferSize(8); + m_surfaceFormat.setGreenBufferSize(8); + m_surfaceFormat.setBlueBufferSize(8); + + m_surfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES); + m_surfaceFormat.setSamples(1); + m_surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer); + m_surfaceFormat.setDepthBufferSize(24); + m_surfaceFormat.setStencilBufferSize(8); + + m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (m_eglDisplay == EGL_NO_DISPLAY) + qFatal("Qt WinRT platform plugin: failed to initialize EGL display."); + + if (!eglInitialize(m_eglDisplay, NULL, NULL)) + qFatal("Qt WinRT platform plugin: failed to initialize EGL. This can happen if you haven't included the D3D compiler DLL in your application package."); + + // TODO: move this to Window + m_eglSurface = eglCreateWindowSurface(m_eglDisplay, q_configFromGLFormat(m_eglDisplay, m_surfaceFormat), window, NULL); + if (m_eglSurface == EGL_NO_SURFACE) + qFatal("Could not create EGL surface, error 0x%X", eglGetError()); + + // Event handlers mapped to QEvents + m_coreWindow->add_KeyDown(Callback(this, &QWinRTScreen::onKey).Get(), &m_tokens[QEvent::KeyPress]); + m_coreWindow->add_KeyUp(Callback(this, &QWinRTScreen::onKey).Get(), &m_tokens[QEvent::KeyRelease]); + m_coreWindow->add_CharacterReceived(Callback(this, &QWinRTScreen::onCharacterReceived).Get(), &m_tokens[QEvent::User]); + m_coreWindow->add_PointerEntered(Callback(this, &QWinRTScreen::onPointerEntered).Get(), &m_tokens[QEvent::Enter]); + m_coreWindow->add_PointerExited(Callback(this, &QWinRTScreen::onPointerExited).Get(), &m_tokens[QEvent::Leave]); + m_coreWindow->add_PointerMoved(Callback(this, &QWinRTScreen::onPointerUpdated).Get(), &m_tokens[QEvent::MouseMove]); + m_coreWindow->add_PointerPressed(Callback(this, &QWinRTScreen::onPointerUpdated).Get(), &m_tokens[QEvent::MouseButtonPress]); + m_coreWindow->add_PointerReleased(Callback(this, &QWinRTScreen::onPointerUpdated).Get(), &m_tokens[QEvent::MouseButtonRelease]); + m_coreWindow->add_PointerWheelChanged(Callback(this, &QWinRTScreen::onPointerUpdated).Get(), &m_tokens[QEvent::Wheel]); + m_coreWindow->add_SizeChanged(Callback(this, &QWinRTScreen::onSizeChanged).Get(), &m_tokens[QEvent::Resize]); + + // Window event handlers + m_coreWindow->add_Activated(Callback(this, &QWinRTScreen::onActivated).Get(), &m_tokens[QEvent::WindowActivate]); + m_coreWindow->add_Closed(Callback(this, &QWinRTScreen::onClosed).Get(), &m_tokens[QEvent::WindowDeactivate]); + m_coreWindow->add_VisibilityChanged(Callback(this, &QWinRTScreen::onVisibilityChanged).Get(), &m_tokens[QEvent::Show]); + m_coreWindow->add_AutomationProviderRequested(Callback(this, &QWinRTScreen::onAutomationProviderRequested).Get(), &m_tokens[QEvent::InputMethodQuery]); + + // Orientation handling + if (SUCCEEDED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), + &m_displayProperties))) { + // Set native orientation + DisplayOrientations displayOrientation; + m_displayProperties->get_NativeOrientation(&displayOrientation); + m_nativeOrientation = qOrientationFromNative(displayOrientation); + + // Set initial orientation + onOrientationChanged(0); + + m_displayProperties->add_OrientationChanged(Callback(this, &QWinRTScreen::onOrientationChanged).Get(), + &m_tokens[QEvent::OrientationChange]); + } + +#ifndef Q_OS_WINPHONE + GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_ApplicationView).Get(), + &m_applicationView); +#endif +} + +QRect QWinRTScreen::geometry() const +{ + return m_geometry; +} + +int QWinRTScreen::depth() const +{ + return m_depth; +} + +QImage::Format QWinRTScreen::format() const +{ + return m_format; +} + +QSurfaceFormat QWinRTScreen::surfaceFormat() const +{ + return m_surfaceFormat; +} + +QWinRTInputContext *QWinRTScreen::inputContext() const +{ + return m_inputContext; +} + +QPlatformCursor *QWinRTScreen::cursor() const +{ + return m_cursor; +} + +Qt::ScreenOrientation QWinRTScreen::nativeOrientation() const +{ + return m_nativeOrientation; +} + +Qt::ScreenOrientation QWinRTScreen::orientation() const +{ + return m_orientation; +} + +ICoreWindow *QWinRTScreen::coreWindow() const +{ + return m_coreWindow; +} + +EGLDisplay QWinRTScreen::eglDisplay() const +{ + return m_eglDisplay; +} + +EGLSurface QWinRTScreen::eglSurface() const +{ + return m_eglSurface; +} + +QWindow *QWinRTScreen::topWindow() const +{ + return m_visibleWindows.isEmpty() ? 0 : m_visibleWindows.first(); +} + +void QWinRTScreen::addWindow(QWindow *window) +{ + if (window == topWindow()) + return; + m_visibleWindows.prepend(window); + QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason); + handleExpose(); +} + +void QWinRTScreen::removeWindow(QWindow *window) +{ + const bool wasTopWindow = window == topWindow(); + if (!m_visibleWindows.removeAll(window)) + return; + if (wasTopWindow) + QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason); + handleExpose(); +} + +void QWinRTScreen::raise(QWindow *window) +{ + m_visibleWindows.removeAll(window); + addWindow(window); +} + +void QWinRTScreen::lower(QWindow *window) +{ + const bool wasTopWindow = window == topWindow(); + if (wasTopWindow && m_visibleWindows.size() == 1) + return; + m_visibleWindows.removeAll(window); + m_visibleWindows.append(window); + if (wasTopWindow) + QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason); + handleExpose(); +} + +void QWinRTScreen::handleExpose() +{ + if (m_visibleWindows.isEmpty()) + return; + QList::const_iterator it = m_visibleWindows.constBegin(); + QWindowSystemInterface::handleExposeEvent(*it, m_geometry); + while (++it != m_visibleWindows.constEnd()) + QWindowSystemInterface::handleExposeEvent(*it, QRegion()); + QWindowSystemInterface::flushWindowSystemEvents(); +} + +HRESULT QWinRTScreen::onKey(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IKeyEventArgs *args) +{ + Q_UNUSED(window); + + // Windows Phone documentation claims this will throw, but doesn't seem to + CorePhysicalKeyStatus keyStatus; + args->get_KeyStatus(&keyStatus); + + VirtualKey virtualKey; + args->get_VirtualKey(&virtualKey); + + // Filter meta keys + Qt::Key key = qMetaKeyFromVirtual(virtualKey); + + // Get keyboard modifiers. This could alternatively be tracked by key presses, but + // WinRT doesn't send key events for Alt unless Ctrl is also pressed. + // If the key that caused this event is a modifier, it is not returned in the flags. + Qt::KeyboardModifiers mods = qKeyModifiers(m_coreWindow); + + if (m_activeKeys.contains(keyStatus.ScanCode)) { // Handle tracked keys (release/repeat) + QString text = keyStatus.IsKeyReleased ? m_activeKeys.take(keyStatus.ScanCode) : m_activeKeys.value(keyStatus.ScanCode); + QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease, key, mods, text); + + if (!keyStatus.IsKeyReleased) // Repeating key + QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyPress, key, mods, text); + + } else if (keyStatus.IsKeyReleased) { // Unlikely, but possible if key is held before application is focused + QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease, key, mods); + + } else { // Handle key presses + if (key != Qt::Key_unknown) // Handle non-character key presses here, others in onCharacterReceived + QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyPress, key, mods); + + m_activeKeys.insert(keyStatus.ScanCode, QString()); + } + + return S_OK; +} + +HRESULT QWinRTScreen::onCharacterReceived(ICoreWindow *window, ICharacterReceivedEventArgs *args) +{ + Q_UNUSED(window); + + quint32 keyCode; + args->get_KeyCode(&keyCode); + + // Windows Phone documentation claims this will throw, but doesn't seem to + CorePhysicalKeyStatus keyStatus; + args->get_KeyStatus(&keyStatus); + + QString text = QChar(keyCode); + + Qt::KeyboardModifiers mods = qKeyModifiers(m_coreWindow); + Qt::Key key = qKeyFromChar(keyCode, mods); + + QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyPress, key, mods, text); + + // Note that we can receive a character without corresponding press/release events, such as + // the case of an Alt-combo. In this case, we should send the release immediately. + if (m_activeKeys.contains(keyStatus.ScanCode)) + m_activeKeys.insert(keyStatus.ScanCode, text); + else + QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease, key, mods, text); + + return S_OK; +} + +HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *window, IPointerEventArgs *args) +{ + Q_UNUSED(window); + IPointerPoint *pointerPoint; + if (SUCCEEDED(args->get_CurrentPoint(&pointerPoint))) { + // Assumes full-screen window + Point point; + pointerPoint->get_Position(&point); + QPoint pos(point.X, point.Y); + + QWindowSystemInterface::handleEnterEvent(topWindow(), pos, pos); + pointerPoint->Release(); + } + return S_OK; +} + +HRESULT QWinRTScreen::onPointerExited(ICoreWindow *window, IPointerEventArgs *args) +{ + Q_UNUSED(window); + Q_UNUSED(args); + QWindowSystemInterface::handleLeaveEvent(0); + return S_OK; +} + +HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *args) +{ + Q_UNUSED(window); + + IPointerPoint *pointerPoint; + if (FAILED(args->get_CurrentPoint(&pointerPoint))) + return E_INVALIDARG; + + // Common traits - point, modifiers, properties + Point point; + pointerPoint->get_Position(&point); + QPointF pos(point.X, point.Y); + + VirtualKeyModifiers modifiers; + args->get_KeyModifiers(&modifiers); + Qt::KeyboardModifiers mods; + if (modifiers & VirtualKeyModifiers_Control) + mods |= Qt::ControlModifier; + if (modifiers & VirtualKeyModifiers_Menu) + mods |= Qt::AltModifier; + if (modifiers & VirtualKeyModifiers_Shift) + mods |= Qt::ShiftModifier; + if (modifiers & VirtualKeyModifiers_Windows) + mods |= Qt::MetaModifier; + + IPointerPointProperties *properties; + if (FAILED(pointerPoint->get_Properties(&properties))) + return E_INVALIDARG; + +#ifdef Q_OS_WINPHONE + quint32 pointerId = 0; + Pointer pointer = m_pointers.value(pointerId); +#else + Pointer pointer = { Pointer::Unknown, 0 }; + quint32 pointerId; + pointerPoint->get_PointerId(&pointerId); + if (m_pointers.contains(pointerId)) { + pointer = m_pointers.value(pointerId); + } else { // We have not yet enumerated this device. Do so now... + IPointerDevice *device; + if (SUCCEEDED(pointerPoint->get_PointerDevice(&device))) { + PointerDeviceType type; + device->get_PointerDeviceType(&type); + switch (type) { + case PointerDeviceType_Touch: + pointer.type = Pointer::TouchScreen; + pointer.device = new QTouchDevice; + pointer.device->setName(QStringLiteral("WinRT TouchScreen ") + QString::number(pointerId)); + // TODO: We may want to probe the device usage flags for more accurate values for these next two + pointer.device->setType(QTouchDevice::TouchScreen); + pointer.device->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure); + QWindowSystemInterface::registerTouchDevice(pointer.device); + break; + + case PointerDeviceType_Pen: + pointer.type = Pointer::Tablet; + break; + + case PointerDeviceType_Mouse: + pointer.type = Pointer::Mouse; + break; + } + + m_pointers.insert(pointerId, pointer); + device->Release(); + } + } +#endif + switch (pointer.type) { + case Pointer::Mouse: { + qint32 delta; + properties->get_MouseWheelDelta(&delta); + if (delta) { + boolean isHorizontal; + properties->get_IsHorizontalMouseWheel(&isHorizontal); + QPoint angleDelta(isHorizontal ? delta : 0, isHorizontal ? 0 : delta); + QWindowSystemInterface::handleWheelEvent(topWindow(), pos, pos, QPoint(), angleDelta, mods); + break; + } + + boolean isPressed; + Qt::MouseButtons buttons = Qt::NoButton; + properties->get_IsLeftButtonPressed(&isPressed); + if (isPressed) + buttons |= Qt::LeftButton; + + properties->get_IsMiddleButtonPressed(&isPressed); + if (isPressed) + buttons |= Qt::MiddleButton; + + properties->get_IsRightButtonPressed(&isPressed); + if (isPressed) + buttons |= Qt::RightButton; + + properties->get_IsXButton1Pressed(&isPressed); + if (isPressed) + buttons |= Qt::XButton1; + + properties->get_IsXButton2Pressed(&isPressed); + if (isPressed) + buttons |= Qt::XButton2; + + QWindowSystemInterface::handleMouseEvent(topWindow(), pos, pos, buttons, mods); + + break; + } + case Pointer::TouchScreen: { + quint32 id; + pointerPoint->get_PointerId(&id); + + Rect area; + properties->get_ContactRect(&area); + + float pressure; + properties->get_Pressure(&pressure); + + QHash::iterator it = m_touchPoints.find(id); + if (it != m_touchPoints.end()) { + boolean isPressed; + pointerPoint->get_IsInContact(&isPressed); + it.value().state = isPressed ? Qt::TouchPointMoved : Qt::TouchPointReleased; + } else { + it = m_touchPoints.insert(id, QWindowSystemInterface::TouchPoint()); + it.value().state = Qt::TouchPointPressed; + it.value().id = id; + } + it.value().area = QRectF(area.X, area.Y, area.Width, area.Height); + it.value().normalPosition = QPointF(pos.x()/m_geometry.width(), pos.y()/m_geometry.height()); + it.value().pressure = pressure; + + QWindowSystemInterface::handleTouchEvent(topWindow(), pointer.device, m_touchPoints.values(), mods); + + // Remove released points, station others + for (QHash::iterator i = m_touchPoints.begin(); i != m_touchPoints.end();) { + if (i.value().state == Qt::TouchPointReleased) + i = m_touchPoints.erase(i); + else + (i++).value().state = Qt::TouchPointStationary; + } + + break; + } + case Pointer::Tablet: { + quint32 id; + pointerPoint->get_PointerId(&id); + + boolean isPressed; + pointerPoint->get_IsInContact(&isPressed); + + boolean isEraser; + properties->get_IsEraser(&isEraser); + int pointerType = isEraser ? 3 : 1; + + float pressure; + properties->get_Pressure(&pressure); + + float xTilt; + properties->get_XTilt(&xTilt); + + float yTilt; + properties->get_YTilt(&yTilt); + + float rotation; + properties->get_Twist(&rotation); + + QWindowSystemInterface::handleTabletEvent(topWindow(), isPressed, pos, pos, pointerId, + pointerType, pressure, xTilt, yTilt, + 0, rotation, 0, id, mods); + + break; + } + } + + properties->Release(); + pointerPoint->Release(); + + return S_OK; +} + +HRESULT QWinRTScreen::onAutomationProviderRequested(ICoreWindow *, IAutomationProviderRequestedEventArgs *args) +{ +#ifndef Q_OS_WINPHONE + args->put_AutomationProvider(m_inputContext); +#endif + return S_OK; +} + +HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *window, IWindowSizeChangedEventArgs *args) +{ + Q_UNUSED(window); + + Size size; + if (FAILED(args->get_Size(&size))) { + qWarning(Q_FUNC_INFO ": failed to get size"); + return S_OK; + } + + // Regardless of state, all top-level windows are viewport-sized - this might change if + // a more advanced compositor is written. + m_geometry.setSize(QSize(size.Width, size.Height)); + QWindowSystemInterface::handleScreenGeometryChange(screen(), m_geometry); + QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), m_geometry); + QPlatformScreen::resizeMaximizedWindows(); + handleExpose(); + + return S_OK; +} + +HRESULT QWinRTScreen::onActivated(ICoreWindow *window, IWindowActivatedEventArgs *args) +{ + Q_UNUSED(window); + + CoreWindowActivationState activationState; + args->get_WindowActivationState(&activationState); + if (activationState == CoreWindowActivationState_Deactivated) { + QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive); + return S_OK; + } + + // Activate topWindow + if (!m_visibleWindows.isEmpty()) { + Qt::FocusReason focusReason = activationState == CoreWindowActivationState_PointerActivated + ? Qt::MouseFocusReason : Qt::ActiveWindowFocusReason; + QWindowSystemInterface::handleWindowActivated(topWindow(), focusReason); + } + return S_OK; +} + +HRESULT QWinRTScreen::onClosed(ICoreWindow *window, ICoreWindowEventArgs *args) +{ + Q_UNUSED(window); + Q_UNUSED(args); + + foreach (QWindow *w, QGuiApplication::topLevelWindows()) + QWindowSystemInterface::handleCloseEvent(w); + return S_OK; +} + +HRESULT QWinRTScreen::onVisibilityChanged(ICoreWindow *window, IVisibilityChangedEventArgs *args) +{ + Q_UNUSED(window); + Q_UNUSED(args); + + boolean visible; + args->get_Visible(&visible); + QWindowSystemInterface::handleApplicationStateChanged(visible ? Qt::ApplicationActive : Qt::ApplicationHidden); + return S_OK; +} + +HRESULT QWinRTScreen::onOrientationChanged(IInspectable *) +{ + DisplayOrientations displayOrientation; + m_displayProperties->get_CurrentOrientation(&displayOrientation); + Qt::ScreenOrientation newOrientation = qOrientationFromNative(displayOrientation); + if (m_orientation != newOrientation) { + m_orientation = newOrientation; + QWindowSystemInterface::handleScreenOrientationChange(screen(), m_orientation); + } + + return S_OK; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h new file mode 100644 index 0000000000..d0ac53d56d --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtscreen.h @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINRTSCREEN_H +#define QWINRTSCREEN_H + +#include +#include + +#include +#include +#include + +#include + +namespace ABI { + namespace Windows { + namespace UI { + namespace Core { + struct IAutomationProviderRequestedEventArgs; + struct ICharacterReceivedEventArgs; + struct ICoreWindow; + struct ICoreWindowEventArgs; + struct IKeyEventArgs; + struct IPointerEventArgs; + struct IVisibilityChangedEventArgs; + struct IWindowActivatedEventArgs; + struct IWindowSizeChangedEventArgs; + } + namespace ViewManagement { + struct IApplicationViewStatics; + } + } + namespace Graphics { + namespace Display { + struct IDisplayPropertiesStatics; + } + } + } +} +struct IInspectable; + +QT_BEGIN_NAMESPACE + +class QTouchDevice; +class QWinRTEGLContext; +class QWinRTPageFlipper; +class QWinRTCursor; +class QWinRTInputContext; + +struct Pointer { + enum Type { Unknown, Mouse, TouchScreen, Tablet }; + Type type; + QTouchDevice *device; +}; + +class QWinRTScreen : public QPlatformScreen +{ +public: + explicit QWinRTScreen(ABI::Windows::UI::Core::ICoreWindow *window); + QRect geometry() const; + int depth() const; + QImage::Format format() const; + QSurfaceFormat surfaceFormat() const; + QWinRTInputContext *inputContext() const; + QPlatformCursor *cursor() const; + + Qt::ScreenOrientation nativeOrientation() const; + Qt::ScreenOrientation orientation() const; + + QWindow *topWindow() const; + void addWindow(QWindow *window); + void removeWindow(QWindow *window); + void raise(QWindow *window); + void lower(QWindow *window); + + ABI::Windows::UI::Core::ICoreWindow *coreWindow() const; + EGLDisplay eglDisplay() const; // To opengl context + EGLSurface eglSurface() const; // To window + +private: + void handleExpose(); + + // Event handlers + QHash m_tokens; + + HRESULT onKey(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IKeyEventArgs *args); + HRESULT onCharacterReceived(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::ICharacterReceivedEventArgs *args); + HRESULT onPointerEntered(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IPointerEventArgs *args); + HRESULT onPointerExited(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IPointerEventArgs *args); + HRESULT onPointerUpdated(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IPointerEventArgs *args); + HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *args); + + HRESULT onActivated(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowActivatedEventArgs *args); + HRESULT onClosed(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::ICoreWindowEventArgs *args); + HRESULT onVisibilityChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IVisibilityChangedEventArgs *args); + HRESULT onAutomationProviderRequested(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IAutomationProviderRequestedEventArgs *args); + + HRESULT onOrientationChanged(IInspectable *); + + ABI::Windows::UI::Core::ICoreWindow *m_coreWindow; + ABI::Windows::UI::ViewManagement::IApplicationViewStatics *m_applicationView; + QRect m_geometry; + QImage::Format m_format; + QSurfaceFormat m_surfaceFormat; + int m_depth; + QWinRTInputContext *m_inputContext; + QWinRTCursor *m_cursor; + QList m_visibleWindows; + + EGLDisplay m_eglDisplay; + EGLSurface m_eglSurface; + + ABI::Windows::Graphics::Display::IDisplayPropertiesStatics *m_displayProperties; + Qt::ScreenOrientation m_nativeOrientation; + Qt::ScreenOrientation m_orientation; + + QHash m_activeKeys; + QHash m_pointers; + QHash m_touchPoints; +}; + +QT_END_NAMESPACE + +#endif // QWINRTSCREEN_H diff --git a/src/plugins/platforms/winrt/qwinrtservices.cpp b/src/plugins/platforms/winrt/qwinrtservices.cpp new file mode 100644 index 0000000000..8f0a1d55bb --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtservices.cpp @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** 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 "qwinrtservices.h" +#include +#include +#include + +#include +#include +#include +#include +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Storage; +using namespace ABI::Windows::System; + +QT_BEGIN_NAMESPACE + +QWinRTServices::QWinRTServices() +{ + GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_Uri).Get(), &m_uriFactory); + GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_StorageFile).Get(), &m_fileFactory); + GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_System_Launcher).Get(), &m_launcher); +} + +QWinRTServices::~QWinRTServices() +{ + if (m_uriFactory) + m_uriFactory->Release(); + + if (m_fileFactory) + m_fileFactory->Release(); + + if (m_launcher) + m_launcher->Release(); +} + +bool QWinRTServices::openUrl(const QUrl &url) +{ + if (!(m_uriFactory && m_launcher)) + return QPlatformServices::openUrl(url); + + IUriRuntimeClass *uri; + QString urlString = url.toString(); HSTRING uriString; HSTRING_HEADER header; + WindowsCreateStringReference((const wchar_t*)urlString.utf16(), urlString.length(), &header, &uriString); + m_uriFactory->CreateUri(uriString, &uri); + if (!uri) + return false; + + IAsyncOperation *launchOp; + m_launcher->LaunchUriAsync(uri, &launchOp); + uri->Release(); + if (!launchOp) + return false; + + boolean result = false; + while (launchOp->GetResults(&result) == E_ILLEGAL_METHOD_CALL) + QCoreApplication::processEvents(); + launchOp->Release(); + + return result; +} + +bool QWinRTServices::openDocument(const QUrl &url) +{ + if (!(m_fileFactory && m_launcher)) + return QPlatformServices::openDocument(url); + + QString pathString = QDir::toNativeSeparators( + QDir::cleanPath(qApp->applicationDirPath().append(url.toString(QUrl::RemoveScheme)))); + HSTRING_HEADER header; HSTRING path; + WindowsCreateStringReference((const wchar_t*)pathString.utf16(), pathString.length(), &header, &path); + IAsyncOperation *fileOp; + m_fileFactory->GetFileFromPathAsync(path, &fileOp); + if (!fileOp) + return false; + + IStorageFile *file = nullptr; + while (fileOp->GetResults(&file) == E_ILLEGAL_METHOD_CALL) + QCoreApplication::processEvents(); + fileOp->Release(); + if (!file) + return false; + + IAsyncOperation *launchOp; + m_launcher->LaunchFileAsync(file, &launchOp); + if (!launchOp) + return false; + + boolean result = false; + while (launchOp->GetResults(&result) == E_ILLEGAL_METHOD_CALL) + QCoreApplication::processEvents(); + launchOp->Release(); + + return result; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtservices.h b/src/plugins/platforms/winrt/qwinrtservices.h new file mode 100644 index 0000000000..9cc917030a --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtservices.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINRTSERVICES_H +#define QWINRTSERVICES_H + +#include + +namespace ABI { + namespace Windows { + namespace Foundation { + struct IUriRuntimeClassFactory; + } + namespace Storage { + struct IStorageFileStatics; + } + namespace System { + struct ILauncherStatics; + } + } +} + +QT_BEGIN_NAMESPACE + +class QWinRTServices : public QPlatformServices +{ +public: + explicit QWinRTServices(); + ~QWinRTServices(); + + bool openUrl(const QUrl &url); + bool openDocument(const QUrl &url); + +private: + ABI::Windows::Foundation::IUriRuntimeClassFactory *m_uriFactory; + ABI::Windows::Storage::IStorageFileStatics *m_fileFactory; + ABI::Windows::System::ILauncherStatics *m_launcher; +}; + +QT_END_NAMESPACE + +#endif // QWINRTSERVICES_H diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp new file mode 100644 index 0000000000..88b753b463 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** 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 "qwinrtwindow.h" +#include "qwinrtscreen.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QWinRTWindow::QWinRTWindow(QWindow *window) + : QPlatformWindow(window) + , m_screen(static_cast(screen())) +{ + setWindowFlags(window->flags()); + setWindowState(window->windowState()); + handleContentOrientationChange(window->contentOrientation()); + setGeometry(window->geometry()); +} + +QWinRTWindow::~QWinRTWindow() +{ + m_screen->removeWindow(window()); +} + +QSurfaceFormat QWinRTWindow::format() const +{ + return m_screen->surfaceFormat(); +} + +bool QWinRTWindow::isActive() const +{ + return m_screen->topWindow() == window(); +} + +bool QWinRTWindow::isExposed() const +{ + const bool exposed = isActive(); + return exposed; +} + +void QWinRTWindow::setGeometry(const QRect &rect) +{ + if (window()->isTopLevel()) { + QPlatformWindow::setGeometry(m_screen->geometry()); + QWindowSystemInterface::handleGeometryChange(window(), geometry()); + } else { + QPlatformWindow::setGeometry(rect); + QWindowSystemInterface::handleGeometryChange(window(), rect); + } +} + +void QWinRTWindow::setVisible(bool visible) +{ + if (!window()->isTopLevel()) + return; + if (visible) + m_screen->addWindow(window()); + else + m_screen->removeWindow(window()); +} + +void QWinRTWindow::raise() +{ + if (!window()->isTopLevel()) + return; + m_screen->raise(window()); +} + +void QWinRTWindow::lower() +{ + if (!window()->isTopLevel()) + return; + m_screen->lower(window()); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtwindow.h b/src/plugins/platforms/winrt/qwinrtwindow.h new file mode 100644 index 0000000000..1f19b4f2d5 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtwindow.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINRTWINDOW_H +#define QWINRTWINDOW_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QWinRTScreen; + +class QWinRTWindow : public QPlatformWindow +{ +public: + QWinRTWindow(QWindow *window); + ~QWinRTWindow(); + + QSurfaceFormat format() const; + bool isActive() const; + bool isExposed() const; + void setGeometry(const QRect &rect); + void setVisible(bool visible); + void raise(); + void lower(); + +private: + QWinRTScreen *m_screen; +}; + +QT_END_NAMESPACE + +#endif // QWINRTWINDOW_H diff --git a/src/plugins/platforms/winrt/winrt.json b/src/plugins/platforms/winrt/winrt.json new file mode 100644 index 0000000000..962747b697 --- /dev/null +++ b/src/plugins/platforms/winrt/winrt.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "winrt" ] +} diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro new file mode 100644 index 0000000000..ea5ff93d00 --- /dev/null +++ b/src/plugins/platforms/winrt/winrt.pro @@ -0,0 +1,55 @@ +TARGET = qwinrt +CONFIG -= precompile_header + +PLUGIN_TYPE = platforms +PLUGIN_CLASS_NAME = QWinRTIntegrationPlugin +load(qt_plugin) + +QT += core-private gui-private platformsupport-private + +DEFINES *= QT_NO_CAST_FROM_ASCII __WRL_NO_DEFAULT_LIB__ GL_GLEXT_PROTOTYPES + +LIBS += $$QMAKE_LIBS_CORE -ldxgi + +SOURCES = \ + main.cpp \ + qwinrtbackingstore.cpp \ + qwinrtcursor.cpp \ + qwinrteglcontext.cpp \ + qwinrteventdispatcher.cpp \ + qwinrtfontdatabase.cpp \ + qwinrtinputcontext.cpp \ + qwinrtintegration.cpp \ + qwinrtscreen.cpp \ + qwinrtservices.cpp \ + qwinrtwindow.cpp + +HEADERS = \ + qwinrtbackingstore.h \ + qwinrtcursor.h \ + qwinrteglcontext.h \ + qwinrteventdispatcher.h \ + qwinrtfontdatabase.h \ + qwinrtinputcontext.h \ + qwinrtintegration.h \ + qwinrtscreen.h \ + qwinrtservices.h \ + qwinrtwindow.h + +BLIT_INPUT = $$PWD/blit.hlsl +fxc_blitps.commands = fxc.exe /nologo /T ps_4_0_level_9_1 /E blitps /Vn q_blitps /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} +fxc_blitps.output = $$OUT_PWD/blitps.h +fxc_blitps.input = BLIT_INPUT +fxc_blitps.dependency_type = TYPE_C +fxc_blitps.variable_out = HEADERS +fxc_blitps.CONFIG += target_predeps +fxc_blitvs.commands = fxc.exe /nologo /T vs_4_0_level_9_1 /E blitvs /Vn q_blitvs /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} +fxc_blitvs.output = $$OUT_PWD/blitvs.h +fxc_blitvs.input = BLIT_INPUT +fxc_blitvs.dependency_type = TYPE_C +fxc_blitvs.variable_out = HEADERS +fxc_blitvs.CONFIG += target_predeps +QMAKE_EXTRA_COMPILERS += fxc_blitps fxc_blitvs + +OTHER_FILES += winrt.json \ + blit.hlsl diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 914e7c9bfd..9e977322ff 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -1597,8 +1597,8 @@ void Configure::applySpecSpecifics() dictionary[ "LIBPNG" ] = "qt"; dictionary[ "FREETYPE" ] = "yes"; dictionary[ "ACCESSIBILITY" ] = "no"; - dictionary[ "OPENGL" ] = "no"; - dictionary[ "OPENGL_ES_2" ] = "no"; + dictionary[ "OPENGL" ] = "yes"; + dictionary[ "OPENGL_ES_2" ] = "yes"; dictionary[ "OPENVG" ] = "no"; dictionary[ "OPENSSL" ] = "auto"; dictionary[ "DBUS" ] = "no"; @@ -1607,7 +1607,7 @@ void Configure::applySpecSpecifics() dictionary[ "ICU" ] = "qt"; dictionary[ "CE_CRT" ] = "yes"; dictionary[ "LARGE_FILE" ] = "no"; - dictionary[ "ANGLE" ] = "no"; + dictionary[ "ANGLE" ] = "d3d11"; if (dictionary.value("XQMAKESPEC").startsWith("winphone")) dictionary[ "SQL_SQLITE" ] = "no"; } else if (dictionary.value("XQMAKESPEC").startsWith("wince")) { From 3592dd554f1c763a3c0c90d4b12b4eafb0bb636c Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 26 Sep 2013 09:46:53 +0200 Subject: [PATCH 022/684] QBrush: use a 3D array instead of pointer tables to save 28 relocs in QtGui Change-Id: I4695a053fa5f455075ddda209791904f98ba7149 Reviewed-by: Gunnar Sletta --- src/gui/painting/qbrush.cpp | 81 ++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index 66c3a68c13..5b8556d198 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -56,44 +56,49 @@ QT_BEGIN_NAMESPACE const uchar *qt_patternForBrush(int brushStyle, bool invert) { Q_ASSERT(brushStyle > Qt::SolidPattern && brushStyle < Qt::LinearGradientPattern); - if(invert) { - static const uchar dense1_pat[] = { 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff }; - static const uchar dense2_pat[] = { 0x77, 0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff }; - static const uchar dense3_pat[] = { 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55, 0xee }; - static const uchar dense4_pat[] = { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 }; - static const uchar dense5_pat[] = { 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa, 0x11 }; - static const uchar dense6_pat[] = { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 }; - static const uchar dense7_pat[] = { 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00 }; - static const uchar hor_pat[] = { 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00 }; - static const uchar ver_pat[] = { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }; - static const uchar cross_pat[] = { 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10, 0x10 }; - static const uchar bdiag_pat[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; - static const uchar fdiag_pat[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; - static const uchar dcross_pat[] = { 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 }; - static const uchar *const pat_tbl[] = { - dense1_pat, dense2_pat, dense3_pat, dense4_pat, dense5_pat, - dense6_pat, dense7_pat, - hor_pat, ver_pat, cross_pat, bdiag_pat, fdiag_pat, dcross_pat }; - return pat_tbl[brushStyle - Qt::Dense1Pattern]; - } - static const uchar dense1_pat[] = { 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00 }; - static const uchar dense2_pat[] = { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 }; - static const uchar dense3_pat[] = { 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa, 0x11 }; - static const uchar dense4_pat[] = { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa }; - static const uchar dense5_pat[] = { 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55, 0xee }; - static const uchar dense6_pat[] = { 0x77, 0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff }; - static const uchar dense7_pat[] = { 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff }; - static const uchar hor_pat[] = { 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff }; - static const uchar ver_pat[] = { 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef }; - static const uchar cross_pat[] = { 0xef, 0xef, 0xef, 0x00, 0xef, 0xef, 0xef, 0xef }; - static const uchar bdiag_pat[] = { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe }; - static const uchar fdiag_pat[] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f }; - static const uchar dcross_pat[] = { 0x7e, 0xbd, 0xdb, 0xe7, 0xe7, 0xdb, 0xbd, 0x7e }; - static const uchar *const pat_tbl[] = { - dense1_pat, dense2_pat, dense3_pat, dense4_pat, dense5_pat, - dense6_pat, dense7_pat, - hor_pat, ver_pat, cross_pat, bdiag_pat, fdiag_pat, dcross_pat }; - return pat_tbl[brushStyle - Qt::Dense1Pattern]; + static const uchar pat_tbl[][2][8] = { + { + /* dense1 */ { 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00 }, + /*~dense1 */ { 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff }, + }, { + /* dense2 */ { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 }, + /*~dense2 */ { 0x77, 0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff }, + }, { + /* dense3 */ { 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa, 0x11 }, + /*~dense3 */ { 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55, 0xee }, + }, { + /* dense4 */ { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa }, + /*~dense4 */ { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 }, + }, { + /* dense5 */ { 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55, 0xee }, + /*~dense5 */ { 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa, 0x11 }, + }, { + /* dense6 */ { 0x77, 0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff }, + /*~dense6 */ { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 }, + }, { + /* dense7 */ { 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff }, + /*~dense7 */ { 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00 }, + }, { + /* hor */ { 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff }, + /*~hor */ { 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00 }, + }, { + /* ver */ { 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef }, + /*~ver */ { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, + }, { + /* cross */ { 0xef, 0xef, 0xef, 0x00, 0xef, 0xef, 0xef, 0xef }, + /*~cross */ { 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10, 0x10 }, + }, { + /* bdiag */ { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe }, + /*~bdiag */ { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }, + }, { + /* fdiag */ { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f }, + /*~fdiag */ { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }, + }, { + /* dcross */ { 0x7e, 0xbd, 0xdb, 0xe7, 0xe7, 0xdb, 0xbd, 0x7e }, + /*~dcross */ { 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 }, + }, + }; + return pat_tbl[brushStyle - Qt::Dense1Pattern][invert]; } QPixmap qt_pixmapForBrush(int brushStyle, bool invert) From 19088c831a6d9ecc46ffd4487ff68df236096f05 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Tue, 1 Oct 2013 09:47:02 +0300 Subject: [PATCH 023/684] libpng: Add Windows Phone to existing WinRT define Treat Windows Phone as WinRT. Change-Id: I74e45a199629df3efaafa6acb05f991044f5c884 Reviewed-by: Friedemann Kleint --- src/3rdparty/libpng/pngpriv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdparty/libpng/pngpriv.h b/src/3rdparty/libpng/pngpriv.h index 592d4ee0cb..f01e56f612 100644 --- a/src/3rdparty/libpng/pngpriv.h +++ b/src/3rdparty/libpng/pngpriv.h @@ -362,7 +362,7 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; #if defined(WIN32) || defined(_Windows) || defined(_WINDOWS) || \ defined(_WIN32) || defined(__WIN32__) # include /* defines _WINDOWS_ macro */ -# if defined(WINAPI_FAMILY) && ((WINAPI_FAMILY & WINAPI_FAMILY_DESKTOP_APP) == WINAPI_PARTITION_APP) +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) # define _WINRT_ /* Define a macro for Windows Runtime builds */ # endif #endif From 3649a6e61d823289d18be19387d7e3923dd90bd0 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Mon, 30 Sep 2013 08:20:24 +0300 Subject: [PATCH 024/684] Fix QT_POINTER_SIZE on WinRT x64 Q_OS_WIN64 is not defined for WinRT, so make sure the pointer size is correct. Change-Id: I5a55bfd7edbfd23e0eab50fa31a76faa9e383a8d Reviewed-by: Oliver Wolff --- src/corelib/global/qglobal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 1ebe0bd8ea..fd5ab865f3 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -192,7 +192,7 @@ typedef qint64 qlonglong; typedef quint64 qulonglong; #ifndef QT_POINTER_SIZE -# if defined(Q_OS_WIN64) +# if defined(Q_OS_WIN64) || (defined(Q_OS_WINRT) && defined(_M_X64)) # define QT_POINTER_SIZE 8 # elif defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_WINRT) # define QT_POINTER_SIZE 4 From cb82b3e8913e9d7952e9b3d4fa680c4af9965434 Mon Sep 17 00:00:00 2001 From: Donald Carr Date: Wed, 2 Oct 2013 01:35:46 -0700 Subject: [PATCH 025/684] Add unsupported linux libc++ clang mkspec Change-Id: Ie282196f3961777d04170fb7426f51c5fba83678 Reviewed-by: Simon Hausmann --- .../unsupported/linux-libc++-clang/qmake.conf | 20 ++++ .../linux-libc++-clang/qplatformdefs.h | 100 ++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 mkspecs/unsupported/linux-libc++-clang/qmake.conf create mode 100644 mkspecs/unsupported/linux-libc++-clang/qplatformdefs.h diff --git a/mkspecs/unsupported/linux-libc++-clang/qmake.conf b/mkspecs/unsupported/linux-libc++-clang/qmake.conf new file mode 100644 index 0000000000..bf0abb2a54 --- /dev/null +++ b/mkspecs/unsupported/linux-libc++-clang/qmake.conf @@ -0,0 +1,20 @@ +# +# qmake configuration for linux-clang +# + +MAKEFILE_GENERATOR = UNIX +CONFIG += incremental + +QMAKE_INCREMENTAL_STYLE = sublib + +include(../../common/linux.conf) +include(../../common/gcc-base-unix.conf) +include(../../common/clang.conf) + +QMAKE_CFLAGS_RELEASE = -Os +QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE + +QMAKE_CXXFLAGS_CXX11 += -std=c++11 -stdlib=libc++ +QMAKE_LFLAGS_CXX11 += -stdlib=libc++ -lc++abi + +load(qt_config) diff --git a/mkspecs/unsupported/linux-libc++-clang/qplatformdefs.h b/mkspecs/unsupported/linux-libc++-clang/qplatformdefs.h new file mode 100644 index 0000000000..c1066ee9a2 --- /dev/null +++ b/mkspecs/unsupported/linux-libc++-clang/qplatformdefs.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the qmake spec 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 QPLATFORMDEFS_H +#define QPLATFORMDEFS_H + +// Get Qt defines/settings + +#include "qglobal.h" + +// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs + +// 1) need to reset default environment if _BSD_SOURCE is defined +// 2) need to specify POSIX thread interfaces explicitly in glibc 2.0 +// 3) it seems older glibc need this to include the X/Open stuff +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +#include + + +// We are hot - unistd.h should have turned on the specific APIs we requested + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef QT_NO_IPV6IFNAME +#include +#endif + +#define QT_USE_XOPEN_LFS_EXTENSIONS +#include "../../common/posix/qplatformdefs.h" + +#undef QT_SOCKLEN_T + +#if defined(__GLIBC__) && (__GLIBC__ >= 2) +#define QT_SOCKLEN_T socklen_t +#else +#define QT_SOCKLEN_T int +#endif + +#if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500) +#define QT_SNPRINTF ::snprintf +#define QT_VSNPRINTF ::vsnprintf +#endif + +#endif // QPLATFORMDEFS_H From 69e78b9a0764ea5ec56689f09311741d4fc5870e Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Thu, 3 Oct 2013 12:19:52 +0300 Subject: [PATCH 026/684] WinRT winmain: enable debugger waiting WinRT applications are not invoked directly, so a debugger may attach too late to be useful. While the application can be launched with a debugging server, attaching directly to the running process is simpler and less resource-intensive. For this reason, it is useful for applications to wait for the direct debugger to attach. If the existing -qdebug parameter is passed to the application, wait idly until the debugger attaches. Change-Id: I7b4957beb9728ab6311b459e4d809dc5f4767780 Reviewed-by: Friedemann Kleint --- src/winmain/qtmain_winrt.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/winmain/qtmain_winrt.cpp b/src/winmain/qtmain_winrt.cpp index d0f138269f..c0542ff242 100644 --- a/src/winmain/qtmain_winrt.cpp +++ b/src/winmain/qtmain_winrt.cpp @@ -69,7 +69,7 @@ typedef ITypedEventHandler { public: - AppContainer(int argc, wchar_t **argv) : m_argc(argc) + AppContainer(int argc, wchar_t **argv) : m_argc(argc), m_debugWait(false) { m_argv.reserve(argc); for (int i = 0; i < argc; ++i) { @@ -95,6 +95,11 @@ public: HRESULT __stdcall Load(HSTRING) { return S_OK; } HRESULT __stdcall Run() { + // Wait for debugger before continuing + if (m_debugWait) { + while (!IsDebuggerPresent()) + WaitForSingleObjectEx(GetCurrentThread(), 1, true); + } return main(m_argv.count(), m_argv.data()); } HRESULT __stdcall Uninitialize() { return S_OK; } @@ -113,6 +118,8 @@ private: foreach (const QByteArray &arg, QString::fromWCharArray( WindowsGetStringRawBuffer(arguments, nullptr)).toLocal8Bit().split(' ')) { m_argv.append(qstrdup(arg.constData())); + if (arg == "-qdebug") + m_debugWait = true; } } return S_OK; @@ -120,6 +127,7 @@ private: int m_argc; QVector m_argv; + bool m_debugWait; EventRegistrationToken m_activationToken; }; From 0a92295ca829a62125c9f122fd3daec991993855 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Sat, 14 Sep 2013 20:31:54 +0200 Subject: [PATCH 027/684] Relay mouse event synthesization information Make platform plugins, like the windows one, able to indicate if a mouse event is synthesized from a touch event by the OS. This will be valuable information for the Quick2 event handlers. No new member variables are added to QMouseEvent. Instead, the enum value is encoded in the caps member, there are plenty of bits available in it. This introduces Qt::MouseEventSource and QMouseEvent::source() as public APIs. Change-Id: If087a0bafb33a6cd7891bd07b84871358f6aba69 Reviewed-by: Shawn Rutledge Reviewed-by: Friedemann Kleint --- src/corelib/global/qnamespace.h | 6 ++++ src/corelib/global/qnamespace.qdoc | 22 +++++++++++++ src/gui/kernel/qevent.cpp | 18 +++++++++++ src/gui/kernel/qevent.h | 2 ++ src/gui/kernel/qguiapplication.cpp | 32 +++++++++++++++---- src/gui/kernel/qguiapplication_p.h | 4 ++- src/gui/kernel/qwindowsysteminterface.cpp | 20 +++++++----- src/gui/kernel/qwindowsysteminterface.h | 16 +++++++--- src/gui/kernel/qwindowsysteminterface_p.h | 11 ++++--- .../windows/qwindowsmousehandler.cpp | 9 ++++-- 10 files changed, 115 insertions(+), 25 deletions(-) diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 420721cb54..1409e5d977 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1584,6 +1584,12 @@ public: ScrollUpdate, ScrollEnd }; + + enum MouseEventSource { + MouseEventNotSynthesized, + MouseEventSynthesizedBySystem, + MouseEventSynthesizedByQt + }; } #ifdef Q_MOC_RUN ; diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 1cd2321ef6..63afd707c1 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -2895,3 +2895,25 @@ \value ScrollEnd Scrolling has ended, but the scrolling distance did not change anymore. */ + +/*! + \enum Qt::MouseEventSource + \since 5.3 + + This enum describes the source of a mouse event and can be useful + to determine if the event is an artificial mouse event originating + from another device such as a touchscreen. + + \value MouseEventNotSynthesized The most common value. On + platforms where such information is available this value indicates + that the event was generated in response to a genuine mouse event + in the system. + + \value MouseEventSynthesizedBySystem Indicates that the mouse + event was synthesized from a touch event by the platform. + + \value MouseEventSynthesizedByQt Indicates that the mouse event was + synthesized from an unhandled touch event by Qt. + + \sa Qt::AA_SynthesizeMouseForUnhandledTouchEvents +*/ diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index e11c4671e6..e5ce6f9daa 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -274,6 +274,24 @@ QMouseEvent::~QMouseEvent() { } +/*! + \since 5.3 + + Returns information about the mouse event source. + + The mouse event source can be used to distinguish between genuine + and artificial mouse events. The latter are events that are + synthesized from touch events by the operating system or Qt itself. + + \note Many platforms provide no such information. On such platforms + \l Qt::MouseEventNotSynthesized is returned always. + + \sa Qt::MouseEventSource + */ +Qt::MouseEventSource QMouseEvent::source() const +{ + return QGuiApplicationPrivate::mouseEventSource(this); +} /*! \fn QPointF QMouseEvent::localPos() const diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 0c1cf70420..7d05e1c5a9 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -135,6 +135,8 @@ public: QT_DEPRECATED inline QPointF posF() const { return l; } #endif + Qt::MouseEventSource source() const; + protected: QPointF l, w, s; Qt::MouseButton b; diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index b242a3cc68..07ee8e9a64 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1560,6 +1560,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo QMouseEvent ev(type, localPoint, localPoint, globalPoint, button, buttons, e->modifiers); ev.setTimestamp(e->timestamp); + setMouseEventSource(&ev, e->source); #ifndef QT_NO_CURSOR if (const QScreen *screen = window->screen()) if (QPlatformCursor *cursor = screen->handle()->cursor()) @@ -1612,6 +1613,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo QMouseEvent dblClickEvent(doubleClickType, localPoint, localPoint, globalPoint, button, buttons, e->modifiers); dblClickEvent.setTimestamp(e->timestamp); + setMouseEventSource(&dblClickEvent, e->source); QGuiApplication::sendSpontaneousEvent(window, &dblClickEvent); } } @@ -2024,7 +2026,8 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To synthIt->pos, synthIt->screenPos, Qt::NoButton, - e->modifiers); + e->modifiers, + Qt::MouseEventSynthesizedByQt); fake.synthetic = true; processMouseEvent(&fake); } @@ -3103,9 +3106,16 @@ void QGuiApplicationPrivate::_q_updateFocusObject(QObject *object) emit q->focusObjectChanged(object); } +enum { + MouseCapsMask = 0xFF, + MouseSourceMaskDst = 0xFF00, + MouseSourceMaskSrc = MouseCapsMask, + MouseSourceShift = 8, +}; + int QGuiApplicationPrivate::mouseEventCaps(QMouseEvent *event) { - return event->caps; + return event->caps & MouseCapsMask; } QVector2D QGuiApplicationPrivate::mouseEventVelocity(QMouseEvent *event) @@ -3115,16 +3125,26 @@ QVector2D QGuiApplicationPrivate::mouseEventVelocity(QMouseEvent *event) void QGuiApplicationPrivate::setMouseEventCapsAndVelocity(QMouseEvent *event, int caps, const QVector2D &velocity) { - event->caps = caps; + Q_ASSERT(caps <= MouseCapsMask); + event->caps &= ~MouseCapsMask; + event->caps |= caps & MouseCapsMask; event->velocity = velocity; } -void QGuiApplicationPrivate::setMouseEventCapsAndVelocity(QMouseEvent *event, QMouseEvent *other) +Qt::MouseEventSource QGuiApplicationPrivate::mouseEventSource(const QMouseEvent *event) { - event->caps = other->caps; - event->velocity = other->velocity; + return Qt::MouseEventSource((event->caps & MouseSourceMaskDst) >> MouseSourceShift); } +void QGuiApplicationPrivate::setMouseEventSource(QMouseEvent *event, Qt::MouseEventSource source) +{ + // Mouse event synthesization status is encoded in the caps field because + // QTouchDevice::CapabilityFlag uses only 6 bits from it. + int value = source; + Q_ASSERT(value <= MouseSourceMaskSrc); + event->caps &= ~MouseSourceMaskDst; + event->caps |= (value & MouseSourceMaskSrc) << MouseSourceShift; +} #include "moc_qguiapplication.cpp" diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index 7a4a161476..b1d20c9ead 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -264,7 +264,9 @@ public: static int mouseEventCaps(QMouseEvent *event); static QVector2D mouseEventVelocity(QMouseEvent *event); static void setMouseEventCapsAndVelocity(QMouseEvent *event, int caps, const QVector2D &velocity); - static void setMouseEventCapsAndVelocity(QMouseEvent *event, QMouseEvent *other); + + static Qt::MouseEventSource mouseEventSource(const QMouseEvent *event); + static void setMouseEventSource(QMouseEvent *event, Qt::MouseEventSource source); const QDrawHelperGammaTables *gammaTables(); diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index d62330083e..5ee9bce540 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -161,31 +161,35 @@ void QWindowSystemInterface::handleCloseEvent(QWindow *tlw, bool *accepted) \a w == 0 means that the event is in global coords only, \a local will be ignored in this case */ -void QWindowSystemInterface::handleMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +void QWindowSystemInterface::handleMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, + Qt::KeyboardModifiers mods, Qt::MouseEventSource source) { unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); - handleMouseEvent(w, time, local, global, b, mods); + handleMouseEvent(w, time, local, global, b, mods, source); } -void QWindowSystemInterface::handleMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +void QWindowSystemInterface::handleMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b, + Qt::KeyboardModifiers mods, Qt::MouseEventSource source) { QWindowSystemInterfacePrivate::MouseEvent * e = - new QWindowSystemInterfacePrivate::MouseEvent(w, timestamp, local, global, b, mods); + new QWindowSystemInterfacePrivate::MouseEvent(w, timestamp, local, global, b, mods, source); QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } -void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, + Qt::KeyboardModifiers mods, Qt::MouseEventSource source) { const unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); - handleFrameStrutMouseEvent(w, time, local, global, b, mods); + handleFrameStrutMouseEvent(w, time, local, global, b, mods, source); } -void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b, + Qt::KeyboardModifiers mods, Qt::MouseEventSource source) { QWindowSystemInterfacePrivate::MouseEvent * e = new QWindowSystemInterfacePrivate::MouseEvent(w, timestamp, QWindowSystemInterfacePrivate::FrameStrutMouse, - local, global, b, mods); + local, global, b, mods, source); QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index c8e464f985..813f538651 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -73,10 +73,18 @@ class QPlatformDropQtResponse; class Q_GUI_EXPORT QWindowSystemInterface { public: - static void handleMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier); - static void handleMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier); - static void handleFrameStrutMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier); - static void handleFrameStrutMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier); + static void handleMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, + Qt::KeyboardModifiers mods = Qt::NoModifier, + Qt::MouseEventSource source = Qt::MouseEventNotSynthesized); + static void handleMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b, + Qt::KeyboardModifiers mods = Qt::NoModifier, + Qt::MouseEventSource source = Qt::MouseEventNotSynthesized); + static void handleFrameStrutMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, + Qt::KeyboardModifiers mods = Qt::NoModifier, + Qt::MouseEventSource source = Qt::MouseEventNotSynthesized); + static void handleFrameStrutMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b, + Qt::KeyboardModifiers mods = Qt::NoModifier, + Qt::MouseEventSource source = Qt::MouseEventNotSynthesized); static bool tryHandleShortcutEvent(QWindow *w, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1); diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h index 46479701cc..a4221b0e76 100644 --- a/src/gui/kernel/qwindowsysteminterface_p.h +++ b/src/gui/kernel/qwindowsysteminterface_p.h @@ -205,14 +205,17 @@ public: class MouseEvent : public InputEvent { public: MouseEvent(QWindow * w, ulong time, const QPointF & local, const QPointF & global, - Qt::MouseButtons b, Qt::KeyboardModifiers mods) - : InputEvent(w, time, Mouse, mods), localPos(local), globalPos(global), buttons(b) { } + Qt::MouseButtons b, Qt::KeyboardModifiers mods, + Qt::MouseEventSource src = Qt::MouseEventNotSynthesized) + : InputEvent(w, time, Mouse, mods), localPos(local), globalPos(global), buttons(b), source(src) { } MouseEvent(QWindow * w, ulong time, EventType t, const QPointF & local, const QPointF & global, - Qt::MouseButtons b, Qt::KeyboardModifiers mods) - : InputEvent(w, time, t, mods), localPos(local), globalPos(global), buttons(b) { } + Qt::MouseButtons b, Qt::KeyboardModifiers mods, + Qt::MouseEventSource src = Qt::MouseEventNotSynthesized) + : InputEvent(w, time, t, mods), localPos(local), globalPos(global), buttons(b), source(src) { } QPointF localPos; QPointF globalPos; Qt::MouseButtons buttons; + Qt::MouseEventSource source; }; class WheelEvent : public InputEvent { diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 3dd8c5a0cd..8516af7bd9 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -167,6 +167,8 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, if (et == QtWindows::MouseWheelEvent) return translateMouseWheelEvent(window, hwnd, msg, result); + Qt::MouseEventSource source = Qt::MouseEventNotSynthesized; + #ifndef Q_OS_WINCE static const bool passSynthesizedMouseEvents = QWindowsIntegration::instance()->options() & QWindowsIntegration::PassOsMouseEventsSynthesizedFromTouch; if (!passSynthesizedMouseEvents) { @@ -177,6 +179,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, const bool fromTouch = (extraInfo & signatureMask) == miWpSignature && (extraInfo & 0x80); if (fromTouch) return false; + source = Qt::MouseEventSynthesizedBySystem; } #endif // !Q_OS_WINCE @@ -187,7 +190,8 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, const Qt::MouseButtons buttons = QWindowsMouseHandler::queryMouseButtons(); QWindowSystemInterface::handleFrameStrutMouseEvent(window, clientPosition, globalPosition, buttons, - QWindowsKeyMapper::queryKeyboardModifiers()); + QWindowsKeyMapper::queryKeyboardModifiers(), + source); return false; // Allow further event processing (dragging of windows). } @@ -335,7 +339,8 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, } QWindowSystemInterface::handleMouseEvent(window, winEventPosition, globalPosition, buttons, - QWindowsKeyMapper::queryKeyboardModifiers()); + QWindowsKeyMapper::queryKeyboardModifiers(), + source); m_previousCaptureWindow = hasCapture ? window : 0; return true; } From 8279a07c86d5fabd76acc8aec3725fe6383d7b9e Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 13 Sep 2013 13:51:58 +0300 Subject: [PATCH 028/684] WinRT: Locale handling support Provides locale-related codepaths for WinRT where existing Win32 API is unsupported. Change-Id: I35b83d6b208165b7660cac3c9b383cb6ba7e5cf9 Done-with: Maurice Kalinowski Reviewed-by: Andrew Knight Reviewed-by: Friedemann Kleint --- src/corelib/tools/qcollator_win.cpp | 24 ++++ src/corelib/tools/qdatetime.cpp | 3 + src/corelib/tools/qlocale_win.cpp | 206 ++++++++++++++++++++++++---- src/corelib/tools/qstring.cpp | 4 + src/corelib/tools/tools.pri | 1 + 5 files changed, 209 insertions(+), 29 deletions(-) diff --git a/src/corelib/tools/qcollator_win.cpp b/src/corelib/tools/qcollator_win.cpp index 282711fbc6..6cc15891f5 100644 --- a/src/corelib/tools/qcollator_win.cpp +++ b/src/corelib/tools/qcollator_win.cpp @@ -125,9 +125,15 @@ int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) con // comparing strings, the value 2 can be subtracted from a nonzero return value. Then, the // meaning of <0, ==0, and >0 is consistent with the C runtime. +#ifndef Q_OS_WINRT return CompareString(LOCALE_USER_DEFAULT, d->collator, reinterpret_cast(s1), len1, reinterpret_cast(s2), len2) - 2; +#else // !Q_OS_WINRT + return CompareStringEx(LOCALE_NAME_USER_DEFAULT, d->collator, + reinterpret_cast(s1), len1, + reinterpret_cast(s2), len2, NULL, NULL, 0) - 2; +#endif // Q_OS_WINRT } int QCollator::compare(const QString &str1, const QString &str2) const @@ -142,13 +148,31 @@ int QCollator::compare(const QStringRef &s1, const QStringRef &s2) const QCollatorSortKey QCollator::sortKey(const QString &string) const { +#ifndef Q_OS_WINRT int size = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | d->collator, reinterpret_cast(string.constData()), string.size(), 0, 0); +#elif defined(Q_OS_WINPHONE) + int size = 0; + Q_UNIMPLEMENTED(); +#else // Q_OS_WINPHONE + int size = LCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_SORTKEY | d->collator, + reinterpret_cast(string.constData()), string.size(), + 0, 0, NULL, NULL, 0); +#endif // !Q_OS_WINPHONE QString ret(size, Qt::Uninitialized); +#ifndef Q_OS_WINRT int finalSize = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | d->collator, reinterpret_cast(string.constData()), string.size(), reinterpret_cast(ret.data()), ret.size()); +#elif defined(Q_OS_WINPHONE) + int finalSize = 0; +#else // Q_OS_WINPHONE + int finalSize = LCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_SORTKEY | d->collator, + reinterpret_cast(string.constData()), string.size(), + reinterpret_cast(ret.data()), ret.size(), + NULL, NULL, 0); +#endif // !Q_OS_WINPHONE if (finalSize == 0) { qWarning() << "there were problems when generating the ::sortKey by LCMapStringW with error:" << GetLastError(); } diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index d64d929d5a..94e98ac54a 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -61,6 +61,9 @@ # ifdef Q_OS_WINCE # include "qfunctions_wince.h" # endif +# ifdef Q_OS_WINRT +# include "qfunctions_winrt.h" +# endif #endif #if defined(Q_OS_MAC) diff --git a/src/corelib/tools/qlocale_win.cpp b/src/corelib/tools/qlocale_win.cpp index 0730002ca3..bbc208e673 100644 --- a/src/corelib/tools/qlocale_win.cpp +++ b/src/corelib/tools/qlocale_win.cpp @@ -55,12 +55,32 @@ # include #endif +#ifdef Q_OS_WINRT +#include +#include +#include +#ifndef Q_OS_WINPHONE +#include +#endif +#endif // Q_OS_WINRT + QT_BEGIN_NAMESPACE +#ifndef Q_OS_WINRT static QByteArray getWinLocaleName(LCID id = LOCALE_USER_DEFAULT); static const char *winLangCodeToIsoName(int code); static QString winIso639LangName(LCID id = LOCALE_USER_DEFAULT); static QString winIso3116CtryName(LCID id = LOCALE_USER_DEFAULT); +#else // !Q_OS_WINRT +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; + +static QByteArray getWinLocaleName(LPWSTR id = LOCALE_NAME_USER_DEFAULT); +static const char *winLangCodeToIsoName(int code); +static QString winIso639LangName(LPWSTR id = LOCALE_NAME_USER_DEFAULT); +static QString winIso3116CtryName(LPWSTR id = LOCALE_NAME_USER_DEFAULT); +#endif // Q_OS_WINRT #ifndef QT_NO_SYSTEMLOCALE @@ -121,14 +141,23 @@ private: }; // cached values: +#ifndef Q_OS_WINRT LCID lcid; +#else + WCHAR lcName[LOCALE_NAME_MAX_LENGTH]; +#endif SubstitutionType substitutionType; QChar zero; + int getLocaleInfo(LCTYPE type, LPWSTR data, int size); QString getLocaleInfo(LCTYPE type, int maxlen = 0); int getLocaleInfo_int(LCTYPE type, int maxlen = 0); QChar getLocaleInfo_qchar(LCTYPE type); + int getCurrencyFormat(DWORD flags, LPCWSTR value, const CURRENCYFMTW *format, LPWSTR data, int size); + int getDateFormat(DWORD flags, const SYSTEMTIME * date, LPCWSTR format, LPWSTR data, int size); + int getTimeFormat(DWORD flags, const SYSTEMTIME *date, LPCWSTR format, LPWSTR data, int size); + SubstitutionType substitution(); QString &substituteDigits(QString &string); @@ -140,20 +169,60 @@ Q_GLOBAL_STATIC(QSystemLocalePrivate, systemLocalePrivate) QSystemLocalePrivate::QSystemLocalePrivate() : substitutionType(SUnknown) { +#ifndef Q_OS_WINRT lcid = GetUserDefaultLCID(); +#else + GetUserDefaultLocaleName(lcName, LOCALE_NAME_MAX_LENGTH); +#endif +} + +inline int QSystemLocalePrivate::getCurrencyFormat(DWORD flags, LPCWSTR value, const CURRENCYFMTW *format, LPWSTR data, int size) +{ +#ifndef Q_OS_WINRT + return GetCurrencyFormat(lcid, flags, value, format, data, size); +#else + return GetCurrencyFormatEx(lcName, flags, value, format, data, size); +#endif +} + +inline int QSystemLocalePrivate::getDateFormat(DWORD flags, const SYSTEMTIME * date, LPCWSTR format, LPWSTR data, int size) +{ +#ifndef Q_OS_WINRT + return GetDateFormat(lcid, flags, date, format, data, size); +#else + return GetDateFormatEx(lcName, flags, date, format, data, size, NULL); +#endif +} + +inline int QSystemLocalePrivate::getTimeFormat(DWORD flags, const SYSTEMTIME *date, LPCWSTR format, LPWSTR data, int size) +{ +#ifndef Q_OS_WINRT + return GetTimeFormat(lcid, flags, date, format, data, size); +#else + return GetTimeFormatEx(lcName, flags, date, format, data, size); +#endif +} + +inline int QSystemLocalePrivate::getLocaleInfo(LCTYPE type, LPWSTR data, int size) +{ +#ifndef Q_OS_WINRT + return GetLocaleInfo(lcid, type, data, size); +#else + return GetLocaleInfoEx(lcName, type, data, size); +#endif } QString QSystemLocalePrivate::getLocaleInfo(LCTYPE type, int maxlen) { QVarLengthArray buf(maxlen ? maxlen : 64); - if (!GetLocaleInfo(lcid, type, buf.data(), buf.size())) + if (!getLocaleInfo(type, buf.data(), buf.size())) return QString(); if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - int cnt = GetLocaleInfo(lcid, type, 0, 0); + int cnt = getLocaleInfo(type, 0, 0); if (cnt == 0) return QString(); buf.resize(cnt); - if (!GetLocaleInfo(lcid, type, buf.data(), buf.size())) + if (!getLocaleInfo(type, buf.data(), buf.size())) return QString(); } return QString::fromWCharArray(buf.data()); @@ -177,7 +246,7 @@ QSystemLocalePrivate::SubstitutionType QSystemLocalePrivate::substitution() { if (substitutionType == SUnknown) { wchar_t buf[8]; - if (!GetLocaleInfo(lcid, LOCALE_IDIGITSUBSTITUTION, buf, 8)) { + if (!getLocaleInfo(LOCALE_IDIGITSUBSTITUTION, buf, 8)) { substitutionType = QSystemLocalePrivate::SNever; return substitutionType; } @@ -189,7 +258,7 @@ QSystemLocalePrivate::SubstitutionType QSystemLocalePrivate::substitution() substitutionType = QSystemLocalePrivate::SAlways; else { wchar_t digits[11]; - if (!GetLocaleInfo(lcid, LOCALE_SNATIVEDIGITS, digits, 11)) { + if (!getLocaleInfo(LOCALE_SNATIVEDIGITS, digits, 11)) { substitutionType = QSystemLocalePrivate::SNever; return substitutionType; } @@ -332,7 +401,7 @@ QVariant QSystemLocalePrivate::toString(const QDate &date, QLocale::FormatType t DWORD flags = (type == QLocale::LongFormat ? DATE_LONGDATE : DATE_SHORTDATE); wchar_t buf[255]; - if (GetDateFormat(lcid, flags, &st, NULL, buf, 255)) { + if (getDateFormat(flags, &st, NULL, buf, 255)) { QString format = QString::fromWCharArray(buf); if (substitution() == SAlways) substituteDigits(format); @@ -353,7 +422,7 @@ QVariant QSystemLocalePrivate::toString(const QTime &time, QLocale::FormatType) DWORD flags = 0; wchar_t buf[255]; - if (GetTimeFormat(lcid, flags, &st, NULL, buf, 255)) { + if (getTimeFormat(flags, &st, NULL, buf, 255)) { QString format = QString::fromWCharArray(buf); if (substitution() == SAlways) substituteDigits(format); @@ -371,7 +440,7 @@ QVariant QSystemLocalePrivate::measurementSystem() { wchar_t output[2]; - if (GetLocaleInfo(lcid, LOCALE_IMEASURE, output, 2)) { + if (getLocaleInfo(LOCALE_IMEASURE, output, 2)) { QString iMeasure = QString::fromWCharArray(output); if (iMeasure == QLatin1String("1")) { return QLocale::ImperialSystem; @@ -385,7 +454,7 @@ QVariant QSystemLocalePrivate::amText() { wchar_t output[15]; // maximum length including terminating zero character for Win2003+ - if (GetLocaleInfo(lcid, LOCALE_S1159, output, 15)) { + if (getLocaleInfo(LOCALE_S1159, output, 15)) { return QString::fromWCharArray(output); } @@ -396,7 +465,7 @@ QVariant QSystemLocalePrivate::pmText() { wchar_t output[15]; // maximum length including terminating zero character for Win2003+ - if (GetLocaleInfo(lcid, LOCALE_S2359, output, 15)) { + if (getLocaleInfo(LOCALE_S2359, output, 15)) { return QString::fromWCharArray(output); } @@ -407,7 +476,7 @@ QVariant QSystemLocalePrivate::firstDayOfWeek() { wchar_t output[4]; // maximum length including terminating zero character for Win2003+ - if (GetLocaleInfo(lcid, LOCALE_IFIRSTDAYOFWEEK, output, 4)) + if (getLocaleInfo(LOCALE_IFIRSTDAYOFWEEK, output, 4)) return QString::fromWCharArray(output).toUInt()+1; return 1; @@ -418,20 +487,20 @@ QVariant QSystemLocalePrivate::currencySymbol(QLocale::CurrencySymbolFormat form wchar_t buf[13]; switch (format) { case QLocale::CurrencySymbol: - if (GetLocaleInfo(lcid, LOCALE_SCURRENCY, buf, 13)) + if (getLocaleInfo(LOCALE_SCURRENCY, buf, 13)) return QString::fromWCharArray(buf); break; case QLocale::CurrencyIsoCode: - if (GetLocaleInfo(lcid, LOCALE_SINTLSYMBOL, buf, 9)) + if (getLocaleInfo(LOCALE_SINTLSYMBOL, buf, 9)) return QString::fromWCharArray(buf); break; case QLocale::CurrencyDisplayName: { QVarLengthArray buf(64); - if (!GetLocaleInfo(lcid, LOCALE_SNATIVECURRNAME, buf.data(), buf.size())) { + if (!getLocaleInfo(LOCALE_SNATIVECURRNAME, buf.data(), buf.size())) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) break; buf.resize(255); // should be large enough, right? - if (!GetLocaleInfo(lcid, LOCALE_SNATIVECURRNAME, buf.data(), buf.size())) + if (!getLocaleInfo(LOCALE_SNATIVECURRNAME, buf.data(), buf.size())) break; } return QString::fromWCharArray(buf.data()); @@ -478,14 +547,14 @@ QVariant QSystemLocalePrivate::toCurrencyString(const QSystemLocale::CurrencyToS CURRENCYFMT format; CURRENCYFMT *pformat = NULL; if (!arg.symbol.isEmpty()) { - format.NumDigits = getLocaleInfo_int(lcid, LOCALE_ICURRDIGITS); - format.LeadingZero = getLocaleInfo_int(lcid, LOCALE_ILZERO); - decimalSep = getLocaleInfo(lcid, LOCALE_SMONDECIMALSEP); + format.NumDigits = getLocaleInfo_int(LOCALE_ICURRDIGITS); + format.LeadingZero = getLocaleInfo_int(LOCALE_ILZERO); + decimalSep = getLocaleInfo(LOCALE_SMONDECIMALSEP); format.lpDecimalSep = (wchar_t *)decimalSep.utf16(); - thousandSep = getLocaleInfo(lcid, LOCALE_SMONTHOUSANDSEP); + thousandSep = getLocaleInfo(LOCALE_SMONTHOUSANDSEP); format.lpThousandSep = (wchar_t *)thousandSep.utf16(); - format.NegativeOrder = getLocaleInfo_int(lcid, LOCALE_INEGCURR); - format.PositiveOrder = getLocaleInfo_int(lcid, LOCALE_ICURRENCY); + format.NegativeOrder = getLocaleInfo_int(LOCALE_INEGCURR); + format.PositiveOrder = getLocaleInfo_int(LOCALE_ICURRENCY); format.lpCurrencySymbol = (wchar_t *)arg.symbol.utf16(); // grouping is complicated and ugly: @@ -494,7 +563,7 @@ QVariant QSystemLocalePrivate::toCurrencyString(const QSystemLocale::CurrencyToS // int(30) == "123456,789.00" == string("3;0;0") // int(32) == "12,34,56,789.00" == string("3;2;0") // int(320)== "1234,56,789.00" == string("3;2") - QString groupingStr = getLocaleInfo(lcid, LOCALE_SMONGROUPING); + QString groupingStr = getLocaleInfo(LOCALE_SMONGROUPING); format.Grouping = groupingStr.remove(QLatin1Char(';')).toInt(); if (format.Grouping % 10 == 0) // magic format.Grouping /= 10; @@ -503,13 +572,13 @@ QVariant QSystemLocalePrivate::toCurrencyString(const QSystemLocale::CurrencyToS pformat = &format; } - int ret = ::GetCurrencyFormat(lcid, 0, reinterpret_cast(value.utf16()), + int ret = getCurrencyFormat(0, reinterpret_cast(value.utf16()), pformat, out.data(), out.size()); if (ret == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - ret = ::GetCurrencyFormat(lcid, 0, reinterpret_cast(value.utf16()), + ret = getCurrencyFormat(0, reinterpret_cast(value.utf16()), pformat, out.data(), 0); out.resize(ret); - ::GetCurrencyFormat(lcid, 0, reinterpret_cast(value.utf16()), + getCurrencyFormat(0, reinterpret_cast(value.utf16()), pformat, out.data(), out.size()); } @@ -528,11 +597,13 @@ QVariant QSystemLocalePrivate::uiLanguages() PWSTR pwszLanguagesBuffer, PULONG pcchLanguagesBuffer); static GetUserPreferredUILanguagesFunc GetUserPreferredUILanguages_ptr = 0; +#ifndef Q_OS_WINRT if (!GetUserPreferredUILanguages_ptr) { QSystemLibrary lib(QLatin1String("kernel32")); if (lib.load()) GetUserPreferredUILanguages_ptr = (GetUserPreferredUILanguagesFunc)lib.resolve("GetUserPreferredUILanguages"); } +#endif // !Q_OS_WINRT if (GetUserPreferredUILanguages_ptr) { unsigned long cnt = 0; QVarLengthArray buf(64); @@ -560,8 +631,39 @@ QVariant QSystemLocalePrivate::uiLanguages() } } +#ifndef Q_OS_WINRT // old Windows before Vista return QStringList(QString::fromLatin1(winLangCodeToIsoName(GetUserDefaultUILanguage()))); +#else // !Q_OS_WINRT + QStringList result; +#ifndef Q_OS_WINPHONE + ComPtr appLanguagesStatics; + if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Globalization_ApplicationLanguages).Get(), &appLanguagesStatics))) { + qWarning("Could not obtain ApplicationLanguagesStatic"); + return QStringList(); + } + + ComPtr > languageList; + appLanguagesStatics->get_ManifestLanguages(&languageList); + + if (!languageList) + return QStringList(); + + unsigned int size; + languageList->get_Size(&size); + for (unsigned int i = 0; i < size; ++i) { + HSTRING language; + languageList->GetAt(i, &language); + UINT32 length; + PCWSTR rawString = WindowsGetStringRawBuffer(language, &length); + result << QString::fromWCharArray(rawString, length); + } +#else // !Q_OS_WINPHONE + result << QString::fromWCharArray(lcName); +#endif // Q_OS_WINPHONE + + return result; +#endif // Q_OS_WINRT } QVariant QSystemLocalePrivate::nativeLanguageName() @@ -581,7 +683,11 @@ QVariant QSystemLocalePrivate::nativeCountryName() void QSystemLocalePrivate::update() { +#ifndef Q_OS_WINRT lcid = GetUserDefaultLCID(); +#else + GetUserDefaultLocaleName(lcName, LOCALE_NAME_MAX_LENGTH); +#endif substitutionType = SUnknown; zero = QChar(); } @@ -895,7 +1001,11 @@ static const char *winLangCodeToIsoName(int code) } +#ifndef Q_OS_WINRT static QString winIso639LangName(LCID id) +#else +static QString winIso639LangName(LPWSTR id) +#endif { QString result; @@ -903,7 +1013,11 @@ static QString winIso639LangName(LCID id) // the language code QString lang_code; wchar_t out[256]; - if (GetLocaleInfo(id, LOCALE_ILANGUAGE, out, 255)) // ### shouldn't use them according to msdn +#ifndef Q_OS_WINRT + if (GetLocaleInfo(id, LOCALE_ILANGUAGE, out, 255)) +#else + if (GetLocaleInfoEx(id, LOCALE_ILANGUAGE, out, 255)) +#endif lang_code = QString::fromWCharArray(out); if (!lang_code.isEmpty()) { @@ -926,27 +1040,47 @@ static QString winIso639LangName(LCID id) return result; // not one of the problematic languages - do the usual lookup - if (GetLocaleInfo(id, LOCALE_SISO639LANGNAME , out, 255)) +#ifndef Q_OS_WINRT + if (GetLocaleInfo(id, LOCALE_SISO639LANGNAME, out, 255)) +#else + if (GetLocaleInfoEx(id, LOCALE_SISO639LANGNAME, out, 255)) +#endif result = QString::fromWCharArray(out); return result; } +#ifndef Q_OS_WINRT static QString winIso3116CtryName(LCID id) +#else +static QString winIso3116CtryName(LPWSTR id) +#endif { QString result; wchar_t out[256]; +#ifndef Q_OS_WINRT if (GetLocaleInfo(id, LOCALE_SISO3166CTRYNAME, out, 255)) +#else + if (GetLocaleInfoEx(id, LOCALE_SISO3166CTRYNAME, out, 255)) +#endif result = QString::fromWCharArray(out); return result; } +#ifndef Q_OS_WINRT static QByteArray getWinLocaleName(LCID id) +#else +static QByteArray getWinLocaleName(LPWSTR id) +#endif { QByteArray result; +#ifndef Q_OS_WINRT if (id == LOCALE_USER_DEFAULT) { +#else + if (QString::fromWCharArray(id) == QString::fromWCharArray(LOCALE_NAME_USER_DEFAULT)) { +#endif static QByteArray langEnvVar = qgetenv("LANG"); result = langEnvVar; QString lang, script, cntry; @@ -964,9 +1098,17 @@ static QByteArray getWinLocaleName(LCID id) #if defined(Q_OS_WINCE) result = winLangCodeToIsoName(id != LOCALE_USER_DEFAULT ? id : GetUserDefaultLCID()); -#else +#else // !Q_OS_WINCE +# ifndef Q_OS_WINRT if (id == LOCALE_USER_DEFAULT) id = GetUserDefaultLCID(); +# else // !Q_OS_WINRT + WCHAR lcName[LOCALE_NAME_MAX_LENGTH]; + if (QString::fromWCharArray(id) == QString::fromWCharArray(LOCALE_NAME_USER_DEFAULT)) { + GetUserDefaultLocaleName(lcName, LOCALE_NAME_MAX_LENGTH); + id = lcName; + } +# endif // Q_OS_WINRT QString resultuage = winIso639LangName(id); QString country = winIso3116CtryName(id); result = resultuage.toLatin1(); @@ -974,14 +1116,20 @@ static QByteArray getWinLocaleName(LCID id) result += '_'; result += country.toLatin1(); } -#endif +#endif // !Q_OS_WINCE return result; } Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id) { +#ifndef Q_OS_WINRT return QLocale(QString::fromLatin1(getWinLocaleName(id))); +#else // !Q_OS_WINRT + WCHAR name[LOCALE_NAME_MAX_LENGTH]; + LCIDToLocaleName(id, name, LOCALE_NAME_MAX_LENGTH, 0); + return QLocale(QString::fromLatin1(getWinLocaleName(name))); +#endif // Q_OS_WINRT } QT_END_NAMESPACE diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 239cf0446a..9525a22086 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -5093,7 +5093,11 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1, return ucstrcmp(data1, length1, data2, length2); #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) +#ifndef Q_OS_WINRT int res = CompareString(GetUserDefaultLCID(), 0, (wchar_t*)data1, length1, (wchar_t*)data2, length2); +#else + int res = CompareStringEx(LOCALE_NAME_USER_DEFAULT, 0, (LPCWSTR)data1, length1, (LPCWSTR)data2, length2, NULL, NULL, 0); +#endif switch (res) { case CSTR_LESS_THAN: diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index a645961236..553797a22f 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -127,6 +127,7 @@ else:unix:SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_unix.cpp tools/q else:win32 { SOURCES += tools/qelapsedtimer_win.cpp tools/qlocale_win.cpp !winrt: SOURCES += tools/qtimezoneprivate_win.cpp + winphone: LIBS_PRIVATE += -lWindowsPhoneGlobalizationUtil } else:integrity:SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_unix.cpp else:SOURCES += tools/qelapsedtimer_generic.cpp From 99468bab8aadefbeb125f357589f8e99f262b534 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 5 Apr 2013 22:38:06 -0700 Subject: [PATCH 029/684] Mark some members in the event Unix dispatchers as final Improves the code generation by not making virtual calls where not necessary. Change-Id: I908905f4430359eea3ea8548a35e83e028805911 Reviewed-by: Marc Mutz Reviewed-by: Robin Burchell --- src/corelib/kernel/qeventdispatcher_glib_p.h | 20 ++++++------ src/corelib/kernel/qeventdispatcher_unix_p.h | 32 ++++++++++++-------- 2 files changed, 30 insertions(+), 22 deletions(-) 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 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 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 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 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 From 94abcf98175d927f8e483c8f207c51034fd3b9fc Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 20 Sep 2013 14:41:38 +0200 Subject: [PATCH 030/684] Allow OS synthesized mouse events by default on Windows https://codereview.qt-project.org/#change,66028 fixes Quick2 apps so there will be no need to ignore mouse events synthesized from touches by the OS. The mousefromtouch plugin parameter is changed to nomousefromtouch since mousefromtouch becomes the default. This will restore the OS-provided functionality, like translating tap-and-hold to right clicks, for Quick1 and widget apps. Change-Id: I5554a91a54365b9c72c3ad304010b9fc4e53ab24 Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowsintegration.cpp | 8 +++----- src/plugins/platforms/windows/qwindowsintegration.h | 2 +- src/plugins/platforms/windows/qwindowsmousehandler.cpp | 4 +++- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index d7ac4cfc1e..adac7aa254 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -346,8 +346,8 @@ static inline unsigned parseOptions(const QStringList ¶mList) } } else if (param == QLatin1String("gl=gdi")) { options |= QWindowsIntegration::DisableArb; - } else if (param == QLatin1String("mousefromtouch")) { - options |= QWindowsIntegration::PassOsMouseEventsSynthesizedFromTouch; + } else if (param == QLatin1String("nomousefromtouch")) { + options |= QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch; } } return options; @@ -566,11 +566,9 @@ QVariant QWindowsIntegration::styleHint(QPlatformIntegration::StyleHint hint) co case QPlatformIntegration::SynthesizeMouseFromTouchEvents: #ifdef Q_OS_WINCE // We do not want Qt to synthesize mouse events as Windows also does that. - // Alternatively, Windows-generated touch mouse events can be identified and - // ignored by checking GetMessageExtraInfo() for MI_WP_SIGNATURE (0xFF515700). return false; #else // Q_OS_WINCE - return QVariant(!(d->m_options & PassOsMouseEventsSynthesizedFromTouch)); + return QVariant(bool(d->m_options & DontPassOsMouseEventsSynthesizedFromTouch)); #endif // !Q_OS_WINCE default: break; diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h index 6643b1642e..3911fde388 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.h +++ b/src/plugins/platforms/windows/qwindowsintegration.h @@ -60,7 +60,7 @@ public: DisableArb = 0x4, NoNativeDialogs = 0x8, XpNativeDialogs = 0x10, - PassOsMouseEventsSynthesizedFromTouch = 0x20 // Pass OS-generated mouse events from touch. + DontPassOsMouseEventsSynthesizedFromTouch = 0x20 // Do not pass OS-generated mouse events from touch. }; explicit QWindowsIntegration(const QStringList ¶mList); diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 8516af7bd9..b43aafeba0 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -170,7 +170,9 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized; #ifndef Q_OS_WINCE - static const bool passSynthesizedMouseEvents = QWindowsIntegration::instance()->options() & QWindowsIntegration::PassOsMouseEventsSynthesizedFromTouch; + // Check for events synthesized from touch. Lower byte is touch index, 0 means pen. + static const bool passSynthesizedMouseEvents = + !(QWindowsIntegration::instance()->options() & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch); if (!passSynthesizedMouseEvents) { // Check for events synthesized from touch. Lower 7 bits are touch/pen index, bit 8 indicates touch. // However, when tablet support is active, extraInfo is a packet serial number. This is not a problem From 7f3e3c1099f42cff46bbd267c70587bcf72024fc Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Tue, 8 Oct 2013 13:43:26 +0200 Subject: [PATCH 031/684] Compare QIcon QVariants by their cache key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes it so that two QVariants created from the same QIcon (or from QIcons that were assigned one from eachother) compare to true. Unfortunately creating two QIcons with the same path and comparing them still gives false as they have different cacheKeys Change-Id: Iafe2bc4082a830f9c6469f083c26a7abbe4b35c5 Reviewed-by: Jędrzej Nowacki --- src/gui/kernel/qguivariant.cpp | 2 +- .../gui/kernel/qguivariant/test/black.png | Bin 0 -> 697 bytes .../gui/kernel/qguivariant/test/black2.png | Bin 0 -> 697 bytes .../auto/gui/kernel/qguivariant/test/test.pro | 1 + .../qguivariant/test/tst_qguivariant.cpp | 29 ++++++++++++++++++ .../qguivariant/test/tst_qguivariant.qrc | 6 ++++ .../itemviews/qtreewidget/tst_qtreewidget.cpp | 4 +-- 7 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 tests/auto/gui/kernel/qguivariant/test/black.png create mode 100644 tests/auto/gui/kernel/qguivariant/test/black2.png create mode 100644 tests/auto/gui/kernel/qguivariant/test/tst_qguivariant.qrc diff --git a/src/gui/kernel/qguivariant.cpp b/src/gui/kernel/qguivariant.cpp index 2842211e1d..65f57aed84 100644 --- a/src/gui/kernel/qguivariant.cpp +++ b/src/gui/kernel/qguivariant.cpp @@ -164,7 +164,7 @@ public: #ifndef QT_NO_ICON bool delegate(const QIcon *) { - return false; + return v_cast(Base::m_a)->cacheKey() == v_cast(Base::m_b)->cacheKey(); } #endif bool delegate(const void *p) { return Base::delegate(p); } diff --git a/tests/auto/gui/kernel/qguivariant/test/black.png b/tests/auto/gui/kernel/qguivariant/test/black.png new file mode 100644 index 0000000000000000000000000000000000000000..6c94085ed5b3b7274246af1f45c25b8e380c586c GIT binary patch literal 697 zcmV;q0!ICbP)zxGTA+dZrk?wnYk-<`4-yEDY)i5N znbQmd197sem1M~Pv>Ux?4Qm~|-v|z9^dAV&C%|_`AgQ4MARW=8QjqkiylEjp4&cc{ zITMK(BRPO~DWj+Ya!#&2t4S=xQImX9Z=m2eiZMQZ3?XnyjunriwF;St&VZ?s#4p4O z&q0k`y+K~&ytaUwJ(kK8&P=HEA_6i-Z8?m)Lgl_;CGb(-MHa8QVURiO9o__)#A7HoF z+yG#j*I#P;OtS(cjr#>W4?3_pawl^^uT4$b%2Lv862L$J6U7*l@AI$cwG*|p(5Pq| zfZMcE&oAC4x??~@fqE}Ws8m30+;d@&hRx}8dVIcKuOd$}B-{xwvJRWLw}3B@s4CHG zy2DcFq^1R57^I47^wyHeRhcF3Ejw>!7q6<(Rl*Qv7PXMP`>Nq7)o z)cDR^GS1+C=X(#-N&=n0vmWc6r_BhgLIH;--*^)pf&pVoq!~p=ekvJ#; fIf(-kkdgQUci>@sU(Oae00000NkvXXu0mjf9U?a- literal 0 HcmV?d00001 diff --git a/tests/auto/gui/kernel/qguivariant/test/black2.png b/tests/auto/gui/kernel/qguivariant/test/black2.png new file mode 100644 index 0000000000000000000000000000000000000000..6c94085ed5b3b7274246af1f45c25b8e380c586c GIT binary patch literal 697 zcmV;q0!ICbP)zxGTA+dZrk?wnYk-<`4-yEDY)i5N znbQmd197sem1M~Pv>Ux?4Qm~|-v|z9^dAV&C%|_`AgQ4MARW=8QjqkiylEjp4&cc{ zITMK(BRPO~DWj+Ya!#&2t4S=xQImX9Z=m2eiZMQZ3?XnyjunriwF;St&VZ?s#4p4O z&q0k`y+K~&ytaUwJ(kK8&P=HEA_6i-Z8?m)Lgl_;CGb(-MHa8QVURiO9o__)#A7HoF z+yG#j*I#P;OtS(cjr#>W4?3_pawl^^uT4$b%2Lv862L$J6U7*l@AI$cwG*|p(5Pq| zfZMcE&oAC4x??~@fqE}Ws8m30+;d@&hRx}8dVIcKuOd$}B-{xwvJRWLw}3B@s4CHG zy2DcFq^1R57^I47^wyHeRhcF3Ejw>!7q6<(Rl*Qv7PXMP`>Nq7)o z)cDR^GS1+C=X(#-N&=n0vmWc6r_BhgLIH;--*^)pf&pVoq!~p=ekvJ#; fIf(-kkdgQUci>@sU(Oae00000NkvXXu0mjf9U?a- literal 0 HcmV?d00001 diff --git a/tests/auto/gui/kernel/qguivariant/test/test.pro b/tests/auto/gui/kernel/qguivariant/test/test.pro index d47cf7bf6f..86ab17d9cd 100644 --- a/tests/auto/gui/kernel/qguivariant/test/test.pro +++ b/tests/auto/gui/kernel/qguivariant/test/test.pro @@ -2,5 +2,6 @@ CONFIG += testcase CONFIG += parallel_test TARGET = tst_qguivariant SOURCES += tst_qguivariant.cpp +RESOURCES = tst_qguivariant.qrc INCLUDEPATH += $$PWD/../../../../other/qvariant_common QT += testlib diff --git a/tests/auto/gui/kernel/qguivariant/test/tst_qguivariant.cpp b/tests/auto/gui/kernel/qguivariant/test/tst_qguivariant.cpp index 6fdf3dc843..d5ec9fcfaa 100644 --- a/tests/auto/gui/kernel/qguivariant/test/tst_qguivariant.cpp +++ b/tests/auto/gui/kernel/qguivariant/test/tst_qguivariant.cpp @@ -124,6 +124,8 @@ private slots: void implicitConstruction(); void guiVariantAtExit(); + + void iconEquality(); }; void tst_QGuiVariant::constructor_invalid_data() @@ -702,5 +704,32 @@ void tst_QGuiVariant::guiVariantAtExit() QVERIFY(true); } +void tst_QGuiVariant::iconEquality() +{ + QIcon i; + QVariant a = i; + QVariant b = i; + QCOMPARE(a, b); + + i = QIcon(":/black.png"); + a = i; + QVERIFY(a != b); + + b = a; + QCOMPARE(a, b); + + i = QIcon(":/black2.png"); + a = i; + QVERIFY(a != b); + + b = i; + QCOMPARE(a, b); + + // This is a "different" QIcon + // even if the contents are the same + b = QIcon(":/black2.png"); + QVERIFY(a != b); +} + QTEST_MAIN(tst_QGuiVariant) #include "tst_qguivariant.moc" diff --git a/tests/auto/gui/kernel/qguivariant/test/tst_qguivariant.qrc b/tests/auto/gui/kernel/qguivariant/test/tst_qguivariant.qrc new file mode 100644 index 0000000000..15cfde5788 --- /dev/null +++ b/tests/auto/gui/kernel/qguivariant/test/tst_qguivariant.qrc @@ -0,0 +1,6 @@ + + +black.png +black2.png + + diff --git a/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp index 83ba1ddcda..d2625c400a 100644 --- a/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp +++ b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp @@ -1758,9 +1758,7 @@ void tst_QTreeWidget::setData() QCOMPARE(qvariant_cast(args.at(0)), item); QCOMPARE(qvariant_cast(args.at(1)), j); item->setIcon(j, icon); - // #### shouldn't cause dataChanged() - QCOMPARE(itemChangedSpy.count(), 1); - itemChangedSpy.clear(); + QCOMPARE(itemChangedSpy.count(), 0); QString toolTip = QString("toolTip %0").arg(i); item->setToolTip(j, toolTip); From e31be2964e9b06baa887b600d7bda2e8b8ff82a4 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Mon, 2 Sep 2013 12:57:51 +0200 Subject: [PATCH 032/684] Added initial file system support for winrt While some functionality is not available for winphone (QFileSystemEngine::tempPath), some functionality can be fully supported. Other cases like checking for stale processes which is needed by QLockFile cannot be covered that easily as obtaining information about other processes is limited due to sandboxing. Change-Id: I9ea80ae2b421eea1ddfd4c5bc2f4b6f8adaee85f Done-with: Kamil Trzcinski Reviewed-by: Friedemann Kleint Reviewed-by: Maurice Kalinowski --- src/corelib/io/qfilesystemengine_win.cpp | 157 ++++++++++++++++++--- src/corelib/io/qfilesystemiterator_win.cpp | 14 +- src/corelib/io/qfilesystemmetadata_p.h | 6 +- src/corelib/io/qfsfileengine_win.cpp | 73 +++++++--- src/corelib/io/qlockfile_win.cpp | 14 +- src/corelib/io/qtemporaryfile.cpp | 15 +- 6 files changed, 233 insertions(+), 46 deletions(-) diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index 57231b57a9..105c8d34dd 100644 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -63,13 +63,26 @@ # include #endif #include -#include +#ifndef Q_OS_WINRT +# include +# include +#endif #include -#include #include #include -#define SECURITY_WIN32 -#include +#ifndef Q_OS_WINRT +# define SECURITY_WIN32 +# include +#else // !Q_OS_WINRT +# include +# include +# include + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Storage; +#endif // Q_OS_WINRT #ifndef SPI_GETPLATFORMTYPE #define SPI_GETPLATFORMTYPE 257 @@ -141,7 +154,7 @@ QT_BEGIN_NAMESPACE Q_CORE_EXPORT int qt_ntfs_permission_lookup = 0; -#if defined(Q_OS_WINCE) +#if defined(Q_OS_WINCE) || defined(Q_OS_WINRT) static QString qfsPrivateCurrentDir = QLatin1String(""); // As none of the functions we try to resolve do exist on Windows CE // we use QT_NO_LIBRARY to shorten everything up a little bit. @@ -289,14 +302,14 @@ static bool resolveUNCLibs() } #endif triedResolve = true; -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) HINSTANCE hLib = QSystemLibrary::load(L"Netapi32"); if (hLib) { ptrNetShareEnum = (PtrNetShareEnum)GetProcAddress(hLib, "NetShareEnum"); if (ptrNetShareEnum) ptrNetApiBufferFree = (PtrNetApiBufferFree)GetProcAddress(hLib, "NetApiBufferFree"); } -#endif +#endif // !Q_OS_WINCE && !Q_OS_WINRT } return ptrNetShareEnum && ptrNetApiBufferFree; } @@ -304,7 +317,7 @@ static bool resolveUNCLibs() static QString readSymLink(const QFileSystemEntry &link) { QString result; -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) HANDLE handle = CreateFile((wchar_t*)link.nativeFilePath().utf16(), FILE_READ_EA, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, @@ -347,11 +360,11 @@ static QString readSymLink(const QFileSystemEntry &link) result.replace(0,matchVolName.matchedLength(), QString::fromWCharArray(buffer)); } } -#endif +#endif // !Q_OS_WINCE && !Q_OS_WINRT } #else Q_UNUSED(link); -#endif // Q_OS_WINCE +#endif // Q_OS_WINCE || Q_OS_WINRT return result; } @@ -432,7 +445,11 @@ static inline bool getFindData(QString path, WIN32_FIND_DATA &findData) // can't handle drives if (!path.endsWith(QLatin1Char(':'))) { +#ifndef Q_OS_WINRT HANDLE hFind = ::FindFirstFile((wchar_t*)path.utf16(), &findData); +#else + HANDLE hFind = ::FindFirstFileEx((const wchar_t*)path.utf16(), FindExInfoStandard, &findData, FindExSearchNameMatch, NULL, 0); +#endif if (hFind != INVALID_HANDLE_VALUE) { ::FindClose(hFind); return true; @@ -506,7 +523,7 @@ QString QFileSystemEngine::nativeAbsoluteFilePath(const QString &path) { // can be //server or //server/share QString absPath; -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) QVarLengthArray buf(qMax(MAX_PATH, path.size() + 1)); wchar_t *fileName = 0; DWORD retLen = GetFullPathName((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName); @@ -516,12 +533,17 @@ QString QFileSystemEngine::nativeAbsoluteFilePath(const QString &path) } if (retLen != 0) absPath = QString::fromWCharArray(buf.data(), retLen); -#else +#elif !defined(Q_OS_WINCE) + if (QDir::isRelativePath(path)) + absPath = QDir::toNativeSeparators(QDir::cleanPath(QDir::currentPath() + QLatin1Char('/') + path)); + else + absPath = QDir::toNativeSeparators(QDir::cleanPath(path)); +#else // Q_OS_WINRT if (path.startsWith(QLatin1Char('/')) || path.startsWith(QLatin1Char('\\'))) absPath = QDir::toNativeSeparators(path); else absPath = QDir::toNativeSeparators(QDir::cleanPath(qfsPrivateCurrentDir + QLatin1Char('/') + path)); -#endif +#endif // Q_OS_WINCE // This is really ugly, but GetFullPathName strips off whitespace at the end. // If you for instance write ". " in the lineedit of QFileDialog, // (which is an invalid filename) this function will strip the space off and viola, @@ -548,9 +570,17 @@ QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry) ret = entry.filePath(); #endif } else { +#ifndef Q_OS_WINRT ret = QDir::cleanPath(QDir::currentPath() + QLatin1Char('/') + entry.filePath()); +#else + // Some WinRT APIs do not support absolute paths (due to sandboxing). + // Thus the port uses the executable's directory as its root directory + // and treats paths relative to that as absolute paths. + ret = QDir::cleanPath(QDir::current().relativeFilePath(entry.filePath())); +#endif } +#ifndef Q_OS_WINRT // The path should be absolute at this point. // From the docs : // Absolute paths begin with the directory separator "/" @@ -563,6 +593,7 @@ QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry) // Force uppercase drive letters. ret[0] = ret.at(0).toUpper(); } +#endif // !Q_OS_WINRT return QFileSystemEntry(ret, QFileSystemEntry::FromInternalPath()); } @@ -590,18 +621,24 @@ typedef struct _FILE_ID_INFO { static inline QByteArray fileId(HANDLE handle) { QByteArray result; +#ifndef Q_OS_WINRT BY_HANDLE_FILE_INFORMATION info; if (GetFileInformationByHandle(handle, &info)) { result = QByteArray::number(uint(info.nFileIndexLow), 16); result += ':'; result += QByteArray::number(uint(info.nFileIndexHigh), 16); } +#else // !Q_OS_WINRT + Q_UNUSED(handle); + Q_UNIMPLEMENTED(); +#endif // Q_OS_WINRT return result; } // File ID for Windows starting from version 8. QByteArray fileIdWin8(HANDLE handle) { +#ifndef Q_OS_WINRT typedef BOOL (WINAPI* GetFileInformationByHandleExType)(HANDLE, Q_FILE_INFO_BY_HANDLE_CLASS, void *, DWORD); // Dynamically resolve GetFileInformationByHandleEx (Vista onwards). @@ -621,6 +658,16 @@ QByteArray fileIdWin8(HANDLE handle) result += QByteArray((char *)&infoEx.FileId, sizeof(infoEx.FileId)).toHex(); } } +#else // !Q_OS_WINRT + QByteArray result; + FILE_ID_INFO infoEx; + if (GetFileInformationByHandleEx(handle, FileIdInfo, + &infoEx, sizeof(FILE_ID_INFO))) { + result = QByteArray::number(infoEx.VolumeSerialNumber, 16); + result += ':'; + result += QByteArray((char *)infoEx.FileId.Identifier, sizeof(infoEx.FileId.Identifier)).toHex(); + } +#endif // Q_OS_WINRT return result; } #endif // !Q_OS_WINCE @@ -631,8 +678,13 @@ QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry) #ifndef Q_OS_WINCE QByteArray result; const HANDLE handle = +#ifndef Q_OS_WINRT CreateFile((wchar_t*)entry.nativeFilePath().utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); +#else // !Q_OS_WINRT + CreateFile2((const wchar_t*)entry.nativeFilePath().utf16(), GENERIC_READ, + FILE_SHARE_READ, OPEN_EXISTING, NULL); +#endif // Q_OS_WINRT if (handle) { result = QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS8 ? fileIdWin8(handle) : fileId(handle); @@ -810,7 +862,7 @@ static bool tryDriveUNCFallback(const QFileSystemEntry &fname, QFileSystemMetaDa { bool entryExists = false; DWORD fileAttrib = 0; -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) if (fname.isDriveRoot()) { // a valid drive ?? DWORD drivesBitmask = ::GetLogicalDrives(); @@ -851,7 +903,7 @@ static bool tryDriveUNCFallback(const QFileSystemEntry &fname, QFileSystemMetaDa fileAttrib = FILE_ATTRIBUTE_DIRECTORY; entryExists = true; } -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) } #endif if (entryExists) @@ -894,12 +946,27 @@ bool QFileSystemEngine::fillMetaData(HANDLE fHandle, QFileSystemMetaData &data, { data.entryFlags &= ~what; clearWinStatData(data); +#ifndef Q_OS_WINRT BY_HANDLE_FILE_INFORMATION fileInfo; UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); if (GetFileInformationByHandle(fHandle , &fileInfo)) { data.fillFromFindInfo(fileInfo); } SetErrorMode(oldmode); +#else // !Q_OS_WINRT + FILE_FULL_DIR_INFO fileInfo; + if (GetFileInformationByHandleEx(fHandle, FileFullDirectoryInfo, &fileInfo, sizeof(fileInfo))) { + data.fillFromFileAttribute(fileInfo.FileAttributes); + data.creationTime_.dwHighDateTime = fileInfo.CreationTime.HighPart; + data.creationTime_.dwLowDateTime = fileInfo.CreationTime.LowPart; + data.lastAccessTime_.dwHighDateTime = fileInfo.LastAccessTime.HighPart; + data.lastAccessTime_.dwLowDateTime = fileInfo.LastAccessTime.LowPart; + data.lastWriteTime_.dwHighDateTime = fileInfo.LastWriteTime.HighPart; + data.lastWriteTime_.dwLowDateTime = fileInfo.LastWriteTime.LowPart; + data.fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY ? data.size_ = 0 : data.size_ = fileInfo.AllocationSize.QuadPart; + data.knownFlagsMask |= data.Times | data.SizeAttribute; + } +#endif // Q_OS_WINRT return data.hasFlags(what); } @@ -931,7 +998,9 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM } if (what & QFileSystemMetaData::WinStatFlags) { +#ifndef Q_OS_WINRT UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); +#endif clearWinStatData(data); WIN32_FIND_DATA findData; // The memory structure for WIN32_FIND_DATA is same as WIN32_FILE_ATTRIBUTE_DATA @@ -943,11 +1012,15 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM } else { if (!tryFindFallback(fname, data)) if (!tryDriveUNCFallback(fname, data)) { +#ifndef Q_OS_WINRT SetErrorMode(oldmode); +#endif return false; } } +#ifndef Q_OS_WINRT SetErrorMode(oldmode); +#endif } if (what & QFileSystemMetaData::Permissions) @@ -1000,7 +1073,14 @@ static bool isDirPath(const QString &dirPath, bool *existed) if (path.length() == 2 && path.at(1) == QLatin1Char(':')) path += QLatin1Char('\\'); +#ifndef Q_OS_WINRT DWORD fileAttrib = ::GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16()); +#else // Q_OS_WINRT + DWORD fileAttrib = INVALID_FILE_ATTRIBUTES; + WIN32_FILE_ATTRIBUTE_DATA data; + if (::GetFileAttributesEx((const wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), GetFileExInfoStandard, &data)) + fileAttrib = data.dwFileAttributes; +#endif // Q_OS_WINRT if (fileAttrib == INVALID_FILE_ATTRIBUTES) { int errorCode = GetLastError(); if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) { @@ -1152,12 +1232,13 @@ QString QFileSystemEngine::homePath() QString QFileSystemEngine::tempPath() { QString ret; +#ifndef Q_OS_WINRT wchar_t tempPath[MAX_PATH]; const DWORD len = GetTempPath(MAX_PATH, tempPath); #ifdef Q_OS_WINCE if (len) ret = QString::fromWCharArray(tempPath, len); -#else +#else // Q_OS_WINCE if (len) { // GetTempPath() can return short names, expand. wchar_t longTempPath[MAX_PATH]; const DWORD longLen = GetLongPathName(tempPath, longTempPath, MAX_PATH); @@ -1165,12 +1246,33 @@ QString QFileSystemEngine::tempPath() QString::fromWCharArray(longTempPath, longLen) : QString::fromWCharArray(tempPath, len); } -#endif +#endif // !Q_OS_WINCE if (!ret.isEmpty()) { while (ret.endsWith(QLatin1Char('\\'))) ret.chop(1); ret = QDir::fromNativeSeparators(ret); } +#else // !Q_OS_WINRT + // According to http://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.applicationdata.temporaryfolder.aspx + // the API is not available on winphone which should cause one of the functions + // below to fail + ComPtr applicationDataStatics; + if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_ApplicationData).Get(), &applicationDataStatics))) + return ret; + ComPtr applicationData; + if (FAILED(applicationDataStatics->get_Current(&applicationData))) + return ret; + ComPtr tempFolder; + if (FAILED(applicationData->get_TemporaryFolder(&tempFolder))) + return ret; + ComPtr tempFolderItem; + if (FAILED(tempFolder.As(&tempFolderItem))) + return ret; + HSTRING path; + if (FAILED(tempFolderItem->get_Path(&path))) + return ret; + ret = QString::fromWCharArray(WindowsGetStringRawBuffer(path, nullptr)); +#endif // Q_OS_WINRT if (ret.isEmpty()) { #if !defined(Q_OS_WINCE) ret = QLatin1String("C:/tmp"); @@ -1189,7 +1291,7 @@ bool QFileSystemEngine::setCurrentPath(const QFileSystemEntry &entry) if(!(meta.exists() && meta.isDirectory())) return false; -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) //TODO: this should really be using nativeFilePath(), but that returns a path in long format \\?\c:\foo //which causes many problems later on when it's returned through currentPath() return ::SetCurrentDirectory(reinterpret_cast(QDir::toNativeSeparators(entry.filePath()).utf16())) != 0; @@ -1202,7 +1304,7 @@ bool QFileSystemEngine::setCurrentPath(const QFileSystemEntry &entry) QFileSystemEntry QFileSystemEngine::currentPath() { QString ret; -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) DWORD size = 0; wchar_t currentName[PATH_MAX]; size = ::GetCurrentDirectory(PATH_MAX, currentName); @@ -1218,13 +1320,13 @@ QFileSystemEntry QFileSystemEngine::currentPath() } if (ret.length() >= 2 && ret[1] == QLatin1Char(':')) ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters. -#else +#else // !Q_OS_WINCE && !Q_OS_WINRT //TODO - a race condition exists when using currentPath / setCurrentPath from multiple threads if (qfsPrivateCurrentDir.isEmpty()) qfsPrivateCurrentDir = QCoreApplication::applicationDirPath(); ret = qfsPrivateCurrentDir; -#endif +#endif // Q_OS_WINCE || Q_OS_WINRT return QFileSystemEntry(ret, QFileSystemEntry::FromNativePath()); } @@ -1242,8 +1344,16 @@ bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSy //static bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error) { +#ifndef Q_OS_WINRT bool ret = ::CopyFile((wchar_t*)source.nativeFilePath().utf16(), (wchar_t*)target.nativeFilePath().utf16(), true) != 0; +#else // !Q_OS_WINRT + COPYFILE2_EXTENDED_PARAMETERS copyParams = { + sizeof(copyParams), COPY_FILE_FAIL_IF_EXISTS, NULL, NULL, NULL + }; + bool ret = ::CopyFile2((const wchar_t*)source.nativeFilePath().utf16(), + (const wchar_t*)target.nativeFilePath().utf16(), ©Params) != 0; +#endif // Q_OS_WINRT if(!ret) error = QSystemError(::GetLastError(), QSystemError::NativeError); return ret; @@ -1252,8 +1362,13 @@ bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSyst //static bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error) { +#ifndef Q_OS_WINRT bool ret = ::MoveFile((wchar_t*)source.nativeFilePath().utf16(), (wchar_t*)target.nativeFilePath().utf16()) != 0; +#else // !Q_OS_WINRT + bool ret = ::MoveFileEx((const wchar_t*)source.nativeFilePath().utf16(), + (const wchar_t*)target.nativeFilePath().utf16(), 0) != 0; +#endif // Q_OS_WINRT if(!ret) error = QSystemError(::GetLastError(), QSystemError::NativeError); return ret; diff --git a/src/corelib/io/qfilesystemiterator_win.cpp b/src/corelib/io/qfilesystemiterator_win.cpp index 90232f7cfc..dda96bd45a 100644 --- a/src/corelib/io/qfilesystemiterator_win.cpp +++ b/src/corelib/io/qfilesystemiterator_win.cpp @@ -39,10 +39,12 @@ ** ****************************************************************************/ -#if _WIN32_WINNT < 0x0500 -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0500 -#endif +#if !defined(WINAPI_FAMILY) +# if _WIN32_WINNT < 0x0500 +# undef _WIN32_WINNT +# define _WIN32_WINNT 0x0500 +# endif // _WIN32_WINNT < 0x500 +#endif // !WINAPI_FAMILY #include "qfilesystemiterator_p.h" #include "qfilesystemengine_p.h" @@ -73,6 +75,10 @@ QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Fi if (!nativePath.endsWith(QLatin1Char('\\'))) nativePath.append(QLatin1Char('\\')); nativePath.append(QLatin1Char('*')); +#ifdef Q_OS_WINRT + if (nativePath.startsWith(QLatin1Char('\\'))) + nativePath.remove(0, 1); +#endif if (!dirPath.endsWith(QLatin1Char('/'))) dirPath.append(QLatin1Char('/')); if ((filters & (QDir::Dirs|QDir::Drives)) && (!(filters & (QDir::Files)))) diff --git a/src/corelib/io/qfilesystemmetadata_p.h b/src/corelib/io/qfilesystemmetadata_p.h index 1abc9b7ec4..de79ec32d3 100644 --- a/src/corelib/io/qfilesystemmetadata_p.h +++ b/src/corelib/io/qfilesystemmetadata_p.h @@ -219,7 +219,9 @@ public: #if defined(Q_OS_WIN) inline void fillFromFileAttribute(DWORD fileAttribute, bool isDriveRoot = false); inline void fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType = false, bool isDriveRoot = false); +# ifndef Q_OS_WINRT inline void fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo); +# endif #endif private: friend class QFileSystemEngine; @@ -340,6 +342,7 @@ inline void QFileSystemMetaData::fillFromFindData(WIN32_FIND_DATA &findData, boo } } +#ifndef Q_OS_WINRT inline void QFileSystemMetaData::fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo) { fillFromFileAttribute(fileInfo.dwFileAttributes); @@ -355,7 +358,8 @@ inline void QFileSystemMetaData::fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fi } knownFlagsMask |= Times | SizeAttribute; } -#endif +#endif // !Q_OS_WINRT +#endif // Q_OS_WIN QT_END_NAMESPACE diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index 2b38019674..c974daab06 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -60,14 +60,18 @@ # include #endif #include -#include +#ifndef Q_OS_WINRT +# include +# include +#endif #include -#include #include #include #include -#define SECURITY_WIN32 -#include +#ifndef Q_OS_WINRT +# define SECURITY_WIN32 +# include +#endif #ifndef PATH_MAX #define PATH_MAX FILENAME_MAX @@ -93,7 +97,7 @@ QString QFSFileEnginePrivate::longFileName(const QString &path) return path; QString absPath = QFileSystemEngine::nativeAbsoluteFilePath(path); -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) QString prefix = QLatin1String("\\\\?\\"); if (isUncPath(absPath)) { prefix.append(QLatin1String("UNC\\")); // "\\\\?\\UNC\\" @@ -121,11 +125,12 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) if (openMode & QIODevice::WriteOnly) accessRights |= GENERIC_WRITE; - SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE }; // WriteOnly can create files, ReadOnly cannot. DWORD creationDisp = (openMode & QIODevice::WriteOnly) ? OPEN_ALWAYS : OPEN_EXISTING; // Create the file handle. +#ifndef Q_OS_WINRT + SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE }; fileHandle = CreateFile((const wchar_t*)fileEntry.nativeFilePath().utf16(), accessRights, shareMode, @@ -133,6 +138,13 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) creationDisp, FILE_ATTRIBUTE_NORMAL, NULL); +#else // !Q_OS_WINRT + fileHandle = CreateFile2((const wchar_t*)fileEntry.nativeFilePath().utf16(), + accessRights, + shareMode, + creationDisp, + NULL); +#endif // Q_OS_WINRT // Bail out on error. if (fileHandle == INVALID_HANDLE_VALUE) { @@ -473,7 +485,7 @@ int QFSFileEnginePrivate::nativeHandle() const */ bool QFSFileEnginePrivate::nativeIsSequential() const { -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) HANDLE handle = fileHandle; if (fh || fd != -1) handle = (HANDLE)_get_osfhandle(fh ? QT_FILENO(fh) : fd); @@ -577,7 +589,7 @@ bool QFSFileEngine::setCurrentPath(const QString &path) QString QFSFileEngine::currentPath(const QString &fileName) { -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) QString ret; //if filename is a drive: then get the pwd of that drive if (fileName.length() >= 2 && @@ -596,10 +608,10 @@ QString QFSFileEngine::currentPath(const QString &fileName) if (ret.length() >= 2 && ret[1] == QLatin1Char(':')) ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters. return ret; -#else +#else // !Q_OS_WINCE && !Q_OS_WINRT Q_UNUSED(fileName); return QFileSystemEngine::currentPath().filePath(); -#endif +#endif // Q_OS_WINCE || Q_OS_WINRT } QString QFSFileEngine::homePath() @@ -620,7 +632,7 @@ QString QFSFileEngine::tempPath() QFileInfoList QFSFileEngine::drives() { QFileInfoList ret; -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) #if defined(Q_OS_WIN32) quint32 driveBits = (quint32) GetLogicalDrives() & 0x3ffffff; #endif @@ -633,10 +645,10 @@ QFileInfoList QFSFileEngine::drives() driveBits = driveBits >> 1; } return ret; -#else +#else // !Q_OS_WINCE && !Q_OS_WINRT ret.append(QFileInfo(QLatin1String("/"))); return ret; -#endif +#endif // Q_OS_WINCE || Q_OS_WINRT } bool QFSFileEnginePrivate::doStat(QFileSystemMetaData::MetaDataFlags flags) const @@ -661,7 +673,7 @@ bool QFSFileEnginePrivate::doStat(QFileSystemMetaData::MetaDataFlags flags) cons bool QFSFileEngine::link(const QString &newName) { -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) #if !defined(QT_NO_LIBRARY) bool ret = false; @@ -707,7 +719,7 @@ bool QFSFileEngine::link(const QString &newName) Q_UNUSED(newName); return false; #endif // QT_NO_LIBRARY -#else +#elif defined(Q_OS_WINCE) QString linkName = newName; linkName.replace(QLatin1Char('/'), QLatin1Char('\\')); if (!linkName.endsWith(QLatin1String(".lnk"))) @@ -720,7 +732,11 @@ bool QFSFileEngine::link(const QString &newName) if (!ret) setError(QFile::RenameError, qt_error_string()); return ret; -#endif // Q_OS_WINCE +#else // Q_OS_WINCE + Q_UNUSED(newName); + Q_UNIMPLEMENTED(); + return false; +#endif // Q_OS_WINRT } /*! @@ -937,6 +953,7 @@ QDateTime QFSFileEngine::fileTime(FileTime time) const uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags) { +#ifndef Q_OS_WINPHONE Q_Q(QFSFileEngine); Q_UNUSED(flags); if (openMode == QFile::NotOpen) { @@ -980,7 +997,11 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, // first create the file mapping handle DWORD protection = (openMode & QIODevice::WriteOnly) ? PAGE_READWRITE : PAGE_READONLY; +#ifndef Q_OS_WINRT mapHandle = ::CreateFileMapping(handle, 0, protection, 0, 0, 0); +#else + mapHandle = ::CreateFileMappingFromApp(handle, 0, protection, 0, 0); +#endif if (mapHandle == NULL) { q->setError(QFile::PermissionsError, qt_error_string()); #ifdef Q_USE_DEPRECATED_MAP_API @@ -998,15 +1019,23 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, DWORD offsetHi = offset >> 32; DWORD offsetLo = offset & Q_UINT64_C(0xffffffff); SYSTEM_INFO sysinfo; +#ifndef Q_OS_WINRT ::GetSystemInfo(&sysinfo); +#else + ::GetNativeSystemInfo(&sysinfo); +#endif DWORD mask = sysinfo.dwAllocationGranularity - 1; DWORD extra = offset & mask; if (extra) offsetLo &= ~mask; // attempt to create the map +#ifndef Q_OS_WINRT LPVOID mapAddress = ::MapViewOfFile(mapHandle, access, offsetHi, offsetLo, size + extra); +#else + LPVOID mapAddress = ::MapViewOfFileFromApp(mapHandle, access, offset, size); +#endif if (mapAddress) { uchar *address = extra + static_cast(mapAddress); maps[address] = extra; @@ -1025,11 +1054,18 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, ::CloseHandle(mapHandle); mapHandle = NULL; +#else // !Q_OS_WINPHONE + Q_UNUSED(offset); + Q_UNUSED(size); + Q_UNUSED(flags); + Q_UNIMPLEMENTED(); +#endif // Q_OS_WINPHONE return 0; } bool QFSFileEnginePrivate::unmap(uchar *ptr) { +#ifndef Q_OS_WINPHONE Q_Q(QFSFileEngine); if (!maps.contains(ptr)) { q->setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED)); @@ -1048,6 +1084,11 @@ bool QFSFileEnginePrivate::unmap(uchar *ptr) } return true; +#else // !Q_OS_WINPHONE + Q_UNUSED(ptr); + Q_UNIMPLEMENTED(); + return false; +#endif // Q_OS_WINPHONE } QT_END_NAMESPACE diff --git a/src/corelib/io/qlockfile_win.cpp b/src/corelib/io/qlockfile_win.cpp index b5f6d9f3da..28f6b02a64 100644 --- a/src/corelib/io/qlockfile_win.cpp +++ b/src/corelib/io/qlockfile_win.cpp @@ -52,7 +52,6 @@ QT_BEGIN_NAMESPACE QLockFile::LockError QLockFilePrivate::tryLock_sys() { - SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE }; const QFileSystemEntry fileEntry(fileName); // When writing, allow others to read. // When reading, QFile will allow others to read and write, all good. @@ -60,6 +59,8 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys() // but Windows doesn't allow recreating it while this handle is open anyway, // so this would only create confusion (can't lock, but no lock file to read from). const DWORD dwShareMode = FILE_SHARE_READ; +#ifndef Q_OS_WINRT + SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE }; HANDLE fh = CreateFile((const wchar_t*)fileEntry.nativeFilePath().utf16(), GENERIC_WRITE, dwShareMode, @@ -67,6 +68,13 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys() CREATE_NEW, // error if already exists FILE_ATTRIBUTE_NORMAL, NULL); +#else // !Q_OS_WINRT + HANDLE fh = CreateFile2((const wchar_t*)fileEntry.nativeFilePath().utf16(), + GENERIC_WRITE, + dwShareMode, + CREATE_NEW, // error if already exists + NULL); +#endif // Q_OS_WINRT if (fh == INVALID_HANDLE_VALUE) { const DWORD lastError = GetLastError(); switch (lastError) { @@ -112,6 +120,9 @@ bool QLockFilePrivate::isApparentlyStale() const if (!getLockInfo(&pid, &hostname, &appname)) return false; + // On WinRT there seems to be no way of obtaining information about other + // processes due to sandboxing +#ifndef Q_OS_WINRT HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); if (!procHandle) return true; @@ -120,6 +131,7 @@ bool QLockFilePrivate::isApparentlyStale() const ::CloseHandle(procHandle); if (dwR == WAIT_TIMEOUT) return true; +#endif // !Q_OS_WINRT const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime()); return staleLockTime > 0 && age > staleLockTime; } diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index c2f421843c..4d672f0689 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -151,18 +151,27 @@ static bool createFileFromTemplate(NativeFileHandle &file, for (;;) { // Atomically create file and obtain handle #if defined(Q_OS_WIN) +# ifndef Q_OS_WINRT file = CreateFile((const wchar_t *)path.constData(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); +# else // !Q_OS_WINRT + file = CreateFile2((const wchar_t *)path.constData(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, CREATE_NEW, + NULL); +# endif // Q_OS_WINRT if (file != INVALID_HANDLE_VALUE) return true; DWORD err = GetLastError(); if (err == ERROR_ACCESS_DENIED) { - DWORD attributes = GetFileAttributes((const wchar_t *)path.constData()); - if (attributes == INVALID_FILE_ATTRIBUTES) { + WIN32_FILE_ATTRIBUTE_DATA attributes; + if (!GetFileAttributesEx((const wchar_t *)path.constData(), + GetFileExInfoStandard, &attributes) + || attributes.dwFileAttributes == INVALID_FILE_ATTRIBUTES) { // Potential write error (read-only parent directory, etc.). error = QSystemError(err, QSystemError::NativeError); return false; @@ -336,7 +345,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode) d->fileEntry = QFileSystemEntry(filename, QFileSystemEntry::FromNativePath()); -#if !defined(Q_OS_WIN) +#if !defined(Q_OS_WIN) || defined(Q_OS_WINRT) d->closeFileHandle = true; #endif From df25dfef46b1174e6f545e681be3f0ef1541fd75 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Sun, 6 Oct 2013 15:37:33 +0300 Subject: [PATCH 033/684] WinRT QPA: Fix touch release on phone The IsInContact API is not reliable on phone, so use IsLeftButtonPressed instead. Change-Id: If17089f976586879355f127dadbe394b57afe3c3 Reviewed-by: Maurice Kalinowski Reviewed-by: Oliver Wolff Reviewed-by: Friedemann Kleint --- src/plugins/platforms/winrt/qwinrtscreen.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 93c2736238..59182ca183 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -866,7 +866,11 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *a QHash::iterator it = m_touchPoints.find(id); if (it != m_touchPoints.end()) { boolean isPressed; +#ifndef Q_OS_WINPHONE pointerPoint->get_IsInContact(&isPressed); +#else + properties->get_IsLeftButtonPressed(&isPressed); // IsInContact not reliable on phone +#endif it.value().state = isPressed ? Qt::TouchPointMoved : Qt::TouchPointReleased; } else { it = m_touchPoints.insert(id, QWindowSystemInterface::TouchPoint()); From 6719307a891e3e935e5a589aaceeefb884772378 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Thu, 10 Oct 2013 09:17:52 +0200 Subject: [PATCH 034/684] WinRT: Adopt new event dispatcher approach for WinRT plugin Change-Id: I5605cbe926b57b981071d71187aca6af5d2e6269 Reviewed-by: Andrew Knight Reviewed-by: Friedemann Kleint --- src/plugins/platforms/winrt/qwinrtintegration.cpp | 13 +++++-------- src/plugins/platforms/winrt/qwinrtintegration.h | 3 +-- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp index 9113ffeb19..4cc7eb31f1 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.cpp +++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp @@ -103,12 +103,6 @@ QWinRTIntegration::QWinRTIntegration() m_screen = new QWinRTScreen(window); screenAdded(m_screen); - // Get event dispatcher - ICoreDispatcher *dispatcher; - if (FAILED(window->get_Dispatcher(&dispatcher))) - qCritical("Could not capture UI Dispatcher"); - m_eventDispatcher = new QWinRTEventDispatcher(dispatcher); - m_success = true; } @@ -117,9 +111,12 @@ QWinRTIntegration::~QWinRTIntegration() Windows::Foundation::Uninitialize(); } -QAbstractEventDispatcher *QWinRTIntegration::guiThreadEventDispatcher() const +QAbstractEventDispatcher *QWinRTIntegration::createEventDispatcher() const { - return m_eventDispatcher; + ICoreDispatcher *dispatcher; + if (FAILED(m_screen->coreWindow()->get_Dispatcher(&dispatcher))) + qCritical("Could not capture UI Dispatcher"); + return new QWinRTEventDispatcher(dispatcher); } bool QWinRTIntegration::hasCapability(QPlatformIntegration::Capability cap) const diff --git a/src/plugins/platforms/winrt/qwinrtintegration.h b/src/plugins/platforms/winrt/qwinrtintegration.h index b53c1cf7d2..6cf2c3e5f2 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.h +++ b/src/plugins/platforms/winrt/qwinrtintegration.h @@ -68,7 +68,7 @@ public: QPlatformWindow *createPlatformWindow(QWindow *window) const; QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const; QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const; - QAbstractEventDispatcher *guiThreadEventDispatcher() const; + QAbstractEventDispatcher *createEventDispatcher() const; QPlatformFontDatabase *fontDatabase() const; QPlatformInputContext *inputContext() const; QPlatformServices *services() const; @@ -76,7 +76,6 @@ public: private: bool m_success; QWinRTScreen *m_screen; - QAbstractEventDispatcher *m_eventDispatcher; QPlatformFontDatabase *m_fontDatabase; QPlatformServices *m_services; }; From 63348f43adc93d1c497cb86631d6b7765cc376b2 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Sun, 6 Oct 2013 15:11:36 +0300 Subject: [PATCH 035/684] WinRT: Improve orientation handling Support setting the update mask. Change-Id: I88f4dddd9af5203ec47c70ad3381436caf140fef Reviewed-by: Andrew Knight --- src/plugins/platforms/winrt/qwinrtscreen.cpp | 48 +++++++++++++------- src/plugins/platforms/winrt/qwinrtscreen.h | 1 + 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 59182ca183..8bc778ef11 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -84,21 +84,32 @@ typedef ITypedEventHandler A QT_BEGIN_NAMESPACE -static inline Qt::ScreenOrientation qOrientationFromNative(DisplayOrientations orientation) +static inline Qt::ScreenOrientations qtOrientationsFromNative(DisplayOrientations native) { - switch (orientation) { - default: - case DisplayOrientations_None: - return Qt::PrimaryOrientation; - case DisplayOrientations_Landscape: - return Qt::LandscapeOrientation; - case DisplayOrientations_LandscapeFlipped: - return Qt::InvertedLandscapeOrientation; - case DisplayOrientations_Portrait: - return Qt::PortraitOrientation; - case DisplayOrientations_PortraitFlipped: - return Qt::InvertedPortraitOrientation; - } + Qt::ScreenOrientations orientations = Qt::PrimaryOrientation; + if (native & DisplayOrientations_Portrait) + orientations |= Qt::PortraitOrientation; + if (native & DisplayOrientations_PortraitFlipped) + orientations |= Qt::InvertedPortraitOrientation; + if (native & DisplayOrientations_Landscape) + orientations |= Qt::LandscapeOrientation; + if (native & DisplayOrientations_LandscapeFlipped) + orientations |= Qt::InvertedLandscapeOrientation; + return orientations; +} + +static inline DisplayOrientations nativeOrientationsFromQt(Qt::ScreenOrientations orientation) +{ + DisplayOrientations native = DisplayOrientations_None; + if (orientation & Qt::PortraitOrientation) + native |= DisplayOrientations_Portrait; + if (orientation & Qt::InvertedPortraitOrientation) + native |= DisplayOrientations_PortraitFlipped; + if (orientation & Qt::LandscapeOrientation) + native |= DisplayOrientations_Landscape; + if (orientation & Qt::InvertedLandscapeOrientation) + native |= DisplayOrientations_LandscapeFlipped; + return native; } static inline Qt::KeyboardModifiers qKeyModifiers(ICoreWindow *window) @@ -533,7 +544,7 @@ QWinRTScreen::QWinRTScreen(ICoreWindow *window) // Set native orientation DisplayOrientations displayOrientation; m_displayProperties->get_NativeOrientation(&displayOrientation); - m_nativeOrientation = qOrientationFromNative(displayOrientation); + m_nativeOrientation = static_cast(static_cast(qtOrientationsFromNative(displayOrientation))); // Set initial orientation onOrientationChanged(0); @@ -588,6 +599,11 @@ Qt::ScreenOrientation QWinRTScreen::orientation() const return m_orientation; } +void QWinRTScreen::setOrientationUpdateMask(Qt::ScreenOrientations mask) +{ + m_displayProperties->put_AutoRotationPreferences(nativeOrientationsFromQt(mask)); +} + ICoreWindow *QWinRTScreen::coreWindow() const { return m_coreWindow; @@ -1004,7 +1020,7 @@ HRESULT QWinRTScreen::onOrientationChanged(IInspectable *) { DisplayOrientations displayOrientation; m_displayProperties->get_CurrentOrientation(&displayOrientation); - Qt::ScreenOrientation newOrientation = qOrientationFromNative(displayOrientation); + Qt::ScreenOrientation newOrientation = static_cast(static_cast(qtOrientationsFromNative(displayOrientation))); if (m_orientation != newOrientation) { m_orientation = newOrientation; QWindowSystemInterface::handleScreenOrientationChange(screen(), m_orientation); diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h index d0ac53d56d..83f359ce6d 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.h +++ b/src/plugins/platforms/winrt/qwinrtscreen.h @@ -105,6 +105,7 @@ public: Qt::ScreenOrientation nativeOrientation() const; Qt::ScreenOrientation orientation() const; + void setOrientationUpdateMask(Qt::ScreenOrientations mask); QWindow *topWindow() const; void addWindow(QWindow *window); From da35793ee5cf73c45e3d1d9a994abf8be61fff14 Mon Sep 17 00:00:00 2001 From: Keith Gardner Date: Sat, 12 Oct 2013 12:13:36 -0500 Subject: [PATCH 036/684] Added the preprocessor macro Q_DECL_DEPRECATED_X Added a macro to provide deprecation warnings with a custom text. If the compiler does not support the feature, it falls back to Q_DECL_DEPRECATED instead. Currently supports msvc, gcc, and clang. The armcc documentation didn't show that the feature was available. Change-Id: Iebdb00738a135c756e032eb76152c405a8c29a45 Reviewed-by: Thiago Macieira --- src/corelib/global/qcompilerdetection.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index a388bdb96f..1d2d3247a5 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -98,6 +98,7 @@ # define Q_UNREACHABLE_IMPL() __assume(0) # define Q_NORETURN __declspec(noreturn) # define Q_DECL_DEPRECATED __declspec(deprecated) +# define Q_DECL_DEPRECATED_X(text) __declspec(deprecated(text)) # define Q_DECL_EXPORT __declspec(dllexport) # define Q_DECL_IMPORT __declspec(dllimport) /* Intel C++ disguising as Visual C++: the `using' keyword avoids warnings */ @@ -182,6 +183,7 @@ # define Q_ALIGNOF(type) __alignof__(type) # define Q_TYPEOF(expr) __typeof__(expr) # define Q_DECL_DEPRECATED __attribute__ ((__deprecated__)) +# define Q_DECL_DEPRECATED_X(text) __attribute__ ((__deprecated__(text))) # define Q_DECL_ALIGN(n) __attribute__((__aligned__(n))) # define Q_DECL_UNUSED __attribute__((__unused__)) # define Q_LIKELY(expr) __builtin_expect(!!(expr), true) @@ -838,6 +840,9 @@ #ifndef Q_DECL_VARIABLE_DEPRECATED # define Q_DECL_VARIABLE_DEPRECATED Q_DECL_DEPRECATED #endif +#ifndef Q_DECL_DEPRECATED_X +# define Q_DECL_DEPRECATED_X(text) Q_DECL_DEPRECATED +#endif #ifndef Q_DECL_EXPORT # define Q_DECL_EXPORT #endif From 0232fa3979e0e5d8485de94950f514bfd861d22b Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 10 Oct 2013 14:40:14 +0200 Subject: [PATCH 037/684] Add platform plugin arguments to QLibraryInfo/qt.conf. Make it possible to specify arguments to the platform plugins in a section of the qt.conf file: [Platforms] WindowsArguments=fontengine=freetype Change-Id: Ia05d0fa004471dcb74c78a88eec3b220ec3c6ad8 Reviewed-by: Oswald Buddenhagen Reviewed-by: David Faure Reviewed-by: Paul Olav Tvete --- src/corelib/global/qlibraryinfo.cpp | 33 ++++++++++++++++++++++++++++- src/corelib/global/qlibraryinfo.h | 4 ++++ src/gui/kernel/qguiapplication.cpp | 4 ++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 8d681f0c4c..9bc7506e39 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qdir.h" +#include "qstringlist.h" #include "qfile.h" #include "qsettings.h" #include "qlibraryinfo.h" @@ -113,6 +114,8 @@ public: } }; +static const char platformsSection[] = "Platforms"; + QLibrarySettings::QLibrarySettings() : settings(QLibraryInfoPrivate::findConfiguration()) { @@ -132,7 +135,8 @@ QLibrarySettings::QLibrarySettings() haveEffectivePaths = children.contains(QLatin1String("EffectivePaths")); #endif // Backwards compat: an existing but empty file is claimed to contain the Paths section. - havePaths = !haveEffectivePaths || children.contains(QLatin1String("Paths")); + havePaths = (!haveEffectivePaths && !children.contains(QLatin1String(platformsSection))) + || children.contains(QLatin1String("Paths")); #ifndef QT_BOOTSTRAPPED if (!havePaths) settings.reset(0); @@ -461,6 +465,33 @@ QLibraryInfo::rawLocation(LibraryLocation loc, PathGroup group) return ret; } +/*! + Returns additional arguments to the platform plugin matching + \a platformName which can be specified as a string list using + the key \c Arguments in a group called \c Platforms of the + \c qt.conf file. + + sa {Using qt.conf} + + \internal + + \since 5.3 +*/ + +QStringList QLibraryInfo::platformPluginArguments(const QString &platformName) +{ +#ifndef QT_BOOTSTRAPPED + if (const QSettings *settings = QLibraryInfoPrivate::findConfiguration()) { + QString key = QLatin1String(platformsSection); + key += QLatin1Char('/'); + key += platformName; + key += QLatin1String("Arguments"); + return settings->value(key).toStringList(); + } +#endif // !QT_BOOTSTRAPPED + return QStringList(); +} + /*! \enum QLibraryInfo::LibraryLocation diff --git a/src/corelib/global/qlibraryinfo.h b/src/corelib/global/qlibraryinfo.h index 17864b555b..54ef794d3e 100644 --- a/src/corelib/global/qlibraryinfo.h +++ b/src/corelib/global/qlibraryinfo.h @@ -47,6 +47,8 @@ QT_BEGIN_NAMESPACE +class QStringList; + class Q_CORE_EXPORT QLibraryInfo { public: @@ -96,6 +98,8 @@ public: static QString rawLocation(LibraryLocation, PathGroup); #endif + static QStringList platformPluginArguments(const QString &platformName); + private: QLibraryInfo(); }; diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index f555894b6d..591e83c0bd 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -59,6 +59,7 @@ #include #include #include +#include #include #ifndef QT_NO_ACCESSIBILITY #include "qaccessible.h" @@ -892,6 +893,9 @@ static void init_platform(const QString &pluginArgument, const QString &platform // Split into platform name and arguments QStringList arguments = pluginArgument.split(QLatin1Char(':')); const QString name = arguments.takeFirst().toLower(); + QString argumentsKey = name; + argumentsKey[0] = argumentsKey.at(0).toUpper(); + arguments.append(QLibraryInfo::platformPluginArguments(argumentsKey)); // Create the platform integration. QGuiApplicationPrivate::platform_integration = QPlatformIntegrationFactory::create(name, arguments, argc, argv, platformPluginPath); From af4284401d2ee5675fe6d06211a0686a5732af23 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Sat, 12 Oct 2013 02:07:39 +0300 Subject: [PATCH 038/684] WinRT QPA: Improve key handling Simplify key handling by providing a cleaner tracking of physical key presses and associated character events. Change-Id: I5aa8990e0b24e101b348c04d1ada2cbcd1b0b6be Reviewed-by: Maurice Kalinowski Reviewed-by: Oliver Wolff --- .../platforms/winrt/qwinrtintegration.cpp | 5 + .../platforms/winrt/qwinrtintegration.h | 1 + src/plugins/platforms/winrt/qwinrtscreen.cpp | 413 ++++++++---------- src/plugins/platforms/winrt/qwinrtscreen.h | 8 +- 4 files changed, 190 insertions(+), 237 deletions(-) diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp index 4cc7eb31f1..22c50e67f3 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.cpp +++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp @@ -186,4 +186,9 @@ QPlatformServices *QWinRTIntegration::services() const return m_services; } +Qt::KeyboardModifiers QWinRTIntegration::queryKeyboardModifiers() const +{ + return m_screen->keyboardModifiers(); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtintegration.h b/src/plugins/platforms/winrt/qwinrtintegration.h index 6cf2c3e5f2..d9438bcb3a 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.h +++ b/src/plugins/platforms/winrt/qwinrtintegration.h @@ -72,6 +72,7 @@ public: QPlatformFontDatabase *fontDatabase() const; QPlatformInputContext *inputContext() const; QPlatformServices *services() const; + Qt::KeyboardModifiers queryKeyboardModifiers() const; private: bool m_success; diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 8bc778ef11..911d3619fe 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -112,38 +112,37 @@ static inline DisplayOrientations nativeOrientationsFromQt(Qt::ScreenOrientation return native; } -static inline Qt::KeyboardModifiers qKeyModifiers(ICoreWindow *window) +static inline bool qIsNonPrintable(quint32 keyCode) { - Qt::KeyboardModifiers mods; - CoreVirtualKeyStates mod; - window->GetAsyncKeyState(VirtualKey_Shift, &mod); - if (mod == CoreVirtualKeyStates_Down) - mods |= Qt::ShiftModifier; - window->GetAsyncKeyState(VirtualKey_Menu, &mod); - if (mod == CoreVirtualKeyStates_Down) - mods |= Qt::AltModifier; - window->GetAsyncKeyState(VirtualKey_Control, &mod); - if (mod == CoreVirtualKeyStates_Down) - mods |= Qt::ControlModifier; - window->GetAsyncKeyState(VirtualKey_LeftWindows, &mod); - if (mod == CoreVirtualKeyStates_Down) { - mods |= Qt::MetaModifier; - } else { - window->GetAsyncKeyState(VirtualKey_RightWindows, &mod); - if (mod == CoreVirtualKeyStates_Down) - mods |= Qt::MetaModifier; + switch (keyCode) { + case '\b': + case '\n': + case '\t': + case '\r': + case '\v': + case '\f': + return true; + default: + return false; } - return mods; } -// Return Qt meta key from VirtualKey (discard character keys) -static inline Qt::Key qMetaKeyFromVirtual(VirtualKey key) +// Return Qt meta key from VirtualKey +static inline Qt::Key qKeyFromVirtual(VirtualKey key) { switch (key) { default: return Qt::Key_unknown; + // Non-printable characters + case VirtualKey_Enter: + return Qt::Key_Enter; + case VirtualKey_Tab: + return Qt::Key_Tab; + case VirtualKey_Back: + return Qt::Key_Backspace; + // Modifiers case VirtualKey_Shift: case VirtualKey_LeftShift: @@ -188,8 +187,6 @@ static inline Qt::Key qMetaKeyFromVirtual(VirtualKey key) // Misc. keys case VirtualKey_Cancel: return Qt::Key_Cancel; - case VirtualKey_Back: - return Qt::Key_Back; case VirtualKey_Clear: return Qt::Key_Clear; case VirtualKey_Application: @@ -198,8 +195,6 @@ static inline Qt::Key qMetaKeyFromVirtual(VirtualKey key) return Qt::Key_Sleep; case VirtualKey_Pause: return Qt::Key_Pause; - case VirtualKey_Space: - return Qt::Key_Space; case VirtualKey_PageUp: return Qt::Key_PageUp; case VirtualKey_PageDown: @@ -283,63 +278,103 @@ static inline Qt::Key qMetaKeyFromVirtual(VirtualKey key) case VirtualKey_F24: return Qt::Key_F24; - /* Character keys - pass through. - case VirtualKey_Enter: - case VirtualKey_Tab: + // Character keys + case VirtualKey_Space: + return Qt::Key_Space; case VirtualKey_Number0: - case VirtualKey_Number1: - case VirtualKey_Number2: - case VirtualKey_Number3: - case VirtualKey_Number4: - case VirtualKey_Number5: - case VirtualKey_Number6: - case VirtualKey_Number7: - case VirtualKey_Number8: - case VirtualKey_Number9: - case VirtualKey_A: - case VirtualKey_B: - case VirtualKey_C: - case VirtualKey_D: - case VirtualKey_E: - case VirtualKey_F: - case VirtualKey_G: - case VirtualKey_H: - case VirtualKey_I: - case VirtualKey_J: - case VirtualKey_K: - case VirtualKey_L: - case VirtualKey_M: - case VirtualKey_N: - case VirtualKey_O: - case VirtualKey_P: - case VirtualKey_Q: - case VirtualKey_R: - case VirtualKey_S: - case VirtualKey_T: - case VirtualKey_U: - case VirtualKey_V: - case VirtualKey_W: - case VirtualKey_X: - case VirtualKey_Y: - case VirtualKey_Z: - case VirtualKey_Multiply: - case VirtualKey_Add: - case VirtualKey_Separator: - case VirtualKey_Subtract: - case VirtualKey_Decimal: - case VirtualKey_Divide:*/ - - /* NumberPad keys. No special Alt handling is needed, as WinRT doesn't send events if Alt is pressed. case VirtualKey_NumberPad0: + return Qt::Key_0; + case VirtualKey_Number1: case VirtualKey_NumberPad1: + return Qt::Key_1; + case VirtualKey_Number2: case VirtualKey_NumberPad2: + return Qt::Key_2; + case VirtualKey_Number3: case VirtualKey_NumberPad3: + return Qt::Key_3; + case VirtualKey_Number4: case VirtualKey_NumberPad4: + return Qt::Key_4; + case VirtualKey_Number5: case VirtualKey_NumberPad5: + return Qt::Key_5; + case VirtualKey_Number6: case VirtualKey_NumberPad6: + return Qt::Key_6; + case VirtualKey_Number7: case VirtualKey_NumberPad7: + return Qt::Key_7; + case VirtualKey_Number8: case VirtualKey_NumberPad8: - case VirtualKey_NumberPad9:*/ + return Qt::Key_8; + case VirtualKey_Number9: + case VirtualKey_NumberPad9: + return Qt::Key_9; + case VirtualKey_A: + return Qt::Key_A; + case VirtualKey_B: + return Qt::Key_B; + case VirtualKey_C: + return Qt::Key_C; + case VirtualKey_D: + return Qt::Key_D; + case VirtualKey_E: + return Qt::Key_E; + case VirtualKey_F: + return Qt::Key_F; + case VirtualKey_G: + return Qt::Key_G; + case VirtualKey_H: + return Qt::Key_H; + case VirtualKey_I: + return Qt::Key_I; + case VirtualKey_J: + return Qt::Key_J; + case VirtualKey_K: + return Qt::Key_K; + case VirtualKey_L: + return Qt::Key_L; + case VirtualKey_M: + return Qt::Key_M; + case VirtualKey_N: + return Qt::Key_N; + case VirtualKey_O: + return Qt::Key_O; + case VirtualKey_P: + return Qt::Key_P; + case VirtualKey_Q: + return Qt::Key_Q; + case VirtualKey_R: + return Qt::Key_R; + case VirtualKey_S: + return Qt::Key_S; + case VirtualKey_T: + return Qt::Key_T; + case VirtualKey_U: + return Qt::Key_U; + case VirtualKey_V: + return Qt::Key_V; + case VirtualKey_W: + return Qt::Key_W; + case VirtualKey_X: + return Qt::Key_X; + case VirtualKey_Y: + return Qt::Key_Y; + case VirtualKey_Z: + return Qt::Key_Z; + case VirtualKey_Multiply: + return Qt::Key_9; + case VirtualKey_Add: + return Qt::Key_9; + case VirtualKey_Separator: + return Qt::Key_9; + case VirtualKey_Subtract: + return Qt::Key_9; + case VirtualKey_Decimal: + return Qt::Key_9; + case VirtualKey_Divide: + return Qt::Key_9; /* Keys with no matching Qt enum (?) case VirtualKey_None: @@ -353,122 +388,15 @@ static inline Qt::Key qMetaKeyFromVirtual(VirtualKey key) } } -// Map Qt keys from char -static inline Qt::Key qKeyFromChar(quint32 code, Qt::KeyboardModifiers mods = Qt::NoModifier) +static inline Qt::Key qKeyFromCode(quint32 code, int mods) { - switch (code) { - case 0x1: - case 'a': - case 'A': - return Qt::Key_A; - case 0x2: - case 'b': - case 'B': - return Qt::Key_B; - case 0x3: - case 'c': - case 'C': - return Qt::Key_C; - case 0x4: - case 'd': - case 'D': - return Qt::Key_D; - case 0x5: - case 'e': - case 'E': - return Qt::Key_E; - case 0x6: - case 'f': - case 'F': - return Qt::Key_F; - case 0x7: - case 'g': - case 'G': - return Qt::Key_G; - case 0x8: - //case '\b': - return mods & Qt::ControlModifier ? Qt::Key_H : Qt::Key_Backspace; - case 'h': - case 'H': - return Qt::Key_H; - case 0x9: - //case '\t': - return mods & Qt::ControlModifier ? Qt::Key_I : Qt::Key_Tab; - case 'i': - case 'I': - return Qt::Key_I; - case 0xa: - //case '\n': - return mods & Qt::ControlModifier ? Qt::Key_J : Qt::Key_Enter; - case 'j': - case 'J': - return Qt::Key_J; - case 0xb: - case 'k': - case 'K': - return Qt::Key_K; - case 0xc: - case 'l': - case 'L': - return Qt::Key_L; - case 0xd: - case 'm': - case 'M': - return Qt::Key_M; - case 0xe: - case 'n': - case 'N': - return Qt::Key_N; - case 0xf: - case 'o': - case 'O': - return Qt::Key_O; - case 0x10: - case 'p': - case 'P': - return Qt::Key_P; - case 0x11: - case 'q': - case 'Q': - return Qt::Key_Q; - case 0x12: - case 'r': - case 'R': - return Qt::Key_R; - case 0x13: - case 's': - case 'S': - return Qt::Key_S; - case 0x14: - case 't': - case 'T': - return Qt::Key_T; - case 0x15: - case 'u': - case 'U': - return Qt::Key_U; - case 0x16: - case 'v': - case 'V': - return Qt::Key_V; - case 0x17: - case 'w': - case 'W': - return Qt::Key_W; - case 0x18: - case 'x': - case 'X': - return Qt::Key_X; - case 0x19: - case 'y': - case 'Y': - return Qt::Key_Y; - case 0x1A: - case 'z': - case 'Z': - return Qt::Key_Z; + if (code >= 'a' && code <= 'z') + code = toupper(code); + if ((mods & Qt::ControlModifier) != 0) { + if (code >= 0 && code <= 31) // Ctrl+@..Ctrl+A..CTRL+Z..Ctrl+_ + code += '@'; // to @..A..Z.._ } - return Qt::Key_unknown; + return static_cast(code & 0xff); } QWinRTScreen::QWinRTScreen(ICoreWindow *window) @@ -521,8 +449,8 @@ QWinRTScreen::QWinRTScreen(ICoreWindow *window) qFatal("Could not create EGL surface, error 0x%X", eglGetError()); // Event handlers mapped to QEvents - m_coreWindow->add_KeyDown(Callback(this, &QWinRTScreen::onKey).Get(), &m_tokens[QEvent::KeyPress]); - m_coreWindow->add_KeyUp(Callback(this, &QWinRTScreen::onKey).Get(), &m_tokens[QEvent::KeyRelease]); + m_coreWindow->add_KeyDown(Callback(this, &QWinRTScreen::onKeyDown).Get(), &m_tokens[QEvent::KeyPress]); + m_coreWindow->add_KeyUp(Callback(this, &QWinRTScreen::onKeyUp).Get(), &m_tokens[QEvent::KeyRelease]); m_coreWindow->add_CharacterReceived(Callback(this, &QWinRTScreen::onCharacterReceived).Get(), &m_tokens[QEvent::User]); m_coreWindow->add_PointerEntered(Callback(this, &QWinRTScreen::onPointerEntered).Get(), &m_tokens[QEvent::Enter]); m_coreWindow->add_PointerExited(Callback(this, &QWinRTScreen::onPointerExited).Get(), &m_tokens[QEvent::Leave]); @@ -589,6 +517,30 @@ QPlatformCursor *QWinRTScreen::cursor() const return m_cursor; } +Qt::KeyboardModifiers QWinRTScreen::keyboardModifiers() const +{ + Qt::KeyboardModifiers mods; + CoreVirtualKeyStates mod; + m_coreWindow->GetAsyncKeyState(VirtualKey_Shift, &mod); + if (mod == CoreVirtualKeyStates_Down) + mods |= Qt::ShiftModifier; + m_coreWindow->GetAsyncKeyState(VirtualKey_Menu, &mod); + if (mod == CoreVirtualKeyStates_Down) + mods |= Qt::AltModifier; + m_coreWindow->GetAsyncKeyState(VirtualKey_Control, &mod); + if (mod == CoreVirtualKeyStates_Down) + mods |= Qt::ControlModifier; + m_coreWindow->GetAsyncKeyState(VirtualKey_LeftWindows, &mod); + if (mod == CoreVirtualKeyStates_Down) { + mods |= Qt::MetaModifier; + } else { + m_coreWindow->GetAsyncKeyState(VirtualKey_RightWindows, &mod); + if (mod == CoreVirtualKeyStates_Down) + mods |= Qt::MetaModifier; + } + return mods; +} + Qt::ScreenOrientation QWinRTScreen::nativeOrientation() const { return m_nativeOrientation; @@ -672,42 +624,36 @@ void QWinRTScreen::handleExpose() QWindowSystemInterface::flushWindowSystemEvents(); } -HRESULT QWinRTScreen::onKey(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IKeyEventArgs *args) +HRESULT QWinRTScreen::onKeyDown(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IKeyEventArgs *args) { Q_UNUSED(window); - - // Windows Phone documentation claims this will throw, but doesn't seem to - CorePhysicalKeyStatus keyStatus; - args->get_KeyStatus(&keyStatus); - VirtualKey virtualKey; args->get_VirtualKey(&virtualKey); + Qt::Key key = qKeyFromVirtual(virtualKey); + // Defer character key presses to onCharacterReceived + if (key == Qt::Key_unknown || (key >= Qt::Key_Space && key <= Qt::Key_ydiaeresis)) + return S_OK; + QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyPress, key, keyboardModifiers()); + return S_OK; +} - // Filter meta keys - Qt::Key key = qMetaKeyFromVirtual(virtualKey); - - // Get keyboard modifiers. This could alternatively be tracked by key presses, but - // WinRT doesn't send key events for Alt unless Ctrl is also pressed. - // If the key that caused this event is a modifier, it is not returned in the flags. - Qt::KeyboardModifiers mods = qKeyModifiers(m_coreWindow); - - if (m_activeKeys.contains(keyStatus.ScanCode)) { // Handle tracked keys (release/repeat) - QString text = keyStatus.IsKeyReleased ? m_activeKeys.take(keyStatus.ScanCode) : m_activeKeys.value(keyStatus.ScanCode); - QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease, key, mods, text); - - if (!keyStatus.IsKeyReleased) // Repeating key - QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyPress, key, mods, text); - - } else if (keyStatus.IsKeyReleased) { // Unlikely, but possible if key is held before application is focused - QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease, key, mods); - - } else { // Handle key presses - if (key != Qt::Key_unknown) // Handle non-character key presses here, others in onCharacterReceived - QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyPress, key, mods); - - m_activeKeys.insert(keyStatus.ScanCode, QString()); +HRESULT QWinRTScreen::onKeyUp(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IKeyEventArgs *args) +{ + Q_UNUSED(window); + Qt::KeyboardModifiers mods = keyboardModifiers(); +#ifndef Q_OS_WINPHONE + CorePhysicalKeyStatus status; // Look for a pressed character key + if (SUCCEEDED(args->get_KeyStatus(&status)) && m_activeKeys.contains(status.ScanCode)) { + QPair keyStatus = m_activeKeys.take(status.ScanCode); + QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease, + keyStatus.first, mods, keyStatus.second); + return S_OK; } - +#endif // !Q_OS_WINPHONE + VirtualKey virtualKey; + args->get_VirtualKey(&virtualKey); + QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease, + qKeyFromVirtual(virtualKey), mods); return S_OK; } @@ -717,25 +663,22 @@ HRESULT QWinRTScreen::onCharacterReceived(ICoreWindow *window, ICharacterReceive quint32 keyCode; args->get_KeyCode(&keyCode); + // Don't generate character events for non-printables; the meta key stage is enough + if (qIsNonPrintable(keyCode)) + return S_OK; - // Windows Phone documentation claims this will throw, but doesn't seem to - CorePhysicalKeyStatus keyStatus; - args->get_KeyStatus(&keyStatus); - + Qt::KeyboardModifiers mods = keyboardModifiers(); + Qt::Key key = qKeyFromCode(keyCode, mods); QString text = QChar(keyCode); - - Qt::KeyboardModifiers mods = qKeyModifiers(m_coreWindow); - Qt::Key key = qKeyFromChar(keyCode, mods); - QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyPress, key, mods, text); - - // Note that we can receive a character without corresponding press/release events, such as - // the case of an Alt-combo. In this case, we should send the release immediately. - if (m_activeKeys.contains(keyStatus.ScanCode)) - m_activeKeys.insert(keyStatus.ScanCode, text); - else - QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease, key, mods, text); - +#ifndef Q_OS_WINPHONE + CorePhysicalKeyStatus status; // Defer release to onKeyUp for physical keys + if (SUCCEEDED(args->get_KeyStatus(&status)) && !status.IsKeyReleased) { + m_activeKeys.insert(status.ScanCode, qMakePair(key, text)); + return S_OK; + } +#endif // !Q_OS_WINPHONE + QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease, key, mods, text); return S_OK; } diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h index 83f359ce6d..21e50fa10a 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.h +++ b/src/plugins/platforms/winrt/qwinrtscreen.h @@ -102,6 +102,7 @@ public: QSurfaceFormat surfaceFormat() const; QWinRTInputContext *inputContext() const; QPlatformCursor *cursor() const; + Qt::KeyboardModifiers keyboardModifiers() const; Qt::ScreenOrientation nativeOrientation() const; Qt::ScreenOrientation orientation() const; @@ -123,7 +124,8 @@ private: // Event handlers QHash m_tokens; - HRESULT onKey(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IKeyEventArgs *args); + HRESULT onKeyDown(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IKeyEventArgs *args); + HRESULT onKeyUp(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IKeyEventArgs *args); HRESULT onCharacterReceived(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::ICharacterReceivedEventArgs *args); HRESULT onPointerEntered(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IPointerEventArgs *args); HRESULT onPointerExited(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IPointerEventArgs *args); @@ -154,7 +156,9 @@ private: Qt::ScreenOrientation m_nativeOrientation; Qt::ScreenOrientation m_orientation; - QHash m_activeKeys; +#ifndef Q_OS_WINPHONE + QHash > m_activeKeys; +#endif QHash m_pointers; QHash m_touchPoints; }; From 345907344d228d95848d8c646aaeb051b9228d3b Mon Sep 17 00:00:00 2001 From: Keith Gardner Date: Thu, 17 Oct 2013 17:44:25 -0500 Subject: [PATCH 039/684] Fixed Q_DECL_DEPRECATED_X for Gcc 4.4 Apparently the __attribute__((__deprecated__(text))) feature for gcc was introduced in version 4.5. Since Qt's minimum supported version of gcc is 4.4, the declaration of the macro needed to check the compiler's version number. Since clang reports its __GNUC__ and __GNUC_MINOR__ as gcc 4.2, the check for the compiler support had to be added in with __has_feature(attribute_deprecated_with_message). For icc, a check was added to see if __INTEL_COMPILER >= 1300, __GNUC__ is defined and Q_DECL_DEPRECATED_X was not defined. If this is true, the gcc syntax is used in the define. Change-Id: I23980ac28b79264e8fd657cd3bfd2af7674779a1 Reviewed-by: Olivier Goffart --- src/corelib/global/qcompilerdetection.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 1d2d3247a5..ef425e8d85 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -153,6 +153,9 @@ # define Q_CC_INTEL # define Q_ASSUME_IMPL(expr) __assume(expr) # define Q_UNREACHABLE_IMPL() __builtin_unreachable() +# if __INTEL_COMPILER >= 1300 +# define Q_DECL_DEPRECATED_X(text) __attribute__ ((__deprecated__(text))) +# endif # elif defined(__clang__) /* Clang also masquerades as GCC */ # define Q_CC_CLANG @@ -167,6 +170,7 @@ # if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 # define Q_ASSUME_IMPL(expr) if (expr){} else __builtin_unreachable() # define Q_UNREACHABLE_IMPL() __builtin_unreachable() +# define Q_DECL_DEPRECATED_X(text) __attribute__ ((__deprecated__(text))) # endif # endif @@ -183,7 +187,6 @@ # define Q_ALIGNOF(type) __alignof__(type) # define Q_TYPEOF(expr) __typeof__(expr) # define Q_DECL_DEPRECATED __attribute__ ((__deprecated__)) -# define Q_DECL_DEPRECATED_X(text) __attribute__ ((__deprecated__(text))) # define Q_DECL_ALIGN(n) __attribute__((__aligned__(n))) # define Q_DECL_UNUSED __attribute__((__unused__)) # define Q_LIKELY(expr) __builtin_expect(!!(expr), true) @@ -521,6 +524,9 @@ # if !__has_feature(cxx_rtti) # define QT_NO_RTTI # endif +# if __has_feature(attribute_deprecated_with_message) +# define Q_DECL_DEPRECATED_X(text) __attribute__ ((__deprecated__(text))) +# endif /* C++11 features, see http://clang.llvm.org/cxx_status.html */ # if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) From b1093ef647b7b139a39a6ac66a8f228b84eb535d Mon Sep 17 00:00:00 2001 From: Keith Gardner Date: Wed, 16 Oct 2013 18:04:06 -0500 Subject: [PATCH 040/684] Added QT_DEPRECATED_X(text) Defined the Q_DEPRECATED_X to use the Q_DECL_DEPRECATED_X macro. Change-Id: I334328059c6a1e046f57470027b0d1086a35042c Reviewed-by: Olivier Goffart --- src/corelib/global/qglobal.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index fd5ab865f3..ed17709a4d 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -223,11 +223,14 @@ typedef double qreal; #if defined(QT_NO_DEPRECATED) # undef QT_DEPRECATED +# undef QT_DEPRECATED_X # undef QT_DEPRECATED_VARIABLE # undef QT_DEPRECATED_CONSTRUCTOR #elif defined(QT_DEPRECATED_WARNINGS) # undef QT_DEPRECATED # define QT_DEPRECATED Q_DECL_DEPRECATED +# undef QT_DEPRECATED_X +# define QT_DEPRECATED_X(text) Q_DECL_DEPRECATED_X(text) # undef QT_DEPRECATED_VARIABLE # define QT_DEPRECATED_VARIABLE Q_DECL_VARIABLE_DEPRECATED # undef QT_DEPRECATED_CONSTRUCTOR @@ -235,6 +238,8 @@ typedef double qreal; #else # undef QT_DEPRECATED # define QT_DEPRECATED +# undef QT_DEPRECATED_X +# define QT_DEPRECATED_X(text) # undef QT_DEPRECATED_VARIABLE # define QT_DEPRECATED_VARIABLE # undef QT_DEPRECATED_CONSTRUCTOR From 4dc6a891516146d28316d06e44743718cc9ed29b Mon Sep 17 00:00:00 2001 From: Keith Gardner Date: Wed, 16 Oct 2013 18:42:06 -0500 Subject: [PATCH 041/684] Used QT_DEPRECATED_X in QtAlgorithms Made all of the deprecated functions in QtAlgorithms now use QT_DEPRECATED_X with helpful deprecation messages. Change-Id: I3358e44b8c1f15eeb4689ab02b1802a07d04fc09 Reviewed-by: Olivier Goffart --- src/corelib/tools/qalgorithms.h | 86 ++++++++++++++++----------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h index c6eede05cb..f75f33f25c 100644 --- a/src/corelib/tools/qalgorithms.h +++ b/src/corelib/tools/qalgorithms.h @@ -55,28 +55,28 @@ namespace QAlgorithmsPrivate { #if QT_DEPRECATED_SINCE(5, 2) template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan); +QT_DEPRECATED_X("Use std::sort") Q_OUTOFLINE_TEMPLATE void qSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan); template -QT_DEPRECATED inline void qSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy); +QT_DEPRECATED_X("Use std::sort") inline void qSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy); template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qStableSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan); +QT_DEPRECATED_X("Use std::stable_sort") Q_OUTOFLINE_TEMPLATE void qStableSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan); template -QT_DEPRECATED inline void qStableSortHelper(RandomAccessIterator, RandomAccessIterator, const T &); +QT_DEPRECATED_X("Use std::stable_sort") inline void qStableSortHelper(RandomAccessIterator, RandomAccessIterator, const T &); template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan); +QT_DEPRECATED_X("Use std::lower_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan); template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan); +QT_DEPRECATED_X("Use std::upper_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan); template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFindHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan); +QT_DEPRECATED_X("Use std::binary_search") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFindHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan); #endif // QT_DEPRECATED_SINCE(5, 2) } #if QT_DEPRECATED_SINCE(5, 2) template -QT_DEPRECATED inline OutputIterator qCopy(InputIterator begin, InputIterator end, OutputIterator dest) +QT_DEPRECATED_X("Use std::copy") inline OutputIterator qCopy(InputIterator begin, InputIterator end, OutputIterator dest) { while (begin != end) *dest++ = *begin++; @@ -84,7 +84,7 @@ QT_DEPRECATED inline OutputIterator qCopy(InputIterator begin, InputIterator end } template -QT_DEPRECATED inline BiIterator2 qCopyBackward(BiIterator1 begin, BiIterator1 end, BiIterator2 dest) +QT_DEPRECATED_X("Use std::copy_backward") inline BiIterator2 qCopyBackward(BiIterator1 begin, BiIterator1 end, BiIterator2 dest) { while (begin != end) *--dest = *--end; @@ -92,7 +92,7 @@ QT_DEPRECATED inline BiIterator2 qCopyBackward(BiIterator1 begin, BiIterator1 en } template -QT_DEPRECATED inline bool qEqual(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2) +QT_DEPRECATED_X("Use std::equal") inline bool qEqual(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2) { for (; first1 != last1; ++first1, ++first2) if (!(*first1 == *first2)) @@ -101,20 +101,20 @@ QT_DEPRECATED inline bool qEqual(InputIterator1 first1, InputIterator1 last1, In } template -QT_DEPRECATED inline void qFill(ForwardIterator first, ForwardIterator last, const T &val) +QT_DEPRECATED_X("Use std::fill") inline void qFill(ForwardIterator first, ForwardIterator last, const T &val) { for (; first != last; ++first) *first = val; } template -QT_DEPRECATED inline void qFill(Container &container, const T &val) +QT_DEPRECATED_X("Use std::fill") inline void qFill(Container &container, const T &val) { qFill(container.begin(), container.end(), val); } template -QT_DEPRECATED inline InputIterator qFind(InputIterator first, InputIterator last, const T &val) +QT_DEPRECATED_X("Use std::find") inline InputIterator qFind(InputIterator first, InputIterator last, const T &val) { while (first != last && !(*first == val)) ++first; @@ -122,13 +122,13 @@ QT_DEPRECATED inline InputIterator qFind(InputIterator first, InputIterator last } template -QT_DEPRECATED inline typename Container::const_iterator qFind(const Container &container, const T &val) +QT_DEPRECATED_X("Use std::find") inline typename Container::const_iterator qFind(const Container &container, const T &val) { return qFind(container.constBegin(), container.constEnd(), val); } template -QT_DEPRECATED inline void qCount(InputIterator first, InputIterator last, const T &value, Size &n) +QT_DEPRECATED_X("Use std::count") inline void qCount(InputIterator first, InputIterator last, const T &value, Size &n) { for (; first != last; ++first) if (*first == value) @@ -136,7 +136,7 @@ QT_DEPRECATED inline void qCount(InputIterator first, InputIterator last, const } template -QT_DEPRECATED inline void qCount(const Container &container, const T &value, Size &n) +QT_DEPRECATED_X("Use std::count") inline void qCount(const Container &container, const T &value, Size &n) { qCount(container.constBegin(), container.constEnd(), value, n); } @@ -153,7 +153,7 @@ LessThan qGreater() } #else template -class QT_DEPRECATED qLess +class QT_DEPRECATED_X("Use std::less") qLess { public: inline bool operator()(const T &t1, const T &t2) const @@ -163,7 +163,7 @@ public: }; template -class QT_DEPRECATED qGreater +class QT_DEPRECATED_X("Use std::greater") qGreater { public: inline bool operator()(const T &t1, const T &t2) const @@ -174,21 +174,21 @@ public: #endif template -QT_DEPRECATED inline void qSort(RandomAccessIterator start, RandomAccessIterator end) +QT_DEPRECATED_X("Use std::sort") inline void qSort(RandomAccessIterator start, RandomAccessIterator end) { if (start != end) QAlgorithmsPrivate::qSortHelper(start, end, *start); } template -QT_DEPRECATED inline void qSort(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan) +QT_DEPRECATED_X("Use std::sort") inline void qSort(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan) { if (start != end) QAlgorithmsPrivate::qSortHelper(start, end, *start, lessThan); } template -QT_DEPRECATED inline void qSort(Container &c) +QT_DEPRECATED_X("Use std::sort") inline void qSort(Container &c) { #ifdef Q_CC_BOR // Work around Borland 5.5 optimizer bug @@ -199,21 +199,21 @@ QT_DEPRECATED inline void qSort(Container &c) } template -QT_DEPRECATED inline void qStableSort(RandomAccessIterator start, RandomAccessIterator end) +QT_DEPRECATED_X("Use std::stable_sort") inline void qStableSort(RandomAccessIterator start, RandomAccessIterator end) { if (start != end) QAlgorithmsPrivate::qStableSortHelper(start, end, *start); } template -QT_DEPRECATED inline void qStableSort(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan) +QT_DEPRECATED_X("Use std::stable_sort") inline void qStableSort(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan) { if (start != end) QAlgorithmsPrivate::qStableSortHelper(start, end, *start, lessThan); } template -QT_DEPRECATED inline void qStableSort(Container &c) +QT_DEPRECATED_X("Use std::stable_sort") inline void qStableSort(Container &c) { #ifdef Q_CC_BOR // Work around Borland 5.5 optimizer bug @@ -224,7 +224,7 @@ QT_DEPRECATED inline void qStableSort(Container &c) } template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value) +QT_DEPRECATED_X("Use std::lower_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value) { // Implementation is duplicated from QAlgorithmsPrivate to keep existing code // compiling. We have to allow using *begin and value with different types, @@ -247,19 +247,19 @@ QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBound(RandomAccess } template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) +QT_DEPRECATED_X("Use std::lower_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) { return QAlgorithmsPrivate::qLowerBoundHelper(begin, end, value, lessThan); } template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qLowerBound(const Container &container, const T &value) +QT_DEPRECATED_X("Use std::lower_bound") Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qLowerBound(const Container &container, const T &value) { return QAlgorithmsPrivate::qLowerBoundHelper(container.constBegin(), container.constEnd(), value, qLess()); } template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value) +QT_DEPRECATED_X("Use std::upper_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value) { // Implementation is duplicated from QAlgorithmsPrivate. RandomAccessIterator middle; @@ -280,19 +280,19 @@ QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBound(RandomAccess } template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) +QT_DEPRECATED_X("Use std::upper_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) { return QAlgorithmsPrivate::qUpperBoundHelper(begin, end, value, lessThan); } template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qUpperBound(const Container &container, const T &value) +QT_DEPRECATED_X("Use std::upper_bound") Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qUpperBound(const Container &container, const T &value) { return QAlgorithmsPrivate::qUpperBoundHelper(container.constBegin(), container.constEnd(), value, qLess()); } template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value) +QT_DEPRECATED_X("Use std::binary_search") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value) { // Implementation is duplicated from QAlgorithmsPrivate. RandomAccessIterator it = qLowerBound(begin, end, value); @@ -304,13 +304,13 @@ QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFind(RandomAccess } template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) +QT_DEPRECATED_X("Use std::binary_search") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) { return QAlgorithmsPrivate::qBinaryFindHelper(begin, end, value, lessThan); } template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qBinaryFind(const Container &container, const T &value) +QT_DEPRECATED_X("Use std::binary_search") Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qBinaryFind(const Container &container, const T &value) { return QAlgorithmsPrivate::qBinaryFindHelper(container.constBegin(), container.constEnd(), value, qLess()); } @@ -340,7 +340,7 @@ namespace QAlgorithmsPrivate { #if QT_DEPRECATED_SINCE(5, 2) template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan) +QT_DEPRECATED_X("Use std::sort") Q_OUTOFLINE_TEMPLATE void qSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan) { top: int span = int(end - start); @@ -393,13 +393,13 @@ top: } template -QT_DEPRECATED inline void qSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy) +QT_DEPRECATED_X("Use std::sort") inline void qSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy) { qSortHelper(begin, end, dummy, qLess()); } template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qReverse(RandomAccessIterator begin, RandomAccessIterator end) +QT_DEPRECATED_X("Use std::reverse") Q_OUTOFLINE_TEMPLATE void qReverse(RandomAccessIterator begin, RandomAccessIterator end) { --end; while (begin < end) @@ -407,7 +407,7 @@ QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qReverse(RandomAccessIterator begin, Ran } template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qRotate(RandomAccessIterator begin, RandomAccessIterator middle, RandomAccessIterator end) +QT_DEPRECATED_X("Use std::rotate") Q_OUTOFLINE_TEMPLATE void qRotate(RandomAccessIterator begin, RandomAccessIterator middle, RandomAccessIterator end) { qReverse(begin, middle); qReverse(middle, end); @@ -415,7 +415,7 @@ QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qRotate(RandomAccessIterator begin, Rand } template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qMerge(RandomAccessIterator begin, RandomAccessIterator pivot, RandomAccessIterator end, T &t, LessThan lessThan) +QT_DEPRECATED_X("Use std::merge") Q_OUTOFLINE_TEMPLATE void qMerge(RandomAccessIterator begin, RandomAccessIterator pivot, RandomAccessIterator end, T &t, LessThan lessThan) { const int len1 = pivot - begin; const int len2 = end - pivot; @@ -450,7 +450,7 @@ QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qMerge(RandomAccessIterator begin, Rando } template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qStableSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &t, LessThan lessThan) +QT_DEPRECATED_X("Use std::stable_sort") Q_OUTOFLINE_TEMPLATE void qStableSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &t, LessThan lessThan) { const int span = end - begin; if (span < 2) @@ -463,13 +463,13 @@ QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qStableSortHelper(RandomAccessIterator b } template -QT_DEPRECATED inline void qStableSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy) +QT_DEPRECATED_X("Use std::stable_sort") inline void qStableSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy) { qStableSortHelper(begin, end, dummy, qLess()); } template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) +QT_DEPRECATED_X("Use std::lower_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) { RandomAccessIterator middle; int n = int(end - begin); @@ -490,7 +490,7 @@ QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBoundHelper(Random template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) +QT_DEPRECATED_X("Use std::upper_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) { RandomAccessIterator middle; int n = end - begin; @@ -510,7 +510,7 @@ QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBoundHelper(Random } template -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFindHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) +QT_DEPRECATED_X("Use std::binary_search") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFindHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) { RandomAccessIterator it = qLowerBoundHelper(begin, end, value, lessThan); From c371680a86933a42964fcb36266806d5d69c6b86 Mon Sep 17 00:00:00 2001 From: Mandeep Sandhu Date: Tue, 24 Sep 2013 17:35:52 +0530 Subject: [PATCH 042/684] QDnsLookup: Support for custom DNS server This commit only adds a new QProperty, "nameserver", to QDnsLookup. This property currently does not do anything and is not used internally by QDnsLookup. The next commit will implement it's usage. Task-number: QTBUG-30166 Change-Id: I85b72bd6661603128cab4068c1b83883fb2bfd1a Reviewed-by: Thiago Macieira --- src/network/kernel/qdnslookup.cpp | 19 +++++++++++++++++++ src/network/kernel/qdnslookup.h | 6 ++++++ src/network/kernel/qdnslookup_p.h | 1 + 3 files changed, 26 insertions(+) diff --git a/src/network/kernel/qdnslookup.cpp b/src/network/kernel/qdnslookup.cpp index 53675d083b..e776a8eb76 100644 --- a/src/network/kernel/qdnslookup.cpp +++ b/src/network/kernel/qdnslookup.cpp @@ -362,6 +362,25 @@ void QDnsLookup::setType(Type type) } } +/*! + \property QDnsLookup::nameserver + \brief the nameserver to use for DNS lookup. +*/ + +QHostAddress QDnsLookup::nameserver() const +{ + return d_func()->nameserver; +} + +void QDnsLookup::setNameserver(const QHostAddress &nameserver) +{ + Q_D(QDnsLookup); + if (nameserver != d->nameserver) { + d->nameserver = nameserver; + emit nameserverChanged(nameserver); + } +} + /*! Returns the list of canonical name records associated with this lookup. */ diff --git a/src/network/kernel/qdnslookup.h b/src/network/kernel/qdnslookup.h index 1df21d866e..ffbef61f92 100644 --- a/src/network/kernel/qdnslookup.h +++ b/src/network/kernel/qdnslookup.h @@ -180,6 +180,7 @@ class Q_NETWORK_EXPORT QDnsLookup : public QObject Q_PROPERTY(QString errorString READ errorString NOTIFY finished) Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) Q_PROPERTY(Type type READ type WRITE setType NOTIFY typeChanged) + Q_PROPERTY(QHostAddress nameserver READ nameserver WRITE setNameserver NOTIFY nameserverChanged) public: enum Error @@ -209,6 +210,7 @@ public: explicit QDnsLookup(QObject *parent = 0); QDnsLookup(Type type, const QString &name, QObject *parent = 0); + QDnsLookup(Type type, const QString &name, const QHostAddress &nameserver, QObject *parent = 0); ~QDnsLookup(); Error error() const; @@ -221,6 +223,9 @@ public: Type type() const; void setType(QDnsLookup::Type); + QHostAddress nameserver() const; + void setNameserver(const QHostAddress &nameserver); + QList canonicalNameRecords() const; QList hostAddressRecords() const; QList mailExchangeRecords() const; @@ -238,6 +243,7 @@ Q_SIGNALS: void finished(); void nameChanged(const QString &name); void typeChanged(Type type); + void nameserverChanged(const QHostAddress &nameserver); private: Q_DECLARE_PRIVATE(QDnsLookup) diff --git a/src/network/kernel/qdnslookup_p.h b/src/network/kernel/qdnslookup_p.h index 692b9088fe..4bd3bd7603 100644 --- a/src/network/kernel/qdnslookup_p.h +++ b/src/network/kernel/qdnslookup_p.h @@ -100,6 +100,7 @@ public: bool isFinished; QString name; QDnsLookup::Type type; + QHostAddress nameserver; QDnsLookupReply reply; QDnsLookupRunnable *runnable; From 93cd08bfcc3b5b83196b6dabf859d5301cc90c98 Mon Sep 17 00:00:00 2001 From: Roger Maclean Date: Mon, 21 Oct 2013 14:18:59 -0400 Subject: [PATCH 043/684] Correct handling of font weights bolder than bold. A couple of places were checking for a font weight equal to QFont::Bold rather than a weight that is greater or equal to this. This sometimes results in QFont::Black being rendered with a lighter weight than QFont::Bold even though it should if anything be heavier. Change-Id: I5aa73a84ea2718783bbac93a031d87b2ad90012c Reviewed-by: Rafael Roquetto Reviewed-by: Konstantin Ritt --- src/gui/text/qfontengine_ft.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 328931e1eb..6e14fc23c6 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -693,7 +693,7 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format, FT_Set_Transform(face, &matrix, 0); freetype->matrix = matrix; // fake bold - if ((fontDef.weight == QFont::Bold) && !(face->style_flags & FT_STYLE_FLAG_BOLD) && !FT_IS_FIXED_WIDTH(face)) + if ((fontDef.weight >= QFont::Bold) && !(face->style_flags & FT_STYLE_FLAG_BOLD) && !FT_IS_FIXED_WIDTH(face)) embolden = true; // underline metrics line_thickness = QFixed::fromFixed(FT_MulFix(face->underline_thickness, face->size->metrics.y_scale)); @@ -1165,7 +1165,7 @@ int QFontEngineFT::synthesized() const int s = 0; if ((fontDef.style != QFont::StyleNormal) && !(freetype->face->style_flags & FT_STYLE_FLAG_ITALIC)) s = SynthesizedItalic; - if ((fontDef.weight == QFont::Bold) && !(freetype->face->style_flags & FT_STYLE_FLAG_BOLD)) + if ((fontDef.weight >= QFont::Bold) && !(freetype->face->style_flags & FT_STYLE_FLAG_BOLD)) s |= SynthesizedBold; if (fontDef.stretch != 100 && FT_IS_SCALABLE(freetype->face)) s |= SynthesizedStretch; From 2d107c20b9670976e0d4a22edc6c3b235e225fa4 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 15 Oct 2013 14:12:34 +0200 Subject: [PATCH 044/684] Fix settable style hints. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce QStyleHintsPrivate and introduce internal setters called by QApplication. Task-number: QTBUG-33991 Change-Id: Id61f8b1e2b5c9cfd7b4713aaded66e93e6f63719 Reviewed-by: Jan Arve Sæther Reviewed-by: Andy Shaw --- src/gui/kernel/qstylehints.cpp | 106 +++++++++++++++++- src/gui/kernel/qstylehints.h | 7 ++ src/widgets/kernel/qapplication.cpp | 12 +- .../kernel/qapplication/tst_qapplication.cpp | 18 +++ 4 files changed, 130 insertions(+), 13 deletions(-) diff --git a/src/gui/kernel/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp index 04ea9c27d5..7899e2540b 100644 --- a/src/gui/kernel/qstylehints.cpp +++ b/src/gui/kernel/qstylehints.cpp @@ -62,6 +62,25 @@ static inline QVariant themeableHint(QPlatformTheme::ThemeHint th, return QGuiApplicationPrivate::platformIntegration()->styleHint(ih); } +class QStyleHintsPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QStyleHints) +public: + inline QStyleHintsPrivate() + : m_mouseDoubleClickInterval(-1) + , m_startDragDistance(-1) + , m_startDragTime(-1) + , m_keyboardInputInterval(-1) + , m_cursorFlashTime(-1) + {} + + int m_mouseDoubleClickInterval; + int m_startDragDistance; + int m_startDragTime; + int m_keyboardInputInterval; + int m_cursorFlashTime; +}; + /*! \class QStyleHints \since 5.0 @@ -80,17 +99,44 @@ static inline QVariant themeableHint(QPlatformTheme::ThemeHint th, \sa QGuiApplication::styleHints(), QPlatformTheme */ QStyleHints::QStyleHints() - : QObject() + : QObject(*new QStyleHintsPrivate(), 0) { } +/*! + Sets the \a mouseDoubleClickInterval. + \internal + \sa mouseDoubleClickInterval() + \since 5.3 +*/ +void QStyleHints::setMouseDoubleClickInterval(int mouseDoubleClickInterval) +{ + Q_D(QStyleHints); + d->m_mouseDoubleClickInterval = mouseDoubleClickInterval; +} + /*! Returns the time limit in milliseconds that distinguishes a double click from two consecutive mouse clicks. */ int QStyleHints::mouseDoubleClickInterval() const { - return themeableHint(QPlatformTheme::MouseDoubleClickInterval, QPlatformIntegration::MouseDoubleClickInterval).toInt(); + Q_D(const QStyleHints); + return d->m_mouseDoubleClickInterval >= 0 ? + d->m_mouseDoubleClickInterval : + themeableHint(QPlatformTheme::MouseDoubleClickInterval, QPlatformIntegration::MouseDoubleClickInterval).toInt(); +} + +/*! + Sets the \a startDragDistance. + \internal + \sa startDragDistance() + \since 5.3 +*/ +void QStyleHints::setStartDragDistance(int startDragDistance) +{ + Q_D(QStyleHints); + d->m_startDragDistance = startDragDistance; } /*! @@ -112,7 +158,22 @@ int QStyleHints::mouseDoubleClickInterval() const */ int QStyleHints::startDragDistance() const { - return themeableHint(QPlatformTheme::StartDragDistance, QPlatformIntegration::StartDragDistance).toInt(); + Q_D(const QStyleHints); + return d->m_startDragDistance >= 0 ? + d->m_startDragDistance : + themeableHint(QPlatformTheme::StartDragDistance, QPlatformIntegration::StartDragDistance).toInt(); +} + +/*! + Sets the \a startDragDragTime. + \internal + \sa startDragTime() + \since 5.3 +*/ +void QStyleHints::setStartDragTime(int startDragTime) +{ + Q_D(QStyleHints); + d->m_startDragTime = startDragTime; } /*! @@ -127,7 +188,10 @@ int QStyleHints::startDragDistance() const */ int QStyleHints::startDragTime() const { - return themeableHint(QPlatformTheme::StartDragTime, QPlatformIntegration::StartDragTime).toInt(); + Q_D(const QStyleHints); + return d->m_startDragTime >= 0 ? + d->m_startDragTime : + themeableHint(QPlatformTheme::StartDragTime, QPlatformIntegration::StartDragTime).toInt(); } /*! @@ -142,13 +206,28 @@ int QStyleHints::startDragVelocity() const return themeableHint(QPlatformTheme::StartDragVelocity, QPlatformIntegration::StartDragVelocity).toInt(); } +/*! + Sets the \a keyboardInputInterval. + \internal + \sa keyboardInputInterval() + \since 5.3 +*/ +void QStyleHints::setKeyboardInputInterval(int keyboardInputInterval) +{ + Q_D(QStyleHints); + d->m_keyboardInputInterval = keyboardInputInterval; +} + /*! Returns the time limit, in milliseconds, that distinguishes a key press from two consecutive key presses. */ int QStyleHints::keyboardInputInterval() const { - return themeableHint(QPlatformTheme::KeyboardInputInterval, QPlatformIntegration::KeyboardInputInterval).toInt(); + Q_D(const QStyleHints); + return d->m_keyboardInputInterval >= 0 ? + d->m_keyboardInputInterval : + themeableHint(QPlatformTheme::KeyboardInputInterval, QPlatformIntegration::KeyboardInputInterval).toInt(); } /*! @@ -160,6 +239,18 @@ int QStyleHints::keyboardAutoRepeatRate() const return themeableHint(QPlatformTheme::KeyboardAutoRepeatRate, QPlatformIntegration::KeyboardAutoRepeatRate).toInt(); } +/*! + Sets the \a cursorFlashTime. + \internal + \sa cursorFlashTime() + \since 5.3 +*/ +void QStyleHints::setCursorFlashTime(int cursorFlashTime) +{ + Q_D(QStyleHints); + d->m_cursorFlashTime = cursorFlashTime; +} + /*! Returns the text cursor's flash (blink) time in milliseconds. @@ -169,7 +260,10 @@ int QStyleHints::keyboardAutoRepeatRate() const */ int QStyleHints::cursorFlashTime() const { - return themeableHint(QPlatformTheme::CursorFlashTime, QPlatformIntegration::CursorFlashTime).toInt(); + Q_D(const QStyleHints); + return d->m_cursorFlashTime >= 0 ? + d->m_cursorFlashTime : + themeableHint(QPlatformTheme::CursorFlashTime, QPlatformIntegration::CursorFlashTime).toInt(); } /*! diff --git a/src/gui/kernel/qstylehints.h b/src/gui/kernel/qstylehints.h index a0facd5f94..cc8d71108a 100644 --- a/src/gui/kernel/qstylehints.h +++ b/src/gui/kernel/qstylehints.h @@ -48,17 +48,24 @@ QT_BEGIN_NAMESPACE class QPlatformIntegration; +class QStyleHintsPrivate; class Q_GUI_EXPORT QStyleHints : public QObject { Q_OBJECT + Q_DECLARE_PRIVATE(QStyleHints) public: + void setMouseDoubleClickInterval(int mouseDoubleClickInterval); int mouseDoubleClickInterval() const; + void setStartDragDistance(int startDragDistance); int startDragDistance() const; + void setStartDragTime(int startDragTime); int startDragTime() const; int startDragVelocity() const; + void setKeyboardInputInterval(int keyboardInputInterval); int keyboardInputInterval() const; int keyboardAutoRepeatRate() const; + void setCursorFlashTime(int cursorFlashTime); int cursorFlashTime() const; bool showIsFullScreen() const; int passwordMaskDelay() const; diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 70c63086a3..210cb29120 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -2599,7 +2599,7 @@ QDesktopWidget *QApplication::desktop() void QApplication::setStartDragTime(int ms) { - Q_UNUSED(ms) + QGuiApplication::styleHints()->setStartDragTime(ms); } /*! @@ -2632,7 +2632,7 @@ int QApplication::startDragTime() void QApplication::setStartDragDistance(int l) { - Q_UNUSED(l); + QGuiApplication::styleHints()->setStartDragDistance(l); } /*! @@ -3599,7 +3599,7 @@ bool QApplication::keypadNavigationEnabled() */ void QApplication::setCursorFlashTime(int msecs) { - Q_UNUSED(msecs); + QGuiApplication::styleHints()->setCursorFlashTime(msecs); } int QApplication::cursorFlashTime() @@ -3614,12 +3614,10 @@ int QApplication::cursorFlashTime() The default value on X11 is 400 milliseconds. On Windows and Mac OS, the operating system's value is used. - - Setting the interval is not supported anymore in Qt 5. */ void QApplication::setDoubleClickInterval(int ms) { - Q_UNUSED(ms); + QGuiApplication::styleHints()->setMouseDoubleClickInterval(ms); } int QApplication::doubleClickInterval() @@ -3647,7 +3645,7 @@ int QApplication::doubleClickInterval() */ void QApplication::setKeyboardInputInterval(int ms) { - Q_UNUSED(ms); + QGuiApplication::styleHints()->setKeyboardInputInterval(ms); } int QApplication::keyboardInputInterval() diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp index fee8b6aee5..f2fa1f87fa 100644 --- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp @@ -178,6 +178,8 @@ private slots: void globalStaticObjectDestruction(); // run this last void abortQuitOnShow(); + + void settableStyleHints(); // Needs to run last as it changes style hints. }; class EventSpy : public QObject @@ -2247,6 +2249,22 @@ void tst_QApplication::abortQuitOnShow() QCOMPARE(app.exec(), 1); } +void tst_QApplication::settableStyleHints() +{ + int argc = 0; + QApplication app(argc, 0); + QApplication::setCursorFlashTime(437); + QCOMPARE(QApplication::cursorFlashTime(), 437); + QApplication::setDoubleClickInterval(128); + QCOMPARE(QApplication::doubleClickInterval(), 128); + QApplication::setStartDragDistance(122000); + QCOMPARE(QApplication::startDragDistance(), 122000); + QApplication::setStartDragTime(834); + QCOMPARE(QApplication::startDragTime(), 834); + QApplication::setKeyboardInputInterval(309); + QCOMPARE(QApplication::keyboardInputInterval(), 309); +} + /* This test is meant to ensure that certain objects (public & commonly used) can safely be used in a Q_GLOBAL_STATIC such that their destructors are From 109bf980b37fed405c6c1eb14cb9c83ff897e389 Mon Sep 17 00:00:00 2001 From: Tasuku Suzuki Date: Sat, 21 Sep 2013 15:23:16 +0900 Subject: [PATCH 045/684] Fix a bug in QSqlQuery::isNull documentation the method returns true if there is not such field. Change-Id: I25db8de4561d3e0604f3e64edc1810140ba4aad2 Reviewed-by: Andy Shaw Reviewed-by: Mark Brand --- src/sql/kernel/qsqlquery.cpp | 17 +++++++++-------- .../auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp | 3 +++ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/sql/kernel/qsqlquery.cpp b/src/sql/kernel/qsqlquery.cpp index 661a582afe..e5f4c5fc56 100644 --- a/src/sql/kernel/qsqlquery.cpp +++ b/src/sql/kernel/qsqlquery.cpp @@ -309,19 +309,20 @@ QSqlQuery& QSqlQuery::operator=(const QSqlQuery& other) } /*! - Returns \c true if the query is \l{isActive()}{active} and positioned - on a valid record and the \a field is NULL; otherwise returns - false. Note that for some drivers, isNull() will not return accurate - information until after an attempt is made to retrieve data. + Returns \c true if the query is not \l{isActive()}{active}, + the query is not positioned on a valid record, + there is no such field, or the field is null; otherwise \c false. + Note that for some drivers, isNull() will not return accurate + information until after an attempt is made to retrieve data. - \sa isActive(), isValid(), value() + \sa isActive(), isValid(), value() */ bool QSqlQuery::isNull(int field) const { - if (d->sqlResult->isActive() && d->sqlResult->isValid()) - return d->sqlResult->isNull(field); - return true; + return !d->sqlResult->isActive() + || !d->sqlResult->isValid() + || d->sqlResult->isNull(field); } /*! diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp index 1a100ce706..9098d5b101 100644 --- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp @@ -1393,6 +1393,9 @@ void tst_QSqlQuery::isNull() QVERIFY( q.next() ); QVERIFY( !q.isNull( 0 ) ); QVERIFY( !q.isNull( 1 ) ); + + // For a non existent field, it should be returning true. + QVERIFY(q.isNull(2)); } /*! TDS specific BIT field test */ From c241e4aa49216b3f11c483b28b363be0b095e8dd Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Thu, 24 Oct 2013 10:56:12 +0100 Subject: [PATCH 046/684] WinRT: Added msvc2013 mkspecs Change-Id: I052f6ba19056e7c0df6d7ea5548eb4dac4db125e Reviewed-by: Andrew Knight Reviewed-by: Friedemann Kleint Reviewed-by: Oliver Wolff --- mkspecs/common/winrt_winphone/qmake.conf | 3 +- mkspecs/winphone-arm-msvc2012/qmake.conf | 1 + mkspecs/winphone-x86-msvc2012/qmake.conf | 1 + mkspecs/winrt-arm-msvc2012/qmake.conf | 1 + mkspecs/winrt-arm-msvc2013/qmake.conf | 17 +++++++++ mkspecs/winrt-arm-msvc2013/qplatformdefs.h | 42 ++++++++++++++++++++++ mkspecs/winrt-x64-msvc2012/qmake.conf | 1 + mkspecs/winrt-x64-msvc2013/qmake.conf | 17 +++++++++ mkspecs/winrt-x64-msvc2013/qplatformdefs.h | 42 ++++++++++++++++++++++ mkspecs/winrt-x86-msvc2012/qmake.conf | 1 + mkspecs/winrt-x86-msvc2013/qmake.conf | 17 +++++++++ mkspecs/winrt-x86-msvc2013/qplatformdefs.h | 42 ++++++++++++++++++++++ 12 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 mkspecs/winrt-arm-msvc2013/qmake.conf create mode 100644 mkspecs/winrt-arm-msvc2013/qplatformdefs.h create mode 100644 mkspecs/winrt-x64-msvc2013/qmake.conf create mode 100644 mkspecs/winrt-x64-msvc2013/qplatformdefs.h create mode 100644 mkspecs/winrt-x86-msvc2013/qmake.conf create mode 100644 mkspecs/winrt-x86-msvc2013/qplatformdefs.h diff --git a/mkspecs/common/winrt_winphone/qmake.conf b/mkspecs/common/winrt_winphone/qmake.conf index 67831c435b..b7ac7a75cf 100644 --- a/mkspecs/common/winrt_winphone/qmake.conf +++ b/mkspecs/common/winrt_winphone/qmake.conf @@ -1,7 +1,7 @@ # # qmake configuration for winrt and windows phone 8 # -# Written for Microsoft Visual C++ 2012 +# Written for Microsoft Visual C++ # MAKEFILE_GENERATOR = MSBUILD @@ -10,7 +10,6 @@ QMAKE_PLATFORM = winrt win32 CONFIG += incremental flat precompile_header autogen_precompile_source debug_and_release debug_and_release_target no_generated_target_info autogen_wmappmanifest rtti DEFINES += UNICODE WIN32 QT_LARGEFILE_SUPPORT Q_BYTE_ORDER=Q_LITTLE_ENDIAN \ QT_NO_PRINTER QT_NO_PRINTDIALOG # TODO: Remove when printing is re-enabled -QMAKE_COMPILER_DEFINES += _MSC_VER=1700 DEPLOYMENT_PLUGIN += qwinrt diff --git a/mkspecs/winphone-arm-msvc2012/qmake.conf b/mkspecs/winphone-arm-msvc2012/qmake.conf index 1e31ac51d0..54f96e6709 100644 --- a/mkspecs/winphone-arm-msvc2012/qmake.conf +++ b/mkspecs/winphone-arm-msvc2012/qmake.conf @@ -5,6 +5,7 @@ # include(../common/winrt_winphone/qmake.conf) +QMAKE_COMPILER_DEFINES += _MSC_VER=1700 QMAKE_PLATFORM = winphone $$QMAKE_PLATFORM DEFINES += WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP ARM __ARM__ __arm__ QT_NO_CURSOR diff --git a/mkspecs/winphone-x86-msvc2012/qmake.conf b/mkspecs/winphone-x86-msvc2012/qmake.conf index 8836de58cf..ede9bb59be 100644 --- a/mkspecs/winphone-x86-msvc2012/qmake.conf +++ b/mkspecs/winphone-x86-msvc2012/qmake.conf @@ -5,6 +5,7 @@ # include(../common/winrt_winphone/qmake.conf) +QMAKE_COMPILER_DEFINES += _MSC_VER=1700 QMAKE_PLATFORM = winphone $$QMAKE_PLATFORM DEFINES += WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP X86 __X86__ __x86__ QT_NO_CURSOR diff --git a/mkspecs/winrt-arm-msvc2012/qmake.conf b/mkspecs/winrt-arm-msvc2012/qmake.conf index cafdbf4a93..7abca86511 100644 --- a/mkspecs/winrt-arm-msvc2012/qmake.conf +++ b/mkspecs/winrt-arm-msvc2012/qmake.conf @@ -5,6 +5,7 @@ # include(../common/winrt_winphone/qmake.conf) +QMAKE_COMPILER_DEFINES += _MSC_VER=1700 DEFINES += WINAPI_FAMILY=WINAPI_FAMILY_APP ARM __ARM__ __arm__ QMAKE_LFLAGS += /MACHINE:ARM diff --git a/mkspecs/winrt-arm-msvc2013/qmake.conf b/mkspecs/winrt-arm-msvc2013/qmake.conf new file mode 100644 index 0000000000..2fd326de24 --- /dev/null +++ b/mkspecs/winrt-arm-msvc2013/qmake.conf @@ -0,0 +1,17 @@ +# +# qmake configuration for winrt-arm-msvc2013 +# +# Written for Microsoft Visual C++ 2013 +# + +include(../common/winrt_winphone/qmake.conf) +QMAKE_COMPILER_DEFINES += _MSC_VER=1800 +DEFINES += WINAPI_FAMILY=WINAPI_FAMILY_APP ARM __ARM__ __arm__ + +QMAKE_CFLAGS += -FS +QMAKE_CXXFLAGS += -FS +QMAKE_LFLAGS += /MACHINE:ARM + +QMAKE_LIBS += windowscodecs.lib kernel32.lib ole32.lib + +VCPROJ_ARCH = ARM diff --git a/mkspecs/winrt-arm-msvc2013/qplatformdefs.h b/mkspecs/winrt-arm-msvc2013/qplatformdefs.h new file mode 100644 index 0000000000..781107b2dc --- /dev/null +++ b/mkspecs/winrt-arm-msvc2013/qplatformdefs.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the qmake spec 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 "../common/winrt_winphone/qplatformdefs.h" diff --git a/mkspecs/winrt-x64-msvc2012/qmake.conf b/mkspecs/winrt-x64-msvc2012/qmake.conf index 784d0ccb7e..c5efcc5481 100644 --- a/mkspecs/winrt-x64-msvc2012/qmake.conf +++ b/mkspecs/winrt-x64-msvc2012/qmake.conf @@ -5,6 +5,7 @@ # include(../common/winrt_winphone/qmake.conf) +QMAKE_COMPILER_DEFINES += _MSC_VER=1700 DEFINES += WINAPI_FAMILY=WINAPI_FAMILY_APP X64 __X64__ __x64__ QMAKE_LFLAGS += /MACHINE:X64 diff --git a/mkspecs/winrt-x64-msvc2013/qmake.conf b/mkspecs/winrt-x64-msvc2013/qmake.conf new file mode 100644 index 0000000000..417cb0f1a0 --- /dev/null +++ b/mkspecs/winrt-x64-msvc2013/qmake.conf @@ -0,0 +1,17 @@ +# +# qmake configuration for winrt-x64-msvc2013 +# +# Written for Microsoft Visual C++ 2013 +# + +include(../common/winrt_winphone/qmake.conf) +QMAKE_COMPILER_DEFINES += _MSC_VER=1800 +DEFINES += WINAPI_FAMILY=WINAPI_FAMILY_APP X64 __X64__ __x64__ + +QMAKE_CFLAGS += -FS +QMAKE_CXXFLAGS += -FS +QMAKE_LFLAGS += /MACHINE:X64 + +QMAKE_LIBS += windowscodecs.lib kernel32.lib ole32.lib + +VCPROJ_ARCH = x64 diff --git a/mkspecs/winrt-x64-msvc2013/qplatformdefs.h b/mkspecs/winrt-x64-msvc2013/qplatformdefs.h new file mode 100644 index 0000000000..781107b2dc --- /dev/null +++ b/mkspecs/winrt-x64-msvc2013/qplatformdefs.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the qmake spec 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 "../common/winrt_winphone/qplatformdefs.h" diff --git a/mkspecs/winrt-x86-msvc2012/qmake.conf b/mkspecs/winrt-x86-msvc2012/qmake.conf index 559c9b5d05..7c0522adb7 100644 --- a/mkspecs/winrt-x86-msvc2012/qmake.conf +++ b/mkspecs/winrt-x86-msvc2012/qmake.conf @@ -5,6 +5,7 @@ # include(../common/winrt_winphone/qmake.conf) +QMAKE_COMPILER_DEFINES += _MSC_VER=1700 DEFINES += WINAPI_FAMILY=WINAPI_FAMILY_APP X86 __X86__ __x86__ QMAKE_LFLAGS += /MACHINE:X86 diff --git a/mkspecs/winrt-x86-msvc2013/qmake.conf b/mkspecs/winrt-x86-msvc2013/qmake.conf new file mode 100644 index 0000000000..075067c04e --- /dev/null +++ b/mkspecs/winrt-x86-msvc2013/qmake.conf @@ -0,0 +1,17 @@ +# +# qmake configuration for winrt-x86-msvc2013 +# +# Written for Microsoft Visual C++ 2013 +# + +include(../common/winrt_winphone/qmake.conf) +QMAKE_COMPILER_DEFINES += _MSC_VER=1800 _WIN32 +DEFINES += WINAPI_FAMILY=WINAPI_FAMILY_APP X86 __X86__ __x86__ + +QMAKE_CFLAGS += -FS +QMAKE_CXXFLAGS += -FS +QMAKE_LFLAGS += /MACHINE:X86 + +QMAKE_LIBS += windowscodecs.lib kernel32.lib ole32.lib + +VCPROJ_ARCH = x86 diff --git a/mkspecs/winrt-x86-msvc2013/qplatformdefs.h b/mkspecs/winrt-x86-msvc2013/qplatformdefs.h new file mode 100644 index 0000000000..781107b2dc --- /dev/null +++ b/mkspecs/winrt-x86-msvc2013/qplatformdefs.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the qmake spec 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 "../common/winrt_winphone/qplatformdefs.h" From 07ee43142bca89958567af55d843e8920c644d35 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Thu, 24 Oct 2013 20:14:10 +0300 Subject: [PATCH 047/684] qmake: Support MSVC2013 for WinRT builds Change-Id: I1c102f0b029616997d72933a90c0f9a2a3a9e222 Reviewed-by: Oswald Buddenhagen Reviewed-by: Oliver Wolff --- mkspecs/winphone-arm-msvc2012/qmake.conf | 3 ++ mkspecs/winphone-x86-msvc2012/qmake.conf | 3 ++ mkspecs/winrt-arm-msvc2012/qmake.conf | 3 ++ mkspecs/winrt-arm-msvc2013/qmake.conf | 3 ++ mkspecs/winrt-x64-msvc2012/qmake.conf | 3 ++ mkspecs/winrt-x64-msvc2013/qmake.conf | 3 ++ mkspecs/winrt-x86-msvc2012/qmake.conf | 3 ++ mkspecs/winrt-x86-msvc2013/qmake.conf | 3 ++ qmake/generators/win32/msvc_nmake.cpp | 66 +++++++++++++++--------- 9 files changed, 65 insertions(+), 25 deletions(-) diff --git a/mkspecs/winphone-arm-msvc2012/qmake.conf b/mkspecs/winphone-arm-msvc2012/qmake.conf index 54f96e6709..d5d26d2a96 100644 --- a/mkspecs/winphone-arm-msvc2012/qmake.conf +++ b/mkspecs/winphone-arm-msvc2012/qmake.conf @@ -14,3 +14,6 @@ QMAKE_LFLAGS += /MACHINE:ARM QMAKE_LIBS += WindowsPhoneCore.lib PhoneAppModelHost.lib ws2_32.lib VCPROJ_ARCH = ARM +MSVC_VER = 11.0 +WINSDK_VER = 8.0 +WINTARGET_VER = WP80 diff --git a/mkspecs/winphone-x86-msvc2012/qmake.conf b/mkspecs/winphone-x86-msvc2012/qmake.conf index ede9bb59be..59e6fb45db 100644 --- a/mkspecs/winphone-x86-msvc2012/qmake.conf +++ b/mkspecs/winphone-x86-msvc2012/qmake.conf @@ -14,3 +14,6 @@ QMAKE_LFLAGS += /MACHINE:X86 QMAKE_LIBS += WindowsPhoneCore.lib PhoneAppModelHost.lib ws2_32.lib VCPROJ_ARCH = x86 +MSVC_VER = 11.0 +WINSDK_VER = 8.0 +WINTARGET_VER = WP80 diff --git a/mkspecs/winrt-arm-msvc2012/qmake.conf b/mkspecs/winrt-arm-msvc2012/qmake.conf index 7abca86511..951dc2db35 100644 --- a/mkspecs/winrt-arm-msvc2012/qmake.conf +++ b/mkspecs/winrt-arm-msvc2012/qmake.conf @@ -13,3 +13,6 @@ QMAKE_LFLAGS += /MACHINE:ARM QMAKE_LIBS += windowscodecs.lib kernel32.lib ole32.lib VCPROJ_ARCH = ARM +MSVC_VER = 11.0 +WINSDK_VER = 8.0 +WINTARGET_VER = win8 diff --git a/mkspecs/winrt-arm-msvc2013/qmake.conf b/mkspecs/winrt-arm-msvc2013/qmake.conf index 2fd326de24..5527a7a41c 100644 --- a/mkspecs/winrt-arm-msvc2013/qmake.conf +++ b/mkspecs/winrt-arm-msvc2013/qmake.conf @@ -15,3 +15,6 @@ QMAKE_LFLAGS += /MACHINE:ARM QMAKE_LIBS += windowscodecs.lib kernel32.lib ole32.lib VCPROJ_ARCH = ARM +MSVC_VER = 12.0 +WINSDK_VER = 8.1 +WINTARGET_VER = winv6.3 diff --git a/mkspecs/winrt-x64-msvc2012/qmake.conf b/mkspecs/winrt-x64-msvc2012/qmake.conf index c5efcc5481..96806499bc 100644 --- a/mkspecs/winrt-x64-msvc2012/qmake.conf +++ b/mkspecs/winrt-x64-msvc2012/qmake.conf @@ -13,3 +13,6 @@ QMAKE_LFLAGS += /MACHINE:X64 QMAKE_LIBS += windowscodecs.lib kernel32.lib ole32.lib VCPROJ_ARCH = x64 +MSVC_VER = 11.0 +WINSDK_VER = 8.0 +WINTARGET_VER = win8 diff --git a/mkspecs/winrt-x64-msvc2013/qmake.conf b/mkspecs/winrt-x64-msvc2013/qmake.conf index 417cb0f1a0..e7d2432cc4 100644 --- a/mkspecs/winrt-x64-msvc2013/qmake.conf +++ b/mkspecs/winrt-x64-msvc2013/qmake.conf @@ -15,3 +15,6 @@ QMAKE_LFLAGS += /MACHINE:X64 QMAKE_LIBS += windowscodecs.lib kernel32.lib ole32.lib VCPROJ_ARCH = x64 +MSVC_VER = 12.0 +WINSDK_VER = 8.1 +WINTARGET_VER = winv6.3 diff --git a/mkspecs/winrt-x86-msvc2012/qmake.conf b/mkspecs/winrt-x86-msvc2012/qmake.conf index 7c0522adb7..b0d9017ebb 100644 --- a/mkspecs/winrt-x86-msvc2012/qmake.conf +++ b/mkspecs/winrt-x86-msvc2012/qmake.conf @@ -13,3 +13,6 @@ QMAKE_LFLAGS += /MACHINE:X86 QMAKE_LIBS += windowscodecs.lib kernel32.lib ole32.lib VCPROJ_ARCH = x86 +MSVC_VER = 11.0 +WINSDK_VER = 8.0 +WINTARGET_VER = win8 diff --git a/mkspecs/winrt-x86-msvc2013/qmake.conf b/mkspecs/winrt-x86-msvc2013/qmake.conf index 075067c04e..40fd339b5b 100644 --- a/mkspecs/winrt-x86-msvc2013/qmake.conf +++ b/mkspecs/winrt-x86-msvc2013/qmake.conf @@ -15,3 +15,6 @@ QMAKE_LFLAGS += /MACHINE:X86 QMAKE_LIBS += windowscodecs.lib kernel32.lib ole32.lib VCPROJ_ARCH = x86 +MSVC_VER = 12.0 +WINSDK_VER = 8.1 +WINTARGET_VER = winv6.3 diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index 3185e68ecc..4412a131ad 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -126,24 +126,56 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t) compiler = QStringLiteral("x86_amd64"); compilerArch = QStringLiteral("amd64"); } -#ifdef Q_OS_WIN64 - const QString regKey = QStringLiteral("Software\\Wow6432Node\\Microsoft\\VisualStudio\\11.0\\Setup\\VC\\ProductDir"); -#else - const QString regKey = QStringLiteral("Software\\Microsoft\\VisualStudio\\11.0\\Setup\\VC\\ProductDir"); + + const QString msvcVer = project->first("MSVC_VER").toQString(); + if (msvcVer.isEmpty()) { + fprintf(stderr, "Mkspec does not specify MSVC_VER. Cannot continue.\n"); + return false; + } + const QString winsdkVer = project->first("WINSDK_VER").toQString(); + if (winsdkVer.isEmpty()) { + fprintf(stderr, "Mkspec does not specify WINSDK_VER. Cannot continue.\n"); + return false; + } + const QString targetVer = project->first("WINTARGET_VER").toQString(); + if (targetVer.isEmpty()) { + fprintf(stderr, "Mkspec does not specify WINTARGET_VER. Cannot continue.\n"); + return false; + } + + QString regKeyPrefix; +#if !defined(Q_OS_WIN64) && _WIN32_WINNT >= 0x0501 + BOOL isWow64; + IsWow64Process(GetCurrentProcess(), &isWow64); + if (!isWow64) + regKeyPrefix = QStringLiteral("Software\\"); + else #endif + regKeyPrefix = QStringLiteral("Software\\Wow6432Node\\"); + + QString regKey = regKeyPrefix + QStringLiteral("Microsoft\\VisualStudio\\") + msvcVer + ("\\Setup\\VC\\ProductDir"); const QString vcInstallDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey); if (vcInstallDir.isEmpty()) { - fprintf(stderr, "Failed to find the Visual Studio 2012 installation directory.\n" - "Is it installed?.\n"); + fprintf(stderr, "Failed to find the Visual Studio installation directory.\n"); + return false; + } + + const bool isPhone = project->isActiveConfig(QStringLiteral("winphone")); + regKey = regKeyPrefix + + (isPhone ? QStringLiteral("Microsoft\\Microsoft SDKs\\WindowsPhone\\v") + : QStringLiteral("Microsoft\\Microsoft SDKs\\Windows\\v")) + + winsdkVer + QStringLiteral("\\InstallationFolder"); + const QString kitDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey); + if (kitDir.isEmpty()) { + fprintf(stderr, "Failed to find the Windows Kit installation directory.\n"); return false; } QStringList incDirs; QStringList libDirs; QStringList binDirs; - const bool isPhone = project->isActiveConfig(QStringLiteral("winphone")); if (isPhone) { - QString sdkDir = vcInstallDir + QStringLiteral("/WPSDK/WP80"); + QString sdkDir = vcInstallDir + QStringLiteral("/WPSDK/") + targetVer; if (!QDir(sdkDir).exists()) { fprintf(stderr, "Failed to find the Windows Phone SDK in %s.\n" "Check that it is properly installed.\n", @@ -153,14 +185,6 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t) incDirs << sdkDir + QStringLiteral("/include"); libDirs << sdkDir + QStringLiteral("/lib/") + compilerArch; binDirs << sdkDir + QStringLiteral("/bin/") + compiler; - - QString kitDir = vcInstallDir + QStringLiteral("/../../Windows Phone Kits/8.0"); - if (!QDir(kitDir).exists()) { - fprintf(stderr, "Failed to find the Windows Phone Kit in %s.\n" - "Check that it is properly installed.\n", - qPrintable(QDir::toNativeSeparators(kitDir))); - return false; - } libDirs << kitDir + QStringLiteral("/lib/") + arch; incDirs << kitDir + QStringLiteral("/include") << kitDir + QStringLiteral("/include/abi") @@ -171,15 +195,7 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t) libDirs << vcInstallDir + QStringLiteral("/lib/") + compilerArch; binDirs << vcInstallDir + QStringLiteral("/bin/") + compiler << vcInstallDir + QStringLiteral("/../Common7/IDE"); - - QString kitDir = vcInstallDir + QStringLiteral("/../../Windows Kits/8.0"); - if (!QDir(kitDir).exists()) { - fprintf(stderr, "Failed to find the Windows Kit in %s.\n" - "Check that it is properly installed.\n", - qPrintable(QDir::toNativeSeparators(kitDir))); - return false; - } - libDirs << kitDir + QStringLiteral("/Lib/win8/um/") + arch; + libDirs << kitDir + QStringLiteral("/Lib/") + targetVer + ("/um/") + arch; incDirs << kitDir + QStringLiteral("/include/um") << kitDir + QStringLiteral("/include/shared") << kitDir + QStringLiteral("/include/winrt"); From 2ced0cb08d7e335bcf419f4e068b423c6660dd77 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Thu, 24 Oct 2013 10:56:47 +0100 Subject: [PATCH 048/684] Clean up common winrt/winphone mkspec Change-Id: I010bf977e01fab2f39184bbe730ec70128cc2982 Reviewed-by: Oswald Buddenhagen --- mkspecs/common/winrt_winphone/qmake.conf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mkspecs/common/winrt_winphone/qmake.conf b/mkspecs/common/winrt_winphone/qmake.conf index b7ac7a75cf..39b5ddc0c4 100644 --- a/mkspecs/common/winrt_winphone/qmake.conf +++ b/mkspecs/common/winrt_winphone/qmake.conf @@ -18,7 +18,6 @@ QMAKE_LEX = flex QMAKE_LEXFLAGS = QMAKE_YACC = byacc QMAKE_YACCFLAGS = -d -#QMAKE_CFLAGS = -nologo -Zm200 -Zc:wchar_t- QMAKE_CFLAGS = -nologo -Zm200 QMAKE_CFLAGS_WARN_ON = -W3 QMAKE_CFLAGS_WARN_OFF = -W0 @@ -91,5 +90,5 @@ include(../shell-win32.conf) VCPROJ_EXTENSION = .vcxproj VCSOLUTION_EXTENSION = .sln -VCPROJ_KEYWORD = Qt4VSv1.0 +VCPROJ_KEYWORD = Qt4VSv1.0 load(qt_config) From 1f22c1d98162b3a7d34ceb64c543d6580333b434 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Sun, 1 Sep 2013 23:34:20 +0200 Subject: [PATCH 049/684] Introduce QTextDocument::baseUrl Required for QQuickText & friends to implement image resource handling in a clean way - to get rid of QQuickTextDocumentWithImageResources and eventually make QQuickTextEdit's document interchangeable. Change-Id: I97314a6c3e2d5726539d5722795a472631388cb0 Reviewed-by: Konstantin Ritt --- src/gui/text/qtextdocument.cpp | 80 ++++++++++++++----- src/gui/text/qtextdocument.h | 8 +- src/gui/text/qtextdocument_p.h | 1 + .../text/qtextdocument/tst_qtextdocument.cpp | 50 ++++++++++++ 4 files changed, 115 insertions(+), 24 deletions(-) diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 30e0f32547..180b09be33 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -550,6 +550,39 @@ void QTextDocument::setDefaultTextOption(const QTextOption &option) d->lout->documentChanged(0, 0, d->length()); } +/*! + \property QTextDocument::baseUrl + \since 5.3 + \brief the base URL used to resolve relative resource URLs within the document. + + Resource URLs are resolved to be within the same directory as the target of the base + URL meaning any portion of the path after the last '/' will be ignored. + + \table + \header \li Base URL \li Relative URL \li Resolved URL + \row \li file:///path/to/content \li images/logo.png \li file:///path/to/images/logo.png + \row \li file:///path/to/content/ \li images/logo.png \li file:///path/to/content/images/logo.png + \row \li file:///path/to/content/index.html \li images/logo.png \li file:///path/to/content/images/logo.png + \row \li file:///path/to/content/images/ \li ../images/logo.png \li file:///path/to/content/images/logo.png + \endtable +*/ +QUrl QTextDocument::baseUrl() const +{ + Q_D(const QTextDocument); + return d->baseUrl; +} + +void QTextDocument::setBaseUrl(const QUrl &url) +{ + Q_D(QTextDocument); + if (d->baseUrl != url) { + d->baseUrl = url; + if (d->lout) + d->lout->documentChanged(0, 0, d->length()); + emit baseUrlChanged(url); + } +} + /*! \since 4.8 @@ -1849,11 +1882,12 @@ void QTextDocument::print(QPagedPaintDevice *printer) const QVariant QTextDocument::resource(int type, const QUrl &name) const { Q_D(const QTextDocument); - QVariant r = d->resources.value(name); + const QUrl url = d->baseUrl.resolved(name); + QVariant r = d->resources.value(url); if (!r.isValid()) { - r = d->cachedResources.value(name); + r = d->cachedResources.value(url); if (!r.isValid()) - r = const_cast(this)->loadResource(type, name); + r = const_cast(this)->loadResource(type, url); } return r; } @@ -1924,27 +1958,29 @@ QVariant QTextDocument::loadResource(int type, const QUrl &name) } // if resource was not loaded try to load it here - if (!qobject_cast(p) && r.isNull() && name.isRelative()) { - QUrl currentURL = d->url; + if (!qobject_cast(p) && r.isNull()) { QUrl resourceUrl = name; - // For the second case QUrl can merge "#someanchor" with "foo.html" - // correctly to "foo.html#someanchor" - if (!(currentURL.isRelative() - || (currentURL.scheme() == QLatin1String("file") - && !QFileInfo(currentURL.toLocalFile()).isAbsolute())) - || (name.hasFragment() && name.path().isEmpty())) { - resourceUrl = currentURL.resolved(name); - } else { - // this is our last resort when current url and new url are both relative - // we try to resolve against the current working directory in the local - // file system. - QFileInfo fi(currentURL.toLocalFile()); - if (fi.exists()) { - resourceUrl = - QUrl::fromLocalFile(fi.absolutePath() + QDir::separator()).resolved(name); - } else if (currentURL.isEmpty()) { - resourceUrl.setScheme(QLatin1String("file")); + if (name.isRelative()) { + QUrl currentURL = d->url; + // For the second case QUrl can merge "#someanchor" with "foo.html" + // correctly to "foo.html#someanchor" + if (!(currentURL.isRelative() + || (currentURL.scheme() == QLatin1String("file") + && !QFileInfo(currentURL.toLocalFile()).isAbsolute())) + || (name.hasFragment() && name.path().isEmpty())) { + resourceUrl = currentURL.resolved(name); + } else { + // this is our last resort when current url and new url are both relative + // we try to resolve against the current working directory in the local + // file system. + QFileInfo fi(currentURL.toLocalFile()); + if (fi.exists()) { + resourceUrl = + QUrl::fromLocalFile(fi.absolutePath() + QDir::separator()).resolved(name); + } else if (currentURL.isEmpty()) { + resourceUrl.setScheme(QLatin1String("file")); + } } } diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h index a85e9c86c9..24e93b7e63 100644 --- a/src/gui/text/qtextdocument.h +++ b/src/gui/text/qtextdocument.h @@ -47,6 +47,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -63,7 +64,6 @@ class QTextFormat; class QTextFrame; class QTextBlock; class QTextCodec; -class QUrl; class QVariant; class QRectF; class QTextOption; @@ -114,6 +114,7 @@ class Q_GUI_EXPORT QTextDocument : public QObject Q_PROPERTY(int maximumBlockCount READ maximumBlockCount WRITE setMaximumBlockCount) Q_PROPERTY(qreal documentMargin READ documentMargin WRITE setDocumentMargin) QDOC_PROPERTY(QTextOption defaultTextOption READ defaultTextOption WRITE setDefaultTextOption) + Q_PROPERTY(QUrl baseUrl READ baseUrl WRITE setBaseUrl NOTIFY baseUrlChanged) public: explicit QTextDocument(QObject *parent = 0); @@ -256,6 +257,9 @@ public: QTextOption defaultTextOption() const; void setDefaultTextOption(const QTextOption &option); + QUrl baseUrl() const; + void setBaseUrl(const QUrl &url); + Qt::CursorMoveStyle defaultCursorMoveStyle() const; void setDefaultCursorMoveStyle(Qt::CursorMoveStyle style); @@ -268,7 +272,7 @@ Q_SIGNALS: void modificationChanged(bool m); void cursorPositionChanged(const QTextCursor &cursor); void blockCountChanged(int newBlockCount); - + void baseUrlChanged(const QUrl &url); void documentLayoutChanged(); public Q_SLOTS: diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h index 1394e88465..b3358161c5 100644 --- a/src/gui/text/qtextdocument_p.h +++ b/src/gui/text/qtextdocument_p.h @@ -355,6 +355,7 @@ public: QString url; qreal indentWidth; qreal documentMargin; + QUrl baseUrl; void mergeCachedResources(const QTextDocumentPrivate *priv); diff --git a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp index b065f537f7..1abac3a28a 100644 --- a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp +++ b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp @@ -189,6 +189,9 @@ private slots: void QTBUG27354_spaceAndSoftSpace(); void cssInheritance(); + void baseUrl_data(); + void baseUrl(); + void QTBUG28998_linkColor(); private: @@ -2978,6 +2981,53 @@ void tst_QTextDocument::cssInheritance() } } +class BaseDocument : public QTextDocument +{ +public: + QUrl loadedResource() const { return resourceUrl; } + + QVariant loadResource(int type, const QUrl &name) + { + resourceUrl = name; + return QTextDocument::loadResource(type, name); + } + +private: + QUrl resourceUrl; +}; + +void tst_QTextDocument::baseUrl_data() +{ + QTest::addColumn("base"); + QTest::addColumn("resource"); + QTest::addColumn("loaded"); + + QTest::newRow("1") << QUrl() << QUrl("images/logo.png") << QUrl("images/logo.png"); + QTest::newRow("2") << QUrl("file:///path/to/content") << QUrl("images/logo.png") << QUrl("file:///path/to/images/logo.png"); + QTest::newRow("3") << QUrl("file:///path/to/content/") << QUrl("images/logo.png") << QUrl("file:///path/to/content/images/logo.png"); + QTest::newRow("4") << QUrl("file:///path/to/content/images") << QUrl("images/logo.png") << QUrl("file:///path/to/content/images/logo.png"); + QTest::newRow("5") << QUrl("file:///path/to/content/images/") << QUrl("images/logo.png") << QUrl("file:///path/to/content/images/images/logo.png"); + QTest::newRow("6") << QUrl("file:///path/to/content/images") << QUrl("../images/logo.png") << QUrl("file:///path/to/images/logo.png"); + QTest::newRow("7") << QUrl("file:///path/to/content/images/") << QUrl("../images/logo.png") << QUrl("file:///path/to/content/images/logo.png"); + QTest::newRow("8") << QUrl("file:///path/to/content/index.html") << QUrl("images/logo.png") << QUrl("file:///path/to/content/images/logo.png"); +} + +void tst_QTextDocument::baseUrl() +{ + QFETCH(QUrl, base); + QFETCH(QUrl, resource); + QFETCH(QUrl, loaded); + + BaseDocument document; + QVERIFY(!document.baseUrl().isValid()); + document.setBaseUrl(base); + QCOMPARE(document.baseUrl(), base); + + document.setHtml(QString("").arg(resource.toString())); + document.resource(QTextDocument::ImageResource, resource); + QCOMPARE(document.loadedResource(), loaded); +} + void tst_QTextDocument::QTBUG28998_linkColor() { QPalette pal; From db98b052ac671122437f181feeffb0b270318d8d Mon Sep 17 00:00:00 2001 From: Roger Maclean Date: Thu, 10 Oct 2013 15:25:55 -0400 Subject: [PATCH 050/684] Add support for BB10 input method framework Added input method support for the BB10 variant of Qt to the extent possible using standard Qt APIs. This adds support for text predictions and entry of languages such as Chinese. Change in interface to QQnxAbstractVirtualKeyboard was made because it is felt the new one is slightly nicer. It doesn't appear safe to assume the focus object has a particular property and in fact in my tests the code failed to work. In some cases the code uses variable and function naming at odds with normal Qt coding standards. This has been done for functions called and data provided by the BB10 input system as for those of us who need to maintain such things, it makes their meaning considerably clearer. While qqnxinputcontext_imf.cpp was used as an initial base for development one can consider the new version as largely new code. I don't believe the original version was ever complete and in any event would not compile. Change-Id: I09470801ffa237cee67da40c0b3d02ed5c77531e Reviewed-by: Rafael Roquetto --- src/plugins/platforms/qnx/qnx.pro | 3 +- .../qnx/qqnxabstractvirtualkeyboard.cpp | 30 +- .../qnx/qqnxabstractvirtualkeyboard.h | 7 +- .../platforms/qnx/qqnxinputcontext_imf.cpp | 1597 +++++++---------- .../platforms/qnx/qqnxinputcontext_imf.h | 62 +- .../platforms/qnx/qqnxinputcontext_noimf.cpp | 9 +- src/plugins/platforms/qnx/qqnxintegration.cpp | 27 +- .../platforms/qnx/qqnxscreeneventfilter.h | 58 + .../platforms/qnx/qqnxscreeneventhandler.cpp | 31 +- .../platforms/qnx/qqnxscreeneventhandler.h | 7 +- .../platforms/qnx/qqnxvirtualkeyboardbps.cpp | 6 +- 11 files changed, 848 insertions(+), 989 deletions(-) create mode 100644 src/plugins/platforms/qnx/qqnxscreeneventfilter.h diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro index f5a4e0735f..e2c25add0b 100644 --- a/src/plugins/platforms/qnx/qnx.pro +++ b/src/plugins/platforms/qnx/qnx.pro @@ -76,7 +76,8 @@ HEADERS = main.h \ qqnxabstractcover.h \ qqnxservices.h \ qqnxcursor.h \ - qqnxrasterwindow.h + qqnxrasterwindow.h \ + qqnxscreeneventfilter.h CONFIG(qqnx_screeneventthread) { DEFINES += QQNX_SCREENEVENTTHREAD diff --git a/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.cpp b/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.cpp index a42f73415e..1d8591cfa1 100644 --- a/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.cpp +++ b/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.cpp @@ -1,6 +1,6 @@ /*************************************************************************** ** -** Copyright (C) 2011 - 2012 Research In Motion +** Copyright (C) 2013 BlackBerry Limited. All rights reserved. ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -62,23 +62,19 @@ void QQnxAbstractVirtualKeyboard::setKeyboardMode(KeyboardMode mode) applyKeyboardMode(mode); } -void QQnxAbstractVirtualKeyboard::setInputHintsFromObject(QObject *focusObject) +void QQnxAbstractVirtualKeyboard::setInputHints(int inputHints) { - if (focusObject) { - const Qt::InputMethodHints hints = static_cast( - focusObject->property("inputMethodHints").toInt()); - if (hints & Qt::ImhEmailCharactersOnly) { - setKeyboardMode(QQnxAbstractVirtualKeyboard::Email); - } else if (hints & Qt::ImhDialableCharactersOnly) { - setKeyboardMode(QQnxAbstractVirtualKeyboard::Phone); - } else if (hints & Qt::ImhUrlCharactersOnly) { - setKeyboardMode(QQnxAbstractVirtualKeyboard::Web); - } else if (hints & Qt::ImhFormattedNumbersOnly || hints & Qt::ImhDigitsOnly || - hints & Qt::ImhDate || hints & Qt::ImhTime) { - setKeyboardMode(QQnxAbstractVirtualKeyboard::NumPunc); - } else { - setKeyboardMode(QQnxAbstractVirtualKeyboard::Default); - } + if (inputHints & Qt::ImhEmailCharactersOnly) { + setKeyboardMode(QQnxAbstractVirtualKeyboard::Email); + } else if (inputHints & Qt::ImhDialableCharactersOnly) { + setKeyboardMode(QQnxAbstractVirtualKeyboard::Phone); + } else if (inputHints & Qt::ImhUrlCharactersOnly) { + setKeyboardMode(QQnxAbstractVirtualKeyboard::Web); + } else if (inputHints & Qt::ImhFormattedNumbersOnly || inputHints & Qt::ImhDigitsOnly || + inputHints & Qt::ImhDate || inputHints & Qt::ImhTime) { + setKeyboardMode(QQnxAbstractVirtualKeyboard::NumPunc); + } else if (inputHints & Qt::ImhHiddenText) { + setKeyboardMode(QQnxAbstractVirtualKeyboard::Password); } else { setKeyboardMode(QQnxAbstractVirtualKeyboard::Default); } diff --git a/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.h b/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.h index 9b911e1dec..033d8ebb74 100644 --- a/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.h +++ b/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.h @@ -1,6 +1,6 @@ /*************************************************************************** ** -** Copyright (C) 2011 - 2012 Research In Motion +** Copyright (C) 2013 BlackBerry Limited. All rights reserved. ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -59,10 +59,11 @@ public: // Symbol - All symbols, alternate to NumPunc, currently unused. // Phone - Phone enhanced keyboard - currently unused as no alternate keyboard available to access a-zA-Z // Pin - Keyboard for entering Pins (Hex values) currently unused. + // Password - Keyboard for entering passwords. // // SPECIAL NOTE: Usage of NumPunc may have to be removed, ABC button is non-functional. // - enum KeyboardMode { Default, Url, Email, Web, NumPunc, Symbol, Phone, Pin }; + enum KeyboardMode { Default, Url, Email, Web, NumPunc, Symbol, Phone, Pin, Password }; explicit QQnxAbstractVirtualKeyboard(QObject *parent = 0); @@ -74,7 +75,7 @@ public: QLocale locale() const { return m_locale; } void setKeyboardMode(KeyboardMode mode); - void setInputHintsFromObject(QObject *focusObject); + void setInputHints(int inputHints); KeyboardMode keyboardMode() const { return m_keyboardMode; } Q_SIGNALS: diff --git a/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp b/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp index 580553f6e2..7f60fa1822 100644 --- a/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp +++ b/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp @@ -1,6 +1,6 @@ /*************************************************************************** ** -** Copyright (C) 2011 - 2012 Research In Motion +** Copyright (C) 2013 BlackBerry Limited. All rights reserved. ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -40,10 +40,10 @@ ****************************************************************************/ #include "qqnxinputcontext_imf.h" -#include "qqnxeventthread.h" #include "qqnxabstractvirtualkeyboard.h" #include "qqnxintegration.h" #include "qqnxscreen.h" +#include "qqnxscreeneventhandler.h" #include #include @@ -62,9 +62,9 @@ #include #if defined(QQNXINPUTCONTEXT_IMF_EVENT_DEBUG) -#define qInputContextIMFEventDebug qDebug +#define qInputContextIMFRequestDebug qDebug #else -#define qInputContextIMFEventDebug QT_NO_QDEBUG_MACRO +#define qInputContextIMFRequestDebug QT_NO_QDEBUG_MACRO #endif #if defined(QQNXINPUTCONTEXT_DEBUG) @@ -73,492 +73,419 @@ #define qInputContextDebug QT_NO_QDEBUG_MACRO #endif -/** TODO: - Support inputMethodHints to restrict input (needs additional features in IMF). -*/ +#include +#include -#define STRX(x) #x -#define STR(x) STRX(x) +static QQnxInputContext *sInputContextInstance; +static QColor sSelectedColor(0,0xb8,0,85); +static QColor sAutoCorrectedColor(0,0xb8,0,85); +static QColor sRevertedColor(0,0x8d,0xaf,51); -// Someone tell me why input_control methods are in this namespace, but the rest is not. -using namespace InputMethodSystem; - -#define qs(x) QString::fromLatin1(x) -#define iarg(name) event->mArgs[qs(#name)] = QVariant::fromValue(name) -#define parg(name) event->mArgs[qs(#name)] = QVariant::fromValue((void*)name) -namespace -{ - -spannable_string_t *toSpannableString(const QString &text); static const input_session_t *sInputSession = 0; -bool isSessionOkay(input_session_t *ic) +static bool isSessionOkay(input_session_t *ic) { return ic !=0 && sInputSession != 0 && ic->component_id == sInputSession->component_id; } enum ImfEventType { - ImfBeginBatchEdit, - ImfClearMetaKeyStates, ImfCommitText, ImfDeleteSurroundingText, - ImfEndBatchEdit, ImfFinishComposingText, - ImfGetCursorCapsMode, ImfGetCursorPosition, - ImfGetExtractedText, - ImfGetSelectedText, ImfGetTextAfterCursor, ImfGetTextBeforeCursor, - ImfPerformEditorAction, - ImfReportFullscreenMode, ImfSendEvent, ImfSendAsyncEvent, ImfSetComposingRegion, ImfSetComposingText, - ImfSetSelection + ImfIsTextSelected, + ImfIsAllTextSelected, }; -// We use this class as a round about way to support a posting synchronous event into -// Qt's main thread from the IMF thread. -class ImfEventResult +// IMF requests all arrive on IMF's own thread and have to be posted to the main thread to be processed. +class QQnxImfRequest { public: - ImfEventResult() - { - m_mutex.lock(); - } + QQnxImfRequest(input_session_t *_session, ImfEventType _type) + : session(_session), type(_type) + { } + ~QQnxImfRequest() { } - ~ImfEventResult() - { - m_mutex.unlock(); - } - - void wait() - { - m_wait.wait(&m_mutex); - } - - void signal() - { - m_wait.wakeAll(); - } - - void setResult(const QVariant& result) - { - m_mutex.lock(); - m_retVal = result; - signal(); - m_mutex.unlock(); - } - - QVariant result() - { - return m_retVal; - } - -private: - QVariant m_retVal; - QMutex m_mutex; - QWaitCondition m_wait; + input_session_t *session; + ImfEventType type; + union { + struct { + int32_t n; + int32_t flags; + bool before; + spannable_string_t *result; + } gtac; // ic_get_text_before_cursor/ic_get_text_after_cursor + struct { + int32_t result; + } gcp; // ic_get_cursor_position + struct { + int32_t start; + int32_t end; + int32_t result; + } scr; // ic_set_composing_region + struct { + spannable_string_t* text; + int32_t new_cursor_position; + int32_t result; + } sct; // ic_set_composing_text + struct { + spannable_string_t* text; + int32_t new_cursor_position; + int32_t result; + } ct; // ic_commit_text + struct { + int32_t result; + } fct; // ic_finish_composing_text + struct { + int32_t left_length; + int32_t right_length; + int32_t result; + } dst; // ic_delete_surrounding_text + struct { + event_t *event; + int32_t result; + } sae; // ic_send_async_event/ic_send_event + struct { + int32_t *pIsSelected; + int32_t result; + } its; // ic_is_text_selected/ic_is_all_text_selected + }; }; -class ImfEvent : public QEvent +// Invoke an IMF initiated request synchronously on Qt's main thread. As describe below all +// IMF requests are made from another thread but need to be executed on the main thread. +static void executeIMFRequest(QQnxImfRequest *event) { - public: - ImfEvent(input_session_t *session, ImfEventType type, ImfEventResult *result) : - QEvent((QEvent::Type)sUserEventType), - m_session(session), - m_imfType(type), - m_result(result) - { - } - ~ImfEvent() { } - - input_session_t *m_session; - ImfEventType m_imfType; - QVariantHash m_args; - ImfEventResult *m_result; - - static int sUserEventType; -}; -int ImfEvent::sUserEventType = QEvent::registerEventType(); - -static int32_t imfBeginBatchEdit(input_session_t *ic) -{ - qInputContextIMFEventDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return 0; - - ImfEventResult result; - ImfEvent *event = new ImfEvent(ic, ImfBeginBatchEdit, &result); - QCoreApplication::postEvent(QCoreApplication::instance(), event); - - result.wait(); - int32_t ret = result.result().value(); - - return ret; + QMetaObject::invokeMethod(sInputContextInstance, + "processImfEvent", + Qt::BlockingQueuedConnection, + Q_ARG(QQnxImfRequest*, event)); } -static int32_t imfClearMetaKeyStates(input_session_t *ic, int32_t states) +// The following functions (ic_*) are callback functions called by the input system to query information +// about the text object that currently has focus or to make changes to it. All calls are made from the +// input system's own thread. The pattern for each callback function is to copy its parameters into +// a QQnxImfRequest structure and call executeIMFRequest to have it passed synchronously to Qt's main thread. +// Any return values should be pre-initialised with suitable default values as in some cases +// (e.g. a stale session) the call will return without having executed any request specific code. +// +// To make the correspondence more obvious, the names of these functions match those defined in the headers. +// They're in an anonymous namespace to avoid compiler conflicts with external functions defined with the +// same names. +namespace { - qInputContextIMFEventDebug() << Q_FUNC_INFO; - if (!isSessionOkay(ic)) - return 0; - - ImfEventResult result; - ImfEvent *event = new ImfEvent(ic, ImfClearMetaKeyStates, &result); - iarg(states); - - QCoreApplication::postEvent(QCoreApplication::instance(), event); - - result.wait(); - int32_t ret = result.result().value(); - - return ret; -} - -static int32_t imfCommitText(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position) +// See comment at beginning of namespace declaration for general information +static int32_t ic_begin_batch_edit(input_session_t *ic) { - qInputContextIMFEventDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return 0; - - ImfEventResult result; - ImfEvent *event = new ImfEvent(ic, ImfCommitText, &result); - parg(text); - iarg(new_cursor_position); - - QCoreApplication::postEvent(QCoreApplication::instance(), event); - - result.wait(); - int32_t ret = result.result().value(); - - return ret; -} - -static int32_t imfDeleteSurroundingText(input_session_t *ic, int32_t left_length, int32_t right_length) -{ - qInputContextIMFEventDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return 0; - - ImfEventResult result; - ImfEvent *event = new ImfEvent(ic, ImfDeleteSurroundingText, &result); - iarg(left_length); - iarg(right_length); - - QCoreApplication::postEvent(QCoreApplication::instance(), event); - - result.wait(); - int32_t ret = result.result().value(); - - return ret; -} - -static int32_t imfEndBatchEdit(input_session_t *ic) -{ - qInputContextIMFEventDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return 0; - - ImfEventResult result; - ImfEvent *event = new ImfEvent(ic, ImfEndBatchEdit, &result); - - QCoreApplication::postEvent(QCoreApplication::instance(), event); - - result.wait(); - int32_t ret = result.result().value(); - - return ret; -} - -static int32_t imfFinishComposingText(input_session_t *ic) -{ - qInputContextIMFEventDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return 0; - - ImfEventResult result; - ImfEvent *event = new ImfEvent(ic, ImfFinishComposingText, &result); - - QCoreApplication::postEvent(QCoreApplication::instance(), event); - - result.wait(); - int32_t ret = result.result().value(); - - return ret; -} - -static int32_t imfGetCursorCapsMode(input_session_t *ic, int32_t req_modes) -{ - qInputContextIMFEventDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return 0; - - ImfEventResult result; - ImfEvent *event = new ImfEvent(ic, ImfGetCursorCapsMode, &result); - iarg(req_modes); - - QCoreApplication::postEvent(QCoreApplication::instance(), event); - - int32_t ret = result.result().value(); - return ret; -} - -static int32_t imfGetCursorPosition(input_session_t *ic) -{ - qInputContextIMFEventDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return 0; - - ImfEventResult result; - ImfEvent *event = new ImfEvent(ic, ImfGetCursorPosition, &result); - - QCoreApplication::postEvent(QCoreApplication::instance(), event); - - result.wait(); - int32_t ret = result.result().value(); - - return ret; -} - -static extracted_text_t *imfGetExtractedText(input_session_t *ic, extracted_text_request_t *request, int32_t flags) -{ - qInputContextIMFEventDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) { - extracted_text_t *et = (extracted_text_t *)calloc(sizeof(extracted_text_t),1); - et->text = (spannable_string_t *)calloc(sizeof(spannable_string_t),1); - return et; - } - - ImfEventResult result; - ImfEvent *event = new ImfEvent(ic, ImfGetExtractedText, &result); - parg(request); - iarg(flags); - - QCoreApplication::postEvent(QCoreApplication::instance(), event); - - result.wait(); - return result.result().value(); -} - -static spannable_string_t *imfGetSelectedText(input_session_t *ic, int32_t flags) -{ - qInputContextIMFEventDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return toSpannableString(""); - - ImfEventResult result; - ImfEvent *event = new ImfEvent(ic, ImfGetSelectedText, &result); - iarg(flags); - - QCoreApplication::postEvent(QCoreApplication::instance(), event); - - result.wait(); - return result.result().value(); -} - -static spannable_string_t *imfGetTextAfterCursor(input_session_t *ic, int32_t n, int32_t flags) -{ - qInputContextIMFEventDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return toSpannableString(""); - - ImfEventResult result; - ImfEvent *event = new ImfEvent(ic, ImfGetTextAfterCursor, &result); - iarg(n); - iarg(flags); - - QCoreApplication::postEvent(QCoreApplication::instance(), event); - - result.wait(); - return result.result().value(); -} - -static spannable_string_t *imfGetTextBeforeCursor(input_session_t *ic, int32_t n, int32_t flags) -{ - qInputContextIMFEventDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return toSpannableString(""); - - ImfEventResult result; - ImfEvent *event = new ImfEvent(ic, ImfGetTextBeforeCursor, &result); - iarg(n); - iarg(flags); - - QCoreApplication::postEvent(QCoreApplication::instance(), event); - - result.wait(); - return result.result().value(); -} - -static int32_t imfPerformEditorAction(input_session_t *ic, int32_t editor_action) -{ - qInputContextIMFEventDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return 0; - - ImfEventResult result; - ImfEvent *event = new ImfEvent(ic, ImfPerformEditorAction, &result); - iarg(editor_action); - - QCoreApplication::postEvent(QCoreApplication::instance(), event); - - result.wait(); - int32_t ret = result.result().value(); - return ret; -} - -static int32_t imfReportFullscreenMode(input_session_t *ic, int32_t enabled) -{ - qInputContextIMFEventDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return 0; - - ImfEventResult result; - ImfEvent *event = new ImfEvent(ic, ImfReportFullscreenMode, &result); - iarg(enabled); - - QCoreApplication::postEvent(QCoreApplication::instance(), event); - - result.wait(); - int32_t ret = result.result().value(); - return ret; -} - -static int32_t imfSendEvent(input_session_t *ic, event_t *event) -{ - qInputContextIMFEventDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return 0; - - ImfEvent *imfEvent = new ImfEvent(ic, ImfSendEvent, 0); - imfEvent->m_args[qs("event")] = QVariant::fromValue(static_cast(event)); - - QCoreApplication::postEvent(QCoreApplication::instance(), imfEvent); + Q_UNUSED(ic); + // Ignore silently. return 0; } -static int32_t imfSendAsyncEvent(input_session_t *ic, event_t *event) +// End composition, committing the supplied text. +// See comment at beginning of namespace declaration for general information +static int32_t ic_commit_text(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position) { - qInputContextIMFEventDebug() << Q_FUNC_INFO; + qInputContextIMFRequestDebug() << Q_FUNC_INFO; - if (!isSessionOkay(ic)) - return 0; + QQnxImfRequest event(ic, ImfCommitText); + event.ct.text = text; + event.ct.new_cursor_position = new_cursor_position; + event.ct.result = -1; + executeIMFRequest(&event); - ImfEvent *imfEvent = new ImfEvent(ic, ImfSendAsyncEvent, 0); - imfEvent->m_args[qs("event")] = QVariant::fromValue(static_cast(event)); + return event.ct.result; +} - QCoreApplication::postEvent(QCoreApplication::instance(), imfEvent); +// Delete left_length characters before and right_length characters after the cursor. +// See comment at beginning of namespace declaration for general information +static int32_t ic_delete_surrounding_text(input_session_t *ic, int32_t left_length, int32_t right_length) +{ + qInputContextIMFRequestDebug() << Q_FUNC_INFO; + QQnxImfRequest event(ic, ImfDeleteSurroundingText); + event.dst.left_length = left_length; + event.dst.right_length = right_length; + event.dst.result = -1; + executeIMFRequest(&event); + + return event.dst.result; +} + +// See comment at beginning of namespace declaration for general information +static int32_t ic_end_batch_edit(input_session_t *ic) +{ + Q_UNUSED(ic); + + // Ignore silently. return 0; } -static int32_t imfSetComposingRegion(input_session_t *ic, int32_t start, int32_t end) +// End composition, committing what's there. +// See comment at beginning of namespace declaration for general information +static int32_t ic_finish_composing_text(input_session_t *ic) { - qInputContextIMFEventDebug() << Q_FUNC_INFO; + qInputContextIMFRequestDebug() << Q_FUNC_INFO; - if (!isSessionOkay(ic)) - return 0; + QQnxImfRequest event(ic, ImfFinishComposingText); + event.fct.result = -1; + executeIMFRequest(&event); - ImfEventResult result; - ImfEvent *event = new ImfEvent(ic, ImfSetComposingRegion, &result); - iarg(start); - iarg(end); - - QCoreApplication::postEvent(QCoreApplication::instance(), event); - - result.wait(); - int32_t ret = result.result().value(); - return ret; + return event.fct.result; } -static int32_t imfSetComposingText(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position) +// Return the position of the cursor. +// See comment at beginning of namespace declaration for general information +static int32_t ic_get_cursor_position(input_session_t *ic) { - qInputContextIMFEventDebug() << Q_FUNC_INFO; + qInputContextIMFRequestDebug() << Q_FUNC_INFO; - if (!isSessionOkay(ic)) - return 0; + QQnxImfRequest event(ic, ImfGetCursorPosition); + event.gcp.result = -1; + executeIMFRequest(&event); - ImfEventResult result; - ImfEvent *event = new ImfEvent(ic, ImfSetComposingText, &result); - parg(text); - iarg(new_cursor_position); - - QCoreApplication::postEvent(QCoreApplication::instance(), event); - - result.wait(); - int32_t ret = result.result().value(); - return ret; + return event.gcp.result; } -static int32_t imfSetSelection(input_session_t *ic, int32_t start, int32_t end) +// Return the n characters after the cursor. +// See comment at beginning of namespace declaration for general information +static spannable_string_t *ic_get_text_after_cursor(input_session_t *ic, int32_t n, int32_t flags) { - qInputContextIMFEventDebug() << Q_FUNC_INFO; + qInputContextIMFRequestDebug() << Q_FUNC_INFO; - if (!isSessionOkay(ic)) - return 0; + QQnxImfRequest event(ic, ImfGetTextAfterCursor); + event.gtac.n = n; + event.gtac.flags = flags; + event.gtac.result = 0; + executeIMFRequest(&event); - ImfEventResult result; - ImfEvent *event = new ImfEvent(ic, ImfSetSelection, &result); - iarg(start); - iarg(end); - - QCoreApplication::postEvent(QCoreApplication::instance(), event); - - result.wait(); - int32_t ret = result.result().value(); - return ret; + return event.gtac.result; } +// Return the n characters before the cursor. +// See comment at beginning of namespace declaration for general information +static spannable_string_t *ic_get_text_before_cursor(input_session_t *ic, int32_t n, int32_t flags) +{ + qInputContextIMFRequestDebug() << Q_FUNC_INFO; + + QQnxImfRequest event(ic, ImfGetTextBeforeCursor); + event.gtac.n = n; + event.gtac.flags = flags; + event.gtac.result = 0; + executeIMFRequest(&event); + + return event.gtac.result; +} + +// Process an event from IMF. Primarily used for reflecting back keyboard events. +// See comment at beginning of namespace declaration for general information +static int32_t ic_send_event(input_session_t *ic, event_t *event) +{ + qInputContextIMFRequestDebug() << Q_FUNC_INFO; + + QQnxImfRequest imfEvent(ic, ImfSendEvent); + imfEvent.sae.event = event; + imfEvent.sae.result = -1; + executeIMFRequest(&imfEvent); + + return imfEvent.sae.result; +} + +// Same as ic_send_event. +// See comment at beginning of namespace declaration for general information +static int32_t ic_send_async_event(input_session_t *ic, event_t *event) +{ + qInputContextIMFRequestDebug() << Q_FUNC_INFO; + + QQnxImfRequest imfEvent(ic, ImfSendAsyncEvent); + imfEvent.sae.event = event; + imfEvent.sae.result = -1; + executeIMFRequest(&imfEvent); + + return imfEvent.sae.result; +} + +// Set the range of text between start and end as the composition range. +// See comment at beginning of namespace declaration for general information +static int32_t ic_set_composing_region(input_session_t *ic, int32_t start, int32_t end) +{ + qInputContextIMFRequestDebug() << Q_FUNC_INFO; + + QQnxImfRequest event(ic, ImfSetComposingRegion); + event.scr.start = start; + event.scr.end = end; + event.scr.result = -1; + executeIMFRequest(&event); + + return event.scr.result; +} + +// Update the composition range with the supplied text. This can be called when no composition +// range is in effect in which case one is started at the current cursor position. +// See comment at beginning of namespace declaration for general information +static int32_t ic_set_composing_text(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position) +{ + qInputContextIMFRequestDebug() << Q_FUNC_INFO; + + QQnxImfRequest event(ic, ImfSetComposingText); + event.sct.text = text; + event.sct.new_cursor_position = new_cursor_position; + event.sct.result = -1; + executeIMFRequest(&event); + + return event.sct.result; +} + +// Indicate if any text is selected +// See comment at beginning of namespace declaration for general information +static int32_t ic_is_text_selected(input_session_t* ic, int32_t* pIsSelected) +{ + qInputContextIMFRequestDebug() << Q_FUNC_INFO; + + QQnxImfRequest event(ic, ImfIsTextSelected); + event.its.pIsSelected = pIsSelected; + event.its.result = -1; + executeIMFRequest(&event); + + return event.its.result; +} + +// Indicate if all text is selected +// See comment at beginning of namespace declaration for general information +static int32_t ic_is_all_text_selected(input_session_t* ic, int32_t* pIsSelected) +{ + qInputContextIMFRequestDebug() << Q_FUNC_INFO; + + QQnxImfRequest event(ic, ImfIsAllTextSelected); + event.its.pIsSelected = pIsSelected; + event.its.result = -1; + executeIMFRequest(&event); + + return event.its.result; +} + +// The following functions are defined in the IMF headers but are not currently called. + +// Not currently used +static int32_t ic_perform_editor_action(input_session_t *ic, int32_t editor_action) +{ + Q_UNUSED(ic); + Q_UNUSED(editor_action); + + qCritical() << "ic_perform_editor_action not implemented"; + return 0; +} + +// Not currently used +static int32_t ic_report_fullscreen_mode(input_session_t *ic, int32_t enabled) +{ + Q_UNUSED(ic); + Q_UNUSED(enabled); + + qCritical() << "ic_report_fullscreen_mode not implemented"; + return 0; +} + +// Not currently used +static extracted_text_t *ic_get_extracted_text(input_session_t *ic, extracted_text_request_t *request, int32_t flags) +{ + Q_UNUSED(ic); + Q_UNUSED(request); + Q_UNUSED(flags); + + qCritical() << "ic_get_extracted_text not implemented"; + return 0; +} + +// Not currently used +static spannable_string_t *ic_get_selected_text(input_session_t *ic, int32_t flags) +{ + Q_UNUSED(ic); + Q_UNUSED(flags); + + qCritical() << "ic_get_selected_text not implemented"; + return 0; +} + +// Not currently used +static int32_t ic_get_cursor_caps_mode(input_session_t *ic, int32_t req_modes) +{ + Q_UNUSED(ic); + Q_UNUSED(req_modes); + + qCritical() << "ic_get_cursor_caps_mode not implemented"; + return 0; +} + +// Not currently used +static int32_t ic_clear_meta_key_states(input_session_t *ic, int32_t states) +{ + Q_UNUSED(ic); + Q_UNUSED(states); + + qCritical() << "ic_clear_meta_key_states not implemented"; + return 0; +} + +// Not currently used +static int32_t ic_set_selection(input_session_t *ic, int32_t start, int32_t end) +{ + Q_UNUSED(ic); + Q_UNUSED(start); + Q_UNUSED(end); + + qCritical() << "ic_set_selection not implemented"; + return 0; +} + + + static connection_interface_t ic_funcs = { - imfBeginBatchEdit, - imfClearMetaKeyStates, - imfCommitText, - imfDeleteSurroundingText, - imfEndBatchEdit, - imfFinishComposingText, - imfGetCursorCapsMode, - imfGetCursorPosition, - imfGetExtractedText, - imfGetSelectedText, - imfGetTextAfterCursor, - imfGetTextBeforeCursor, - imfPerformEditorAction, - imfReportFullscreenMode, - NULL, //ic_send_key_event - imfSendEvent, - imfSendAsyncEvent, - imfSetComposingRegion, - imfSetComposingText, - imfSetSelection, - NULL, //ic_set_candidates, + ic_begin_batch_edit, + ic_clear_meta_key_states, + ic_commit_text, + ic_delete_surrounding_text, + ic_end_batch_edit, + ic_finish_composing_text, + ic_get_cursor_caps_mode, + ic_get_cursor_position, + ic_get_extracted_text, + ic_get_selected_text, + ic_get_text_after_cursor, + ic_get_text_before_cursor, + ic_perform_editor_action, + ic_report_fullscreen_mode, + 0, //ic_send_key_event + ic_send_event, + ic_send_async_event, + ic_set_composing_region, + ic_set_composing_text, + ic_set_selection, + 0, //ic_set_candidates, + 0, //ic_get_cursor_offset, + 0, //ic_get_selection, + ic_is_text_selected, + ic_is_all_text_selected, + 0, //ic_get_max_cursor_offset_t }; +} // namespace + static void -initEvent(event_t *pEvent, const input_session_t *pSession, EventType eventType, int eventId) +initEvent(event_t *pEvent, const input_session_t *pSession, EventType eventType, int eventId, int eventSize) { static int s_transactionId; // Make sure structure is squeaky clean since it's not clear just what is significant. - memset(pEvent, 0, sizeof(event_t)); + memset(pEvent, 0, eventSize); pEvent->event_type = eventType; pEvent->event_id = eventId; pEvent->pid = getpid(); @@ -566,7 +493,7 @@ initEvent(event_t *pEvent, const input_session_t *pSession, EventType eventType, pEvent->transaction_id = ++s_transactionId; } -spannable_string_t *toSpannableString(const QString &text) +static spannable_string_t *toSpannableString(const QString &text) { qInputContextDebug() << Q_FUNC_INFO << text; @@ -579,8 +506,7 @@ spannable_string_t *toSpannableString(const QString &text) const QChar *pData = text.constData(); wchar_t *pDst = pString->str; - while (!pData->isNull()) - { + while (!pData->isNull()) { *pDst = pData->unicode(); pDst++; pData++; @@ -590,7 +516,6 @@ spannable_string_t *toSpannableString(const QString &text) return pString; } -} // namespace static const input_session_t *(*p_ictrl_open_session)(connection_interface_t *) = 0; static void (*p_ictrl_close_session)(input_session_t *) = 0; @@ -645,27 +570,29 @@ QT_BEGIN_NAMESPACE QQnxInputContext::QQnxInputContext(QQnxIntegration *integration, QQnxAbstractVirtualKeyboard &keyboard) : QPlatformInputContext(), - m_lastCaretPos(0), + m_caretPosition(0), m_isComposing(false), + m_isUpdatingText(false), m_inputPanelVisible(false), m_inputPanelLocale(QLocale::c()), m_integration(integration), - m_virtualKeyboad(keyboard) + m_virtualKeyboard(keyboard) { qInputContextDebug() << Q_FUNC_INFO; if (!imfAvailable()) return; - if ( p_imf_client_init() != 0 ) { + // Save a pointer to ourselves so we can execute calls from IMF through executeIMFRequest + // In practice there will only ever be a single instance. + Q_ASSERT(sInputContextInstance == 0); + sInputContextInstance = this; + + if (p_imf_client_init() != 0) { s_imfInitFailed = true; qCritical("imf_client_init failed - IMF services will be unavailable"); } - QCoreApplication::instance()->installEventFilter(this); - - // p_vkb_init_selection_service(); - connect(&keyboard, SIGNAL(visibilityChanged(bool)), this, SLOT(keyboardVisibilityChanged(bool))); connect(&keyboard, SIGNAL(localeChanged(QLocale)), this, SLOT(keyboardLocaleChanged(QLocale))); keyboardVisibilityChanged(keyboard.isVisible()); @@ -676,168 +603,74 @@ QQnxInputContext::~QQnxInputContext() { qInputContextDebug() << Q_FUNC_INFO; + Q_ASSERT(sInputContextInstance == this); + sInputContextInstance = 0; + if (!imfAvailable()) return; - QCoreApplication::instance()->removeEventFilter(this); p_imf_client_disconnect(); } -#define getarg(type, name) type name = imfEvent->mArgs[qs(#name)].value() -#define getparg(type, name) type name = (type)(imfEvent->mArgs[qs(#name)].value()) - bool QQnxInputContext::isValid() const { return imfAvailable(); } -bool QQnxInputContext::eventFilter(QObject *obj, QEvent *event) +void QQnxInputContext::processImfEvent(QQnxImfRequest *imfEvent) { - if (event->type() == ImfEvent::sUserEventType) { - // Forward the event to our real handler. - ImfEvent *imfEvent = static_cast(event); - switch (imfEvent->m_imfType) { - case ImfBeginBatchEdit: { - int32_t ret = onBeginBatchEdit(imfEvent->m_session); - imfEvent->m_result->setResult(QVariant::fromValue(ret)); - break; - } + // If input session is no longer current, just bail, imfEvent should already be set with the appropriate + // return value. + if (!isSessionOkay(imfEvent->session)) + return; - case ImfClearMetaKeyStates: { - getarg(int32_t, states); - int32_t ret = onClearMetaKeyStates(imfEvent->m_session, states); - imfEvent->m_result->setResult(QVariant::fromValue(ret)); - break; - } + switch (imfEvent->type) { + case ImfCommitText: + imfEvent->ct.result = onCommitText(imfEvent->ct.text, imfEvent->ct.new_cursor_position); + break; - case ImfCommitText: { - getparg(spannable_string_t*, text); - getarg(int32_t, new_cursor_position); - int32_t ret = onCommitText(imfEvent->m_session, text, new_cursor_position); - imfEvent->m_result->setResult(QVariant::fromValue(ret)); - break; - } + case ImfDeleteSurroundingText: + imfEvent->dst.result = onDeleteSurroundingText(imfEvent->dst.left_length, imfEvent->dst.right_length); + break; - case ImfDeleteSurroundingText: { - getarg(int32_t, left_length); - getarg(int32_t, right_length); - int32_t ret = onDeleteSurroundingText(imfEvent->m_session, left_length, right_length); - imfEvent->m_result->setResult(QVariant::fromValue(ret)); - break; - } + case ImfFinishComposingText: + imfEvent->fct.result = onFinishComposingText(); + break; - case ImfEndBatchEdit: { - int32_t ret = onEndBatchEdit(imfEvent->m_session); - imfEvent->m_result->setResult(QVariant::fromValue(ret)); - break; - } + case ImfGetCursorPosition: + imfEvent->gcp.result = onGetCursorPosition(); + break; - case ImfFinishComposingText: { - int32_t ret = onFinishComposingText(imfEvent->m_session); - imfEvent->m_result->setResult(QVariant::fromValue(ret)); - break; - } + case ImfGetTextAfterCursor: + imfEvent->gtac.result = onGetTextAfterCursor(imfEvent->gtac.n, imfEvent->gtac.flags); + break; - case ImfGetCursorCapsMode: { - getarg(int32_t, req_modes); - int32_t ret = onGetCursorCapsMode(imfEvent->m_session, req_modes); - imfEvent->m_result->setResult(QVariant::fromValue(ret)); - break; - } + case ImfGetTextBeforeCursor: + imfEvent->gtac.result = onGetTextBeforeCursor(imfEvent->gtac.n, imfEvent->gtac.flags); + break; - case ImfGetCursorPosition: { - int32_t ret = onGetCursorPosition(imfEvent->m_session); - imfEvent->m_result->setResult(QVariant::fromValue(ret)); - break; - } + // Don't need to distinguish these two cases + case ImfSendEvent: + case ImfSendAsyncEvent: + imfEvent->sae.result = onSendEvent(imfEvent->sae.event); + break; - case ImfGetExtractedText: { - getparg(extracted_text_request_t*, request); - getarg(int32_t, flags); - extracted_text_t *ret = onGetExtractedText(imfEvent->m_session, request, flags); - imfEvent->m_result->setResult(QVariant::fromValue(static_cast(ret))); - break; - } + case ImfSetComposingRegion: + imfEvent->scr.result = onSetComposingRegion(imfEvent->scr.start, imfEvent->scr.end); + break; - case ImfGetSelectedText: { - getarg(int32_t, flags); - spannable_string_t *ret = onGetSelectedText(imfEvent->m_session, flags); - imfEvent->m_result->setResult(QVariant::fromValue(static_cast(ret))); - break; - } + case ImfSetComposingText: + imfEvent->sct.result = onSetComposingText(imfEvent->sct.text, imfEvent->sct.new_cursor_position); + break; - case ImfGetTextAfterCursor: { - getarg(int32_t, n); - getarg(int32_t, flags); - spannable_string_t *ret = onGetTextAfterCursor(imfEvent->m_session, n, flags); - imfEvent->m_result->setResult(QVariant::fromValue(static_cast(ret))); - break; - } + case ImfIsTextSelected: + imfEvent->its.result = onIsTextSelected(imfEvent->its.pIsSelected); + break; - case ImfGetTextBeforeCursor: { - getarg(int32_t, n); - getarg(int32_t, flags); - spannable_string_t *ret = onGetTextBeforeCursor(imfEvent->m_session, n, flags); - imfEvent->m_result->setResult(QVariant::fromValue((void*)ret)); - break; - } - - case ImfPerformEditorAction: { - getarg(int32_t, editor_action); - int32_t ret = onPerformEditorAction(imfEvent->m_session, editor_action); - imfEvent->m_result->setResult(QVariant::fromValue(ret)); - break; - } - - case ImfReportFullscreenMode: { - getarg(int32_t, enabled); - int32_t ret = onReportFullscreenMode(imfEvent->m_session, enabled); - imfEvent->m_result->setResult(QVariant::fromValue(ret)); - break; - } - - case ImfSendEvent: { - getparg(event_t*, event); - onSendEvent(imfEvent->m_session, event); - break; - } - - case ImfSendAsyncEvent: { - getparg(event_t*, event); - onSendAsyncEvent(imfEvent->m_session, event); - break; - } - - case ImfSetComposingRegion: { - getarg(int32_t, start); - getarg(int32_t, end); - int32_t ret = onSetComposingRegion(imfEvent->m_session, start, end); - imfEvent->m_result->setResult(QVariant::fromValue(ret)); - break; - } - - case ImfSetComposingText: { - getparg(spannable_string_t*, text); - getarg(int32_t, new_cursor_position); - int32_t ret = onSetComposingText(imfEvent->m_session, text, new_cursor_position); - imfEvent->m_result->setResult(QVariant::fromValue(ret)); - break; - } - - case ImfSetSelection: { - getarg(int32_t, start); - getarg(int32_t, end); - int32_t ret = onSetSelection(imfEvent->m_session, start, end); - imfEvent->m_result->setResult(QVariant::fromValue(ret)); - break; - } - }; //switch - - return true; - } else { - // standard event processing - return QObject::eventFilter(obj, event); - } + case ImfIsAllTextSelected: + imfEvent->its.result = onIsAllTextSelected(imfEvent->its.pIsSelected); + break; + }; //switch } bool QQnxInputContext::filterEvent( const QEvent *event ) @@ -845,12 +678,12 @@ bool QQnxInputContext::filterEvent( const QEvent *event ) qInputContextDebug() << Q_FUNC_INFO << event; switch (event->type()) { - case QEvent::CloseSoftwareInputPanel: { + case QEvent::CloseSoftwareInputPanel: return dispatchCloseSoftwareInputPanel(); - } - case QEvent::RequestSoftwareInputPanel: { + + case QEvent::RequestSoftwareInputPanel: return dispatchRequestSoftwareInputPanel(); - } + default: return false; } @@ -869,12 +702,30 @@ void QQnxInputContext::reset() endComposition(); } -void QQnxInputContext::update(Qt::InputMethodQueries queries) +void QQnxInputContext::commit() { qInputContextDebug() << Q_FUNC_INFO; - reset(); + endComposition(); +} - QPlatformInputContext::update(queries); +void QQnxInputContext::update(Qt::InputMethodQueries queries) +{ + qInputContextDebug() << Q_FUNC_INFO << queries; + + if (queries & Qt::ImCursorPosition) { + int lastCaret = m_caretPosition; + updateCursorPosition(); + // If caret position has changed we need to inform IMF unless this is just due to our own action + // such as committing text. + if (!m_isUpdatingText && lastCaret != m_caretPosition) { + caret_event_t caretEvent; + initEvent(&caretEvent.event, sInputSession, EVENT_CARET, CARET_POS_CHANGED, sizeof(caretEvent)); + caretEvent.old_pos = lastCaret; + caretEvent.new_pos = m_caretPosition; + qInputContextDebug() << Q_FUNC_INFO << "ictrl_dispatch_event caret changed" << lastCaret << m_caretPosition; + p_ictrl_dispatch_event(&caretEvent.event); + } + } } void QQnxInputContext::closeSession() @@ -889,14 +740,17 @@ void QQnxInputContext::closeSession() } } -void QQnxInputContext::openSession() +bool QQnxInputContext::openSession() { - qInputContextDebug() << Q_FUNC_INFO; if (!imfAvailable()) - return; + return false; closeSession(); sInputSession = p_ictrl_open_session(&ic_funcs); + + qInputContextDebug() << Q_FUNC_INFO; + + return sInputSession != 0; } bool QQnxInputContext::hasSession() @@ -918,79 +772,89 @@ bool QQnxInputContext::hasSelectedText() bool QQnxInputContext::dispatchRequestSoftwareInputPanel() { + qInputContextDebug() << Q_FUNC_INFO << "requesting keyboard" << m_inputPanelVisible; m_virtualKeyboard.showKeyboard(); - qInputContextDebug() << Q_FUNC_INFO << "requesting virtual keyboard"; - QObject *input = qGuiApp->focusObject(); - if (!imfAvailable() || !input || !inputMethodAccepted()) - return true; - if (!hasSession()) - openSession(); - - // This also means that the caret position has moved - QInputMethodQueryEvent query(Qt::ImCursorPosition); - QCoreApplication::sendEvent(input, &query); - int caretPos = query.value(Qt::ImCursorPosition).toInt(); - caret_event_t caretEvent; - memset(&caretEvent, 0, sizeof(caret_event_t)); - initEvent(&caretEvent.event, sInputSession, EVENT_CARET, CARET_POS_CHANGED); - caretEvent.old_pos = m_lastCaretPos; - m_lastCaretPos = caretEvent.new_pos = caretPos; - p_ictrl_dispatch_event((event_t *)&caretEvent); return true; } bool QQnxInputContext::dispatchCloseSoftwareInputPanel() { + qInputContextDebug() << Q_FUNC_INFO << "hiding keyboard" << m_inputPanelVisible; m_virtualKeyboard.hideKeyboard(); - qInputContextDebug() << Q_FUNC_INFO << "hiding virtual keyboard"; - // This also means we are stopping composition, but we should already have done that. return true; } /** * IMF Event Dispatchers. */ -bool QQnxInputContext::dispatchFocusEvent(FocusEventId id, int hints) +bool QQnxInputContext::dispatchFocusGainEvent(int inputHints) { - qInputContextDebug() << Q_FUNC_INFO; + if (sInputSession != 0) + dispatchFocusLossEvent(); - if (!sInputSession) { - qWarning() << Q_FUNC_INFO << "Attempt to dispatch a focus event with no input session."; - return false; - } + QObject *input = qGuiApp->focusObject(); - if (!imfAvailable()) + if (!input || !openSession()) return false; // Set the last caret position to 0 since we don't really have one and we don't // want to have the old one. - m_lastCaretPos = 0; + m_caretPosition = 0; + + QInputMethodQueryEvent query(Qt::ImHints); + QCoreApplication::sendEvent(input, &query); focus_event_t focusEvent; - memset(&focusEvent, 0, sizeof(focusEvent)); - initEvent(&focusEvent.event, sInputSession, EVENT_FOCUS, id); + initEvent(&focusEvent.event, sInputSession, EVENT_FOCUS, FOCUS_GAINED, sizeof(focusEvent)); focusEvent.style = DEFAULT_STYLE; - if (hints && Qt::ImhNoPredictiveText) + if (inputHints & Qt::ImhNoPredictiveText) focusEvent.style |= NO_PREDICTION | NO_AUTO_CORRECTION; - if (hints && Qt::ImhNoAutoUppercase) + if (inputHints & Qt::ImhNoAutoUppercase) focusEvent.style |= NO_AUTO_TEXT; + // Following styles are mutually exclusive + if (inputHints & Qt::ImhHiddenText) { + focusEvent.style |= IMF_PASSWORD_TYPE; + } else if (inputHints & Qt::ImhDialableCharactersOnly) { + focusEvent.style |= IMF_PHONE_TYPE; + } else if (inputHints & Qt::ImhUrlCharactersOnly) { + focusEvent.style |= IMF_URL_TYPE; + } else if (inputHints & Qt::ImhEmailCharactersOnly) { + focusEvent.style |= IMF_EMAIL_TYPE; + } + + qInputContextDebug() << Q_FUNC_INFO << "ictrl_dispatch_event focus gain style:" << focusEvent.style; + p_ictrl_dispatch_event((event_t *)&focusEvent); return true; } -bool QQnxInputContext::handleKeyboardEvent(int flags, int sym, int mod, int scan, int cap) +void QQnxInputContext::dispatchFocusLossEvent() { + if (sInputSession != 0) { + qInputContextDebug() << Q_FUNC_INFO << "ictrl_dispatch_event focus lost"; + + focus_event_t focusEvent; + initEvent(&focusEvent.event, sInputSession, EVENT_FOCUS, FOCUS_LOST, sizeof(focusEvent)); + p_ictrl_dispatch_event((event_t *)&focusEvent); + sInputSession = 0; + } +} + +bool QQnxInputContext::handleKeyboardEvent(int flags, int sym, int mod, int scan, int cap, int sequenceId) +{ + Q_UNUSED(scan); + if (!imfAvailable()) return false; int key = (flags & KEY_SYM_VALID) ? sym : cap; - bool navKey = false; - switch ( key ) { + bool navigationKey = false; + switch (key) { case KEYCODE_RETURN: /* In a single line edit we should end composition because enter might be used by something. endComposition(); @@ -1007,27 +871,22 @@ bool QQnxInputContext::handleKeyboardEvent(int flags, int sym, int mod, int scan break; case KEYCODE_LEFT: key = NAVIGATE_LEFT; - navKey = true; + navigationKey = true; break; case KEYCODE_RIGHT: key = NAVIGATE_RIGHT; - navKey = true; + navigationKey = true; break; case KEYCODE_UP: key = NAVIGATE_UP; - navKey = true; + navigationKey = true; break; case KEYCODE_DOWN: key = NAVIGATE_DOWN; - navKey = true; + navigationKey = true; break; - case KEYCODE_CAPS_LOCK: - case KEYCODE_LEFT_SHIFT: - case KEYCODE_RIGHT_SHIFT: case KEYCODE_LEFT_CTRL: case KEYCODE_RIGHT_CTRL: - case KEYCODE_LEFT_ALT: - case KEYCODE_RIGHT_ALT: case KEYCODE_MENU: case KEYCODE_LEFT_HYPER: case KEYCODE_RIGHT_HYPER: @@ -1041,85 +900,133 @@ bool QQnxInputContext::handleKeyboardEvent(int flags, int sym, int mod, int scan break; } - if ( mod & KEYMOD_CTRL ) { - // If CTRL is pressed, just let AIR handle it. But terminate any composition first - //endComposition(); - return false; - } - // Pass the keys we don't know about on through if ( key == 0 ) return false; - // IMF doesn't need key releases so just swallow them. - if (!(flags & KEY_DOWN)) - return true; - - if ( navKey ) { + if (navigationKey) { // Even if we're forwarding up events, we can't do this for // navigation keys. if ( flags & KEY_DOWN ) { navigation_event_t navEvent; - initEvent(&navEvent.event, sInputSession, EVENT_NAVIGATION, key); + initEvent(&navEvent.event, sInputSession, EVENT_NAVIGATION, key, sizeof(navEvent)); navEvent.magnitude = 1; - qInputContextDebug() << Q_FUNC_INFO << "dispatch navigation event " << key; + qInputContextDebug() << Q_FUNC_INFO << "ictrl_dispatch_even navigation" << key; p_ictrl_dispatch_event(&navEvent.event); } - } - else { + } else { key_event_t keyEvent; - initEvent(&keyEvent.event, sInputSession, EVENT_KEY, flags & KEY_DOWN ? IMF_KEY_DOWN : IMF_KEY_UP); - keyEvent.key_code = key; - keyEvent.character = 0; - keyEvent.meta_key_state = 0; + initEvent(&keyEvent.event, sInputSession, EVENT_KEY, flags & KEY_DOWN ? IMF_KEY_DOWN : IMF_KEY_UP, + sizeof(keyEvent)); + keyEvent.key_code = cap; + keyEvent.character = sym; + keyEvent.meta_key_state = mod; + keyEvent.sequence_id = sequenceId; p_ictrl_dispatch_event(&keyEvent.event); - qInputContextDebug() << Q_FUNC_INFO << "dispatch key event " << key; + qInputContextDebug() << Q_FUNC_INFO << "ictrl_dispatch_even key" << key; } - scan = 0; return true; } +void QQnxInputContext::updateCursorPosition() +{ + QObject *input = qGuiApp->focusObject(); + if (!input) + return; + + QInputMethodQueryEvent query(Qt::ImCursorPosition); + QCoreApplication::sendEvent(input, &query); + m_caretPosition = query.value(Qt::ImCursorPosition).toInt(); + + qInputContextDebug() << Q_FUNC_INFO << m_caretPosition; +} + void QQnxInputContext::endComposition() { if (!m_isComposing) return; - QObject *input = qGuiApp->focusObject(); - if (!imfAvailable() || !input) - return; - - QList attributes; - QInputMethodEvent event(QLatin1String(""), attributes); - event.setCommitString(m_composingText); - m_composingText = QString(); - m_isComposing = false; - QCoreApplication::sendEvent(input, &event); + finishComposingText(); action_event_t actionEvent; - memset(&actionEvent, 0, sizeof(actionEvent)); - initEvent(&actionEvent.event, sInputSession, EVENT_ACTION, ACTION_END_COMPOSITION); + initEvent(&actionEvent.event, sInputSession, EVENT_ACTION, ACTION_END_COMPOSITION, sizeof(actionEvent)); + qInputContextDebug() << Q_FUNC_INFO << "ictrl_dispatch_even end composition"; p_ictrl_dispatch_event(&actionEvent.event); } -void QQnxInputContext::setComposingText(QString const& composingText) +void QQnxInputContext::updateComposition(spannable_string_t *text, int32_t new_cursor_position) { - m_composingText = composingText; + QObject *input = qGuiApp->focusObject(); + if (!input) + return; + + if (new_cursor_position > 0) + new_cursor_position += text->length - 1; + + m_composingText = QString::fromWCharArray(text->str, text->length); m_isComposing = true; - QObject *input = qGuiApp->focusObject(); - if (!imfAvailable() || !input) - return; + qInputContextDebug() << Q_FUNC_INFO << m_composingText << new_cursor_position; QList attributes; - QTextCharFormat format; - format.setFontUnderline(true); - attributes.push_back(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, composingText.length(), format)); + attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, + new_cursor_position, + 1, + QVariant())); - QInputMethodEvent event(composingText, attributes); + for (unsigned int i = 0; i < text->spans_count; ++i) { + const uint64_t knownMask = ACTIVE_REGION_ATTRIB | COMPOSED_TEXT_ATTRIB | + AUTO_CORRECTION_ATTRIB | REVERT_CORRECTION_ATTRIB; + bool selected = (text->spans[i].attributes_mask & ACTIVE_REGION_ATTRIB) != 0; + bool converted = (text->spans[i].attributes_mask & COMPOSED_TEXT_ATTRIB) != 0; + bool autoCorrected = (text->spans[i].attributes_mask & AUTO_CORRECTION_ATTRIB) != 0; + bool reverted = (text->spans[i].attributes_mask & REVERT_CORRECTION_ATTRIB) != 0; + if (text->spans[i].attributes_mask & knownMask) { + QTextCharFormat format; + + if (converted || selected) { + format.setFontUnderline(true); + } + if (selected) { + format.setBackground(QBrush(sSelectedColor)); + } else if (autoCorrected) { + format.setBackground(QBrush(sAutoCorrectedColor)); + } else if (reverted) { + format.setBackground(QBrush(sRevertedColor)); + } + qInputContextDebug() << "attrib:" << selected << converted << text->spans[i].start << text->spans[i].end; + attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, text->spans[i].start, + text->spans[i].end - text->spans[i].start + 1, QVariant(format))); + } + } + QInputMethodEvent event(m_composingText, attributes); + m_isUpdatingText = true; QCoreApplication::sendEvent(input, &event); + m_isUpdatingText = false; + + updateCursorPosition(); +} + +void QQnxInputContext::finishComposingText() +{ + QObject *input = qGuiApp->focusObject(); + + if (input) { + qInputContextDebug() << Q_FUNC_INFO << m_composingText; + + QInputMethodEvent event; + event.setCommitString(m_composingText); + m_isUpdatingText = true; + QCoreApplication::sendEvent(input, &event); + m_isUpdatingText = false; + } + m_composingText = QString(); + m_isComposing = false; + + updateCursorPosition(); } int32_t QQnxInputContext::processEvent(event_t *event) @@ -1140,19 +1047,24 @@ int32_t QQnxInputContext::processEvent(event_t *event) event->event_id == NAVIGATE_LEFT ? KEYCODE_LEFT : event->event_id == NAVIGATE_RIGHT ? KEYCODE_RIGHT : 0; - QQnxEventThread::injectKeyboardEvent(KEY_DOWN | KEY_CAP_VALID, key, 0, 0, 0); - QQnxEventThread::injectKeyboardEvent(KEY_CAP_VALID, key, 0, 0, 0); + QQnxScreenEventHandler::injectKeyboardEvent(KEY_DOWN | KEY_CAP_VALID, key, 0, 0, 0); + QQnxScreenEventHandler::injectKeyboardEvent(KEY_CAP_VALID, key, 0, 0, 0); result = 0; break; } case EVENT_KEY: { - qInputContextDebug() << Q_FUNC_INFO << "EVENT_KEY"; - key_event_t *kevent = static_cast(event); - - QQnxEventThread::injectKeyboardEvent(KEY_DOWN | KEY_SYM_VALID | KEY_CAP_VALID, kevent->key_code, 0, 0, kevent->key_code); - QQnxEventThread::injectKeyboardEvent(KEY_SYM_VALID | KEY_CAP_VALID, kevent->key_code, 0, 0, kevent->key_code); - + key_event_t *kevent = reinterpret_cast(event); + int keySym = kevent->character != 0 ? kevent->character : kevent->key_code; + int keyCap = kevent->key_code; + int modifiers = 0; + if (kevent->meta_key_state & META_SHIFT_ON) + modifiers |= KEYMOD_SHIFT; + int flags = KEY_SYM_VALID | KEY_CAP_VALID; + if (event->event_id == IMF_KEY_DOWN) + flags |= KEY_DOWN; + qInputContextDebug() << Q_FUNC_INFO << "EVENT_KEY" << flags << keySym; + QQnxScreenEventHandler::injectKeyboardEvent(flags, keySym, modifiers, 0, keyCap); result = 0; break; } @@ -1179,339 +1091,182 @@ int32_t QQnxInputContext::processEvent(event_t *event) * IMF Event Handlers */ -int32_t QQnxInputContext::onBeginBatchEdit(input_session_t *ic) +int32_t QQnxInputContext::onCommitText(spannable_string_t *text, int32_t new_cursor_position) { - qInputContextDebug() << Q_FUNC_INFO; + Q_UNUSED(new_cursor_position); - if (!isSessionOkay(ic)) - return 0; - - // We don't care. - return 0; -} - -int32_t QQnxInputContext::onClearMetaKeyStates(input_session_t *ic, int32_t states) -{ - Q_UNUSED(states); - qInputContextDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return 0; - - // Should never get called. - qCritical() << Q_FUNC_INFO << "onClearMetaKeyStates is unsupported."; - return 0; -} - -int32_t QQnxInputContext::onCommitText(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position) -{ - Q_UNUSED(new_cursor_position); // TODO: How can we set the cursor position it's not part of the API. - if (!isSessionOkay(ic)) - return 0; - - QObject *input = qGuiApp->focusObject(); - if (!imfAvailable() || !input) - return 0; - - QString commitString = QString::fromWCharArray(text->str, text->length); - - qInputContextDebug() << Q_FUNC_INFO << "Committing [" << commitString << "]"; - - QList attributes; - QInputMethodEvent event(QLatin1String(""), attributes); - event.setCommitString(commitString, 0, 0); - - QCoreApplication::sendEvent(input, &event); - m_composingText = QString(); + m_composingText = QString::fromWCharArray(text->str, text->length); + finishComposingText(); return 0; } -int32_t QQnxInputContext::onDeleteSurroundingText(input_session_t *ic, int32_t left_length, int32_t right_length) +int32_t QQnxInputContext::onDeleteSurroundingText(int32_t left_length, int32_t right_length) { qInputContextDebug() << Q_FUNC_INFO << "L:" << left_length << " R:" << right_length; - if (!isSessionOkay(ic)) - return 0; - QObject *input = qGuiApp->focusObject(); - if (!imfAvailable() || !input) + if (!input) return 0; - if (hasSelectedText()) { - QQnxEventThread::injectKeyboardEvent(KEY_DOWN | KEY_CAP_VALID, KEYCODE_DELETE, 0, 0, 0); - QQnxEventThread::injectKeyboardEvent(KEY_CAP_VALID, KEYCODE_DELETE, 0, 0, 0); - reset(); - return 0; - } - int replacementLength = left_length + right_length; int replacementStart = -left_length; - QList attributes; - QInputMethodEvent event(QLatin1String(""), attributes); - event.setCommitString(QLatin1String(""), replacementStart, replacementLength); + finishComposingText(); + + QInputMethodEvent event; + event.setCommitString(QString(), replacementStart, replacementLength); + m_isUpdatingText = true; QCoreApplication::sendEvent(input, &event); + m_isUpdatingText = false; + + updateCursorPosition(); return 0; } -int32_t QQnxInputContext::onEndBatchEdit(input_session_t *ic) +int32_t QQnxInputContext::onFinishComposingText() { - qInputContextDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return 0; + finishComposingText(); return 0; } -int32_t QQnxInputContext::onFinishComposingText(input_session_t *ic) +int32_t QQnxInputContext::onGetCursorPosition() { qInputContextDebug() << Q_FUNC_INFO; - if (!isSessionOkay(ic)) - return 0; - QObject *input = qGuiApp->focusObject(); - if (!imfAvailable() || !input) + if (!input) return 0; - // Only update the control, no need to send a message back to imf (don't call - // end composition) - QList attributes; - QInputMethodEvent event(QLatin1String(""), attributes); - event.setCommitString(m_composingText); - m_composingText = QString(); - m_isComposing = false; - QCoreApplication::sendEvent(input, &event); + updateCursorPosition(); - return 0; + return m_caretPosition; } -int32_t QQnxInputContext::onGetCursorCapsMode(input_session_t *ic, int32_t req_modes) -{ - Q_UNUSED(req_modes); - qInputContextDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return 0; - - // Should never get called. - qCritical() << Q_FUNC_INFO << "onGetCursorCapsMode is unsupported."; - - return 0; -} - -int32_t QQnxInputContext::onGetCursorPosition(input_session_t *ic) -{ - qInputContextDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return 0; - - QObject *input = qGuiApp->focusObject(); - if (!imfAvailable() || !input) - return 0; - - QInputMethodQueryEvent query(Qt::ImCursorPosition); - QCoreApplication::sendEvent(input, &query); - m_lastCaretPos = query.value(Qt::ImCursorPosition).toInt(); - - return m_lastCaretPos; -} - -extracted_text_t *QQnxInputContext::onGetExtractedText(input_session_t *ic, extracted_text_request_t *request, int32_t flags) -{ - Q_UNUSED(flags); - Q_UNUSED(request); - qInputContextDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) { - extracted_text_t *et = (extracted_text_t *)calloc(sizeof(extracted_text_t),1); - et->text = reinterpret_cast(calloc(sizeof(spannable_string_t),1)); - return et; - } - - // Used to update dictionaries, but not supported right now. - extracted_text_t *et = (extracted_text_t *)calloc(sizeof(extracted_text_t),1); - et->text = reinterpret_cast(calloc(sizeof(spannable_string_t),1)); - - return et; -} - -spannable_string_t *QQnxInputContext::onGetSelectedText(input_session_t *ic, int32_t flags) +spannable_string_t *QQnxInputContext::onGetTextAfterCursor(int32_t n, int32_t flags) { Q_UNUSED(flags); qInputContextDebug() << Q_FUNC_INFO; - if (!isSessionOkay(ic)) - return toSpannableString(""); - QObject *input = qGuiApp->focusObject(); - if (!imfAvailable() || !input) - return 0; - - QInputMethodQueryEvent query(Qt::ImCurrentSelection); - QCoreApplication::sendEvent(input, &query); - QString text = query.value(Qt::ImCurrentSelection).toString(); - - return toSpannableString(text); -} - -spannable_string_t *QQnxInputContext::onGetTextAfterCursor(input_session_t *ic, int32_t n, int32_t flags) -{ - Q_UNUSED(flags); - qInputContextDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return toSpannableString(""); - - QObject *input = qGuiApp->focusObject(); - if (!imfAvailable() || !input) + if (!input) return toSpannableString(""); QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImSurroundingText); QCoreApplication::sendEvent(input, &query); QString text = query.value(Qt::ImSurroundingText).toString(); - m_lastCaretPos = query.value(Qt::ImCursorPosition).toInt(); + m_caretPosition = query.value(Qt::ImCursorPosition).toInt(); - return toSpannableString(text.mid(m_lastCaretPos+1, n)); + return toSpannableString(text.mid(m_caretPosition, n)); } -spannable_string_t *QQnxInputContext::onGetTextBeforeCursor(input_session_t *ic, int32_t n, int32_t flags) +spannable_string_t *QQnxInputContext::onGetTextBeforeCursor(int32_t n, int32_t flags) { Q_UNUSED(flags); qInputContextDebug() << Q_FUNC_INFO; - if (!isSessionOkay(ic)) - return toSpannableString(""); - QObject *input = qGuiApp->focusObject(); - if (!imfAvailable() || !input) + if (!input) return toSpannableString(""); QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImSurroundingText); QCoreApplication::sendEvent(input, &query); QString text = query.value(Qt::ImSurroundingText).toString(); - m_lastCaretPos = query.value(Qt::ImCursorPosition).toInt(); + m_caretPosition = query.value(Qt::ImCursorPosition).toInt(); - if (n < m_lastCaretPos) - return toSpannableString(text.mid(m_lastCaretPos - n, n)); + if (n < m_caretPosition) + return toSpannableString(text.mid(m_caretPosition - n, n)); else - return toSpannableString(text.mid(0, m_lastCaretPos)); + return toSpannableString(text.mid(0, m_caretPosition)); } -int32_t QQnxInputContext::onPerformEditorAction(input_session_t *ic, int32_t editor_action) -{ - Q_UNUSED(editor_action); - qInputContextDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return 0; - - // Should never get called. - qCritical() << Q_FUNC_INFO << "onPerformEditorAction is unsupported."; - - return 0; -} - -int32_t QQnxInputContext::onReportFullscreenMode(input_session_t *ic, int32_t enabled) -{ - Q_UNUSED(enabled); - qInputContextDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return 0; - - // Should never get called. - qCritical() << Q_FUNC_INFO << "onReportFullscreenMode is unsupported."; - - return 0; -} - -int32_t QQnxInputContext::onSendEvent(input_session_t *ic, event_t *event) +int32_t QQnxInputContext::onSendEvent(event_t *event) { qInputContextDebug() << Q_FUNC_INFO; - if (!isSessionOkay(ic)) - return 0; - return processEvent(event); } -int32_t QQnxInputContext::onSendAsyncEvent(input_session_t *ic, event_t *event) +int32_t QQnxInputContext::onSendAsyncEvent(event_t *event) { qInputContextDebug() << Q_FUNC_INFO; - if (!isSessionOkay(ic)) - return 0; - return processEvent(event); } -int32_t QQnxInputContext::onSetComposingRegion(input_session_t *ic, int32_t start, int32_t end) +int32_t QQnxInputContext::onSetComposingRegion(int32_t start, int32_t end) { - qInputContextDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return 0; - QObject *input = qGuiApp->focusObject(); - if (!imfAvailable() || !input) + if (!input) return 0; QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImSurroundingText); QCoreApplication::sendEvent(input, &query); QString text = query.value(Qt::ImSurroundingText).toString(); - m_lastCaretPos = query.value(Qt::ImCursorPosition).toInt(); + m_caretPosition = query.value(Qt::ImCursorPosition).toInt(); - QString empty = QString::fromLatin1(""); - text = text.mid(start, end - start); + qInputContextDebug() << Q_FUNC_INFO << text; + + m_isUpdatingText = true; // Delete the current text. - QList attributes; - QInputMethodEvent event(empty, attributes); - event.setCommitString(empty, start - m_lastCaretPos, end - start); - QCoreApplication::sendEvent(input, &event); - - // Move the specified text into a preedit string. - setComposingText(text); - - return 0; -} - -int32_t QQnxInputContext::onSetComposingText(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position) -{ - Q_UNUSED(new_cursor_position); - qInputContextDebug() << Q_FUNC_INFO; - - if (!isSessionOkay(ic)) - return 0; - - QObject *input = qGuiApp->focusObject(); - if (!imfAvailable() || !input) - return 0; + QInputMethodEvent deleteEvent; + deleteEvent.setCommitString(QString(), start - m_caretPosition, end - start); + QCoreApplication::sendEvent(input, &deleteEvent); + m_composingText = text.mid(start, end - start); m_isComposing = true; - QString preeditString = QString::fromWCharArray(text->str, text->length); - setComposingText(preeditString); + QList attributes; + QTextCharFormat format; + format.setFontUnderline(true); + attributes.push_back(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, m_composingText.length(), format)); + + QInputMethodEvent setTextEvent(m_composingText, attributes); + QCoreApplication::sendEvent(input, &setTextEvent); + + m_isUpdatingText = false; return 0; } -int32_t QQnxInputContext::onSetSelection(input_session_t *ic, int32_t start, int32_t end) +int32_t QQnxInputContext::onSetComposingText(spannable_string_t *text, int32_t new_cursor_position) { - Q_UNUSED(start); - Q_UNUSED(end); - qInputContextDebug() << Q_FUNC_INFO; + if (text->length > 0) { + updateComposition(text, new_cursor_position); + } else { + // If the composing text is empty we can simply end composition, the visual effect is the same. + // However, sometimes one wants to display hint text in an empty text field and for this to work + // QQuickTextEdit.inputMethodComposing has to be false if the composition string is empty. + m_composingText.clear(); + finishComposingText(); + } + return 0; +} - if (!isSessionOkay(ic)) - return 0; +int32_t QQnxInputContext::onIsTextSelected(int32_t* pIsSelected) +{ + *pIsSelected = hasSelectedText(); - // Should never get called. - qCritical() << Q_FUNC_INFO << "onSetSelection is unsupported."; + qInputContextDebug() << Q_FUNC_INFO << *pIsSelected; + + return 0; +} + +int32_t QQnxInputContext::onIsAllTextSelected(int32_t* pIsSelected) +{ + QObject *input = qGuiApp->focusObject(); + if (!input) + return -1; + + QInputMethodQueryEvent query(Qt::ImCurrentSelection | Qt::ImSurroundingText); + QCoreApplication::sendEvent(input, &query); + + *pIsSelected = query.value(Qt::ImSurroundingText).toString().length() == query.value(Qt::ImCurrentSelection).toString().length(); + + qInputContextDebug() << Q_FUNC_INFO << *pIsSelected; return 0; } @@ -1563,8 +1318,16 @@ void QQnxInputContext::setFocusObject(QObject *object) if (!inputMethodAccepted()) { if (m_inputPanelVisible) hideInputPanel(); + if (sInputSession != 0) + dispatchFocusLossEvent(); } else { - m_virtualKeyboard.setInputHintsFromObject(object); + QInputMethodQueryEvent query(Qt::ImHints); + QCoreApplication::sendEvent(object, &query); + int inputHints = query.value(Qt::ImHints).toInt(); + + dispatchFocusGainEvent(inputHints); + + m_virtualKeyboard.setInputHints(inputHints); if (!m_inputPanelVisible) showInputPanel(); diff --git a/src/plugins/platforms/qnx/qqnxinputcontext_imf.h b/src/plugins/platforms/qnx/qqnxinputcontext_imf.h index 1980a99ed9..cda4f2e88e 100644 --- a/src/plugins/platforms/qnx/qqnxinputcontext_imf.h +++ b/src/plugins/platforms/qnx/qqnxinputcontext_imf.h @@ -1,6 +1,6 @@ /*************************************************************************** ** -** Copyright (C) 2011 - 2012 Research In Motion +** Copyright (C) 2013 BlackBerry Limited. All rights reserved. ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -43,6 +43,7 @@ #define QQNXINPUTCONTEXT_H #include +#include "qqnxscreeneventfilter.h" #include #include @@ -55,8 +56,9 @@ QT_BEGIN_NAMESPACE class QQnxAbstractVirtualKeyboard; class QQnxIntegration; +class QQnxImfRequest; -class QQnxInputContext : public QPlatformInputContext +class QQnxInputContext : public QPlatformInputContext, public QQnxScreenEventFilter { Q_OBJECT public: @@ -68,8 +70,9 @@ public: bool filterEvent(const QEvent *event); QRectF keyboardRect() const; void reset(); + void commit(); void update(Qt::InputMethodQueries); - bool handleKeyboardEvent(int flags, int sym, int mod, int scan, int cap); + bool handleKeyboardEvent(int flags, int sym, int mod, int scan, int cap, int sequenceId); void showInputPanel(); @@ -79,61 +82,54 @@ public: QLocale locale() const; void setFocusObject(QObject *object); -protected: - // Filters only for IMF events. - bool eventFilter(QObject *obj, QEvent *event); - private Q_SLOTS: void keyboardVisibilityChanged(bool visible); void keyboardLocaleChanged(const QLocale &locale); + void processImfEvent(QQnxImfRequest *event); private: // IMF Event dispatchers - bool dispatchFocusEvent(FocusEventId id, int hints = Qt::ImhNone); + bool dispatchFocusGainEvent(int inputHints); + void dispatchFocusLossEvent(); bool dispatchRequestSoftwareInputPanel(); bool dispatchCloseSoftwareInputPanel(); int32_t processEvent(event_t *event); void closeSession(); - void openSession(); + bool openSession(); bool hasSession(); + void updateCursorPosition(); void endComposition(); - void setComposingText(QString const &composingText); + void finishComposingText(); bool hasSelectedText(); + void updateComposition(spannable_string_t *text, int32_t new_cursor_position); // IMF Event handlers - these events will come in from QCoreApplication. - int32_t onBeginBatchEdit(input_session_t *ic); - int32_t onClearMetaKeyStates(input_session_t *ic, int32_t states); - int32_t onCommitText(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position); - int32_t onDeleteSurroundingText(input_session_t *ic, int32_t left_length, int32_t right_length); - int32_t onEndBatchEdit(input_session_t *ic); - int32_t onFinishComposingText(input_session_t *ic); - int32_t onGetCursorCapsMode(input_session_t *ic, int32_t req_modes); - int32_t onGetCursorPosition(input_session_t *ic); - extracted_text_t *onGetExtractedText(input_session_t *ic, extracted_text_request_t *request, int32_t flags); - spannable_string_t *onGetSelectedText(input_session_t *ic, int32_t flags); - spannable_string_t *onGetTextAfterCursor(input_session_t *ic, int32_t n, int32_t flags); - spannable_string_t *onGetTextBeforeCursor(input_session_t *ic, int32_t n, int32_t flags); - int32_t onPerformEditorAction(input_session_t *ic, int32_t editor_action); - int32_t onReportFullscreenMode(input_session_t *ic, int32_t enabled); - int32_t onSendEvent(input_session_t *ic, event_t *event); - int32_t onSendAsyncEvent(input_session_t *ic, event_t *event); - int32_t onSetComposingRegion(input_session_t *ic, int32_t start, int32_t end); - int32_t onSetComposingText(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position); - int32_t onSetSelection(input_session_t *ic, int32_t start, int32_t end); + int32_t onCommitText(spannable_string_t *text, int32_t new_cursor_position); + int32_t onDeleteSurroundingText(int32_t left_length, int32_t right_length); + int32_t onGetCursorCapsMode(int32_t req_modes); + int32_t onFinishComposingText(); + int32_t onGetCursorPosition(); + spannable_string_t *onGetTextAfterCursor(int32_t n, int32_t flags); + spannable_string_t *onGetTextBeforeCursor(int32_t n, int32_t flags); + int32_t onSendEvent(event_t *event); + int32_t onSendAsyncEvent(event_t *event); + int32_t onSetComposingRegion(int32_t start, int32_t end); + int32_t onSetComposingText(spannable_string_t *text, int32_t new_cursor_position); + int32_t onIsTextSelected(int32_t* pIsSelected); + int32_t onIsAllTextSelected(int32_t* pIsSelected); int32_t onForceUpdate(); - int m_lastCaretPos; + int m_caretPosition; bool m_isComposing; QString m_composingText; + bool m_isUpdatingText; bool m_inputPanelVisible; QLocale m_inputPanelLocale; QQnxIntegration *m_integration; - QQnxAbstractVirtualKeyboard &m_virtualKeyboad; + QQnxAbstractVirtualKeyboard &m_virtualKeyboard; }; -Q_DECLARE_METATYPE(extracted_text_t*) - QT_END_NAMESPACE #endif // QQNXINPUTCONTEXT_H diff --git a/src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp b/src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp index f444d34b5e..9270f1ed6b 100644 --- a/src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp +++ b/src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp @@ -1,6 +1,6 @@ /*************************************************************************** ** -** Copyright (C) 2011 - 2012 Research In Motion +** Copyright (C) 2013 BlackBerry Limited. All rights reserved. ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -46,6 +46,7 @@ #include #include +#include #if defined(QQNXINPUTCONTEXT_DEBUG) #define qInputContextDebug qDebug @@ -179,7 +180,11 @@ void QQnxInputContext::setFocusObject(QObject *object) if (m_inputPanelVisible) hideInputPanel(); } else { - m_virtualKeyboard.setInputHintsFromObject(object); + QInputMethodQueryEvent query(Qt::ImHints); + QCoreApplication::sendEvent(object, &query); + int inputHints = query.value(Qt::ImHints).toInt(); + + m_virtualKeyboard.setInputHints(inputHints); if (!m_inputPanelVisible) showInputPanel(); diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp index 36a2194b56..09054b9eb9 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.cpp +++ b/src/plugins/platforms/qnx/qqnxintegration.cpp @@ -1,6 +1,6 @@ /*************************************************************************** ** -** Copyright (C) 2011 - 2012 Research In Motion +** Copyright (C) 2013 BlackBerry Limited. All rights reserved. ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -240,6 +240,9 @@ QQnxIntegration::QQnxIntegration(const QStringList ¶mList) #if defined(QQNX_PPS) // Set up the input context m_inputContext = new QQnxInputContext(this, *m_virtualKeyboard); +#if defined(QQNX_IMF) + m_screenEventHandler->addScreenEventFilter(m_inputContext); +#endif #endif } @@ -260,17 +263,6 @@ QQnxIntegration::~QQnxIntegration() delete m_drag; #endif -#if defined(QQNX_PPS) - // Destroy the hardware button notifier - delete m_buttonsNotifier; - - // Destroy input context - delete m_inputContext; -#endif - - // Destroy the keyboard class. - delete m_virtualKeyboard; - #if !defined(QT_NO_CLIPBOARD) // Delete the clipboard delete m_clipboard; @@ -310,6 +302,17 @@ QQnxIntegration::~QQnxIntegration() QQnxGLContext::shutdown(); #endif +#if defined(QQNX_PPS) + // Destroy the hardware button notifier + delete m_buttonsNotifier; + + // Destroy input context + delete m_inputContext; +#endif + + // Destroy the keyboard class. + delete m_virtualKeyboard; + // Destroy services class delete m_services; diff --git a/src/plugins/platforms/qnx/qqnxscreeneventfilter.h b/src/plugins/platforms/qnx/qqnxscreeneventfilter.h new file mode 100644 index 0000000000..f9ecadd2a9 --- /dev/null +++ b/src/plugins/platforms/qnx/qqnxscreeneventfilter.h @@ -0,0 +1,58 @@ +/*************************************************************************** +** +** Copyright (C) 2013 BlackBerry Limited. All rights reserved. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQNXSCREENEVENTFILTER_H +#define QQNXSCREENEVENTFILTER_H + +QT_BEGIN_NAMESPACE + +class QQnxScreenEventFilter +{ +protected: + ~QQnxScreenEventFilter() {} + +public: + virtual bool handleKeyboardEvent(int flags, int sym, int mod, int scan, int cap, int sequenceId) = 0; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp index c869d29c99..a5d6db0985 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp +++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp @@ -1,6 +1,6 @@ /*************************************************************************** ** -** Copyright (C) 2011 - 2012 Research In Motion +** Copyright (C) 2013 BlackBerry Limited. All rights reserved. ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -43,6 +43,7 @@ #include "qqnxintegration.h" #include "qqnxkeytranslator.h" #include "qqnxscreen.h" +#include "qqnxscreeneventfilter.h" #include #include @@ -84,6 +85,16 @@ QQnxScreenEventHandler::QQnxScreenEventHandler(QQnxIntegration *integration) } } +void QQnxScreenEventHandler::addScreenEventFilter(QQnxScreenEventFilter *filter) +{ + m_eventFilters.append(filter); +} + +void QQnxScreenEventHandler::removeScreenEventFilter(QQnxScreenEventFilter *filter) +{ + m_eventFilters.removeOne(filter); +} + bool QQnxScreenEventHandler::handleEvent(screen_event_t event) { // get the event type @@ -209,7 +220,23 @@ void QQnxScreenEventHandler::handleKeyboardEvent(screen_event_t event) if (result) qFatal("QQNX: failed to query event cap, errno=%d", errno); - injectKeyboardEvent(flags, sym, modifiers, scan, cap); + int sequenceId = 0; +#if defined(Q_OS_BLACKBERRY) + result = screen_get_event_property_iv(event, SCREEN_PROPERTY_SEQUENCE_ID, &sequenceId); + if (result) + qFatal("QQNX: failed to query event seqId, errno=%d", errno); +#endif + + bool inject = true; + Q_FOREACH (QQnxScreenEventFilter *filter, m_eventFilters) { + if (filter->handleKeyboardEvent(flags, sym, modifiers, scan, cap, sequenceId)) { + inject = false; + break; + } + } + + if (inject) + injectKeyboardEvent(flags, sym, modifiers, scan, cap); } void QQnxScreenEventHandler::handlePointerEvent(screen_event_t event) diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.h b/src/plugins/platforms/qnx/qqnxscreeneventhandler.h index 7a1af6f343..af0b086eb8 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.h +++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.h @@ -1,6 +1,6 @@ /*************************************************************************** ** -** Copyright (C) 2011 - 2012 Research In Motion +** Copyright (C) 2013 BlackBerry Limited. All rights reserved. ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -49,6 +49,7 @@ QT_BEGIN_NAMESPACE class QQnxIntegration; +class QQnxScreenEventFilter; class QQnxScreenEventHandler : public QObject { @@ -56,6 +57,9 @@ class QQnxScreenEventHandler : public QObject public: explicit QQnxScreenEventHandler(QQnxIntegration *integration); + void addScreenEventFilter(QQnxScreenEventFilter *filter); + void removeScreenEventFilter(QQnxScreenEventFilter *filter); + bool handleEvent(screen_event_t event); bool handleEvent(screen_event_t event, int qnxType); @@ -85,6 +89,7 @@ private: screen_window_t m_lastMouseWindow; QTouchDevice *m_touchDevice; QWindowSystemInterface::TouchPoint m_touchPoints[MaximumTouchPoints]; + QList m_eventFilters; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxvirtualkeyboardbps.cpp b/src/plugins/platforms/qnx/qqnxvirtualkeyboardbps.cpp index 11eb4a5082..f3a6887613 100644 --- a/src/plugins/platforms/qnx/qqnxvirtualkeyboardbps.cpp +++ b/src/plugins/platforms/qnx/qqnxvirtualkeyboardbps.cpp @@ -1,6 +1,6 @@ /*************************************************************************** ** -** Copyright (C) 2012 Research In Motion +** Copyright (C) 2013 BlackBerry Limited. All rights reserved. ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -135,6 +135,10 @@ void QQnxVirtualKeyboardBps::applyKeyboardMode(KeyboardMode mode) layout = VIRTUALKEYBOARD_LAYOUT_PIN; break; + case Password: + layout = VIRTUALKEYBOARD_LAYOUT_PASSWORD; + break; + case Default: // fall through default: layout = VIRTUALKEYBOARD_LAYOUT_DEFAULT; From 10014e083181bce07b7d2697fb23c9691ca6ce02 Mon Sep 17 00:00:00 2001 From: Roger Maclean Date: Wed, 16 Oct 2013 11:38:32 -0400 Subject: [PATCH 051/684] Add configuration for building with imf support on QNX Avoid need to modify qnx.pro in src/plugins/platforms/qnx to build with imf support. By default detects if necessary headers and libraries are available. Can also be explicitly requested or disabled with -imf and -no-imf options. Change-Id: I3f9780fc189a33e4c93fb4f950111121f8e947c3 Reviewed-by: Oswald Buddenhagen --- config.tests/unix/qqnx_imf/qqnx_imf.cpp | 48 +++++++++++++++++++++++++ config.tests/unix/qqnx_imf/qqnx_imf.pro | 3 ++ configure | 22 +++++++++++- tools/configure/configureapp.cpp | 21 ++++++++++- 4 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 config.tests/unix/qqnx_imf/qqnx_imf.cpp create mode 100644 config.tests/unix/qqnx_imf/qqnx_imf.pro diff --git a/config.tests/unix/qqnx_imf/qqnx_imf.cpp b/config.tests/unix/qqnx_imf/qqnx_imf.cpp new file mode 100644 index 0000000000..b88593bf33 --- /dev/null +++ b/config.tests/unix/qqnx_imf/qqnx_imf.cpp @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2013 BlackBerry Limited. All rights reserved. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the config.tests 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 "imf/imf_client.h" + +int main(int, char **) +{ + imf_client_init(); + return 0; +} diff --git a/config.tests/unix/qqnx_imf/qqnx_imf.pro b/config.tests/unix/qqnx_imf/qqnx_imf.pro new file mode 100644 index 0000000000..c51adb65ad --- /dev/null +++ b/config.tests/unix/qqnx_imf/qqnx_imf.pro @@ -0,0 +1,3 @@ +SOURCES = qqnx_imf.cpp +CONFIG -= qt +LIBS += -linput_client diff --git a/configure b/configure index fcd9f08ed1..2933ff6401 100755 --- a/configure +++ b/configure @@ -907,6 +907,7 @@ CFG_JAVASCRIPTCORE_JIT=auto CFG_PKGCONFIG=auto CFG_STACK_PROTECTOR_STRONG=auto CFG_SLOG2=auto +CFG_QNX_IMF=auto CFG_SYSTEM_PROXIES=no # Target architecture @@ -2036,6 +2037,13 @@ while [ "$#" -gt 0 ]; do UNKNOWN_OPT=yes fi ;; + imf) + if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then + CFG_QNX_IMF="$VAL" + else + UNKNOWN_OPT=yes + fi + ;; gstreamer) if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then CFG_GSTREAMER="$VAL" @@ -3727,6 +3735,8 @@ if [ "$XPLATFORM_QNX" = "yes" ]; then -no-slog2 .......... Do not compile with slog2 support. -slog2 ............. Compile with slog2 support. + -no-imf ............ Do not compile with imf support. + -imf ............... Compile with imf support. EOF @@ -4567,6 +4577,14 @@ if [ "$XPLATFORM_QNX" = "yes" ]; then CFG_SLOG2=no fi fi + if [ "$CFG_QNX_IMF" != "no" ]; then + if compileTest unix/qqnx_imf "qqnx_imf"; then + CFG_QNX_IMF=yes + QMAKE_CONFIG="$QMAKE_CONFIG qqnx_imf" + else + CFG_QNX_IMF=no + fi + fi fi if [ "$CFG_ZLIB" = "auto" ]; then @@ -6957,8 +6975,10 @@ if [ "$CFG_XCB" != "no" ]; then report_support " XVideo ............." "$CFG_XVIDEO" fi report_support " Session management ....." "$CFG_SM" -[ "$XPLATFORM_QNX" = "yes" ] && \ +if [ "$XPLATFORM_QNX" = "yes" ]; then report_support " SLOG2 .................." "$CFG_SLOG2" + report_support " IMF ...................." "$CFG_QNX_IMF" +fi report_support " SQL drivers:" report_support " DB2 .................." "$CFG_SQL_db2" plugin "plugin" yes "built into QtSql" report_support " InterBase ............" "$CFG_SQL_ibase" plugin "plugin" yes "built into QtSql" diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index b4162b3f0f..d9390c8266 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -194,6 +194,7 @@ Configure::Configure(int& argc, char** argv) dictionary[ "QT_CUPS" ] = "auto"; dictionary[ "CFG_GCC_SYSROOT" ] = "yes"; dictionary[ "SLOG2" ] = "no"; + dictionary[ "QNX_IMF" ] = "no"; dictionary[ "SYSTEM_PROXIES" ] = "no"; dictionary[ "WERROR" ] = "auto"; @@ -872,6 +873,10 @@ void Configure::parseCmdLine() dictionary[ "SLOG2" ] = "no"; } else if (configCmdLine.at(i) == "-slog2") { dictionary[ "SLOG2" ] = "yes"; + } else if (configCmdLine.at(i) == "-no-imf") { + dictionary[ "QNX_IMF" ] = "no"; + } else if (configCmdLine.at(i) == "-imf") { + dictionary[ "QNX_IMF" ] = "yes"; } else if (configCmdLine.at(i) == "-no-system-proxies") { dictionary[ "SYSTEM_PROXIES" ] = "no"; } else if (configCmdLine.at(i) == "-system-proxies") { @@ -1653,6 +1658,7 @@ void Configure::applySpecSpecifics() } else if ((platform() == QNX) || (platform() == BLACKBERRY)) { dictionary["STACK_PROTECTOR_STRONG"] = "auto"; dictionary["SLOG2"] = "auto"; + dictionary["QNX_IMF"] = "auto"; dictionary["QT_XKBCOMMON"] = "no"; } else if (platform() == ANDROID) { dictionary[ "REDUCE_EXPORTS" ] = "yes"; @@ -1864,6 +1870,8 @@ bool Configure::displayHelp() if ((platform() == QNX) || (platform() == BLACKBERRY)) { desc("SLOG2", "yes", "-slog2", "Compile with slog2 support."); desc("SLOG2", "no", "-no-slog2", "Do not compile with slog2 support."); + desc("QNX_IMF", "yes", "-imf", "Compile with imf support."); + desc("QNX_IMF", "no", "-no-imf", "Do not compile with imf support."); } desc("ANGLE", "yes", "-angle", "Use the ANGLE implementation of OpenGL ES 2.0."); @@ -2209,6 +2217,8 @@ bool Configure::checkAvailability(const QString &part) available = (platform() == QNX || platform() == BLACKBERRY) && compilerSupportsFlag("qcc -fstack-protector-strong"); } else if (part == "SLOG2") { available = tryCompileProject("unix/slog2"); + } else if (part == "QNX_IMF") { + available = tryCompileProject("unix/qqnx_imf"); } return available; @@ -2345,6 +2355,10 @@ void Configure::autoDetection() dictionary["SLOG2"] = checkAvailability("SLOG2") ? "yes" : "no"; } + if ((platform() == QNX || platform() == BLACKBERRY) && dictionary["QNX_IMF"] == "auto") { + dictionary["QNX_IMF"] = checkAvailability("QNX_IMF") ? "yes" : "no"; + } + if (dictionary["QT_EVENTFD"] == "auto") dictionary["QT_EVENTFD"] = checkAvailability("QT_EVENTFD") ? "yes" : "no"; @@ -3188,6 +3202,9 @@ void Configure::generateQConfigPri() if (dictionary[ "SLOG2" ] == "yes") configStream << " slog2"; + if (dictionary[ "QNX_IMF" ] == "yes") + configStream << " qqnx_imf"; + if (dictionary["DIRECTWRITE"] == "yes") configStream << " directwrite"; @@ -3553,8 +3570,10 @@ void Configure::displayConfig() sout << " HarfBuzz-NG support....." << dictionary[ "HARFBUZZ" ] << endl; sout << " PCRE support............" << dictionary[ "PCRE" ] << endl; sout << " ICU support............." << dictionary[ "ICU" ] << endl; - if ((platform() == QNX) || (platform() == BLACKBERRY)) + if ((platform() == QNX) || (platform() == BLACKBERRY)) { sout << " SLOG2 support..........." << dictionary[ "SLOG2" ] << endl; + sout << " IMF support............." << dictionary[ "QNX_IMF" ] << endl; + } sout << " ANGLE..................." << dictionary[ "ANGLE" ] << endl; sout << endl; From 041abb93169668b8f6ebac128050d4507e000e16 Mon Sep 17 00:00:00 2001 From: John Layt Date: Sun, 29 Jul 2012 16:27:21 +0100 Subject: [PATCH 052/684] QPrintSupport: Move QAbstractPrintDialog test into QPrintSupport Move the test for QAbstractPrintDialog from widgets into printsupport Change-Id: Ia7595fa650a7ad565df3090207500ed06564e842 Reviewed-by: Marc Mutz --- tests/auto/printsupport/dialogs/dialogs.pro | 3 +++ .../dialogs/qabstractprintdialog/.gitignore | 0 .../dialogs/qabstractprintdialog/qabstractprintdialog.pro | 0 .../dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp | 0 tests/auto/printsupport/printsupport.pro | 1 + tests/auto/widgets/dialogs/dialogs.pro | 3 --- 6 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 tests/auto/printsupport/dialogs/dialogs.pro rename tests/auto/{widgets => printsupport}/dialogs/qabstractprintdialog/.gitignore (100%) rename tests/auto/{widgets => printsupport}/dialogs/qabstractprintdialog/qabstractprintdialog.pro (100%) rename tests/auto/{widgets => printsupport}/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp (100%) diff --git a/tests/auto/printsupport/dialogs/dialogs.pro b/tests/auto/printsupport/dialogs/dialogs.pro new file mode 100644 index 0000000000..419bd13ccf --- /dev/null +++ b/tests/auto/printsupport/dialogs/dialogs.pro @@ -0,0 +1,3 @@ +TEMPLATE=subdirs +SUBDIRS=\ + qabstractprintdialog \ diff --git a/tests/auto/widgets/dialogs/qabstractprintdialog/.gitignore b/tests/auto/printsupport/dialogs/qabstractprintdialog/.gitignore similarity index 100% rename from tests/auto/widgets/dialogs/qabstractprintdialog/.gitignore rename to tests/auto/printsupport/dialogs/qabstractprintdialog/.gitignore diff --git a/tests/auto/widgets/dialogs/qabstractprintdialog/qabstractprintdialog.pro b/tests/auto/printsupport/dialogs/qabstractprintdialog/qabstractprintdialog.pro similarity index 100% rename from tests/auto/widgets/dialogs/qabstractprintdialog/qabstractprintdialog.pro rename to tests/auto/printsupport/dialogs/qabstractprintdialog/qabstractprintdialog.pro diff --git a/tests/auto/widgets/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp b/tests/auto/printsupport/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp similarity index 100% rename from tests/auto/widgets/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp rename to tests/auto/printsupport/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp diff --git a/tests/auto/printsupport/printsupport.pro b/tests/auto/printsupport/printsupport.pro index 69ba296738..062f46980a 100644 --- a/tests/auto/printsupport/printsupport.pro +++ b/tests/auto/printsupport/printsupport.pro @@ -1,3 +1,4 @@ TEMPLATE=subdirs SUBDIRS=\ + dialogs \ kernel \ diff --git a/tests/auto/widgets/dialogs/dialogs.pro b/tests/auto/widgets/dialogs/dialogs.pro index acff1df5ba..c5f2c409dd 100644 --- a/tests/auto/widgets/dialogs/dialogs.pro +++ b/tests/auto/widgets/dialogs/dialogs.pro @@ -1,6 +1,5 @@ TEMPLATE=subdirs SUBDIRS=\ - qabstractprintdialog \ qcolordialog \ qdialog \ qerrormessage \ @@ -14,8 +13,6 @@ SUBDIRS=\ qsidebar \ qwizard \ -wince*|!qtHaveModule(printsupport):SUBDIRS -= qabstractprintdialog - !contains(QT_CONFIG, private_tests): SUBDIRS -= \ qsidebar \ From 7f1017931ca709bd18085d930d352a3aae877fb3 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 24 Oct 2013 12:58:09 +0200 Subject: [PATCH 053/684] Add empty dist/changes-5.3.0 file Change-Id: Iea2f6bb3b1d5c922167c4e96c825c08db9aa1b4e Reviewed-by: Sergio Ahumada --- dist/changes-5.3.0 | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 dist/changes-5.3.0 diff --git a/dist/changes-5.3.0 b/dist/changes-5.3.0 new file mode 100644 index 0000000000..87d9c771e7 --- /dev/null +++ b/dist/changes-5.3.0 @@ -0,0 +1,29 @@ +Qt 5.3 introduces many new features and improvements as well as bugfixes +over the 5.2.x series. For more details, refer to the online documentation +included in this distribution. The documentation is also available online: + + http://qt-project.org/doc/qt-5.3 + +The Qt version 5.3 series is binary compatible with the 5.2.x series. +Applications compiled for 5.2 will continue to run with 5.3. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + http://bugreports.qt-project.org/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Library * +**************************************************************************** + +QtWidgets +--------- + +QtCore +------ + +QtGui +----- From e65f568a8f6d6fbb89bc241b0ea78b18708ad2d5 Mon Sep 17 00:00:00 2001 From: Roger Maclean Date: Mon, 21 Oct 2013 14:33:23 -0400 Subject: [PATCH 054/684] Improve mapping between Font Config and Qt font attributes It was sometimes impossible to select the desired font due to the code completely ignoring the FC_WIDTH attribute and poor mapping of the FC_WEIGHT attribute. The result was that it was easy to have a font file that was inaccessible by Qt since it shared attributes with another font file. The FC_WIDTH attribute is now fetched and used unchanged as the font's stretch value other than ensuring it is within the allowed range. For FC_WEIGHT, the code no longer matches the value with the closest QFont::Weight enum but instead does a piecewise linear mapping so that Qt enum values match Font Config ones to the extent possible. Also removed bogus call to fetch the width that was doing nothing with it. Change-Id: Id39715f14a617c1d0e00ecf5a7d391cab99adc03 Reviewed-by: Konstantin Ritt Reviewed-by: Fabian Bumberger Reviewed-by: Bernd Weimer Reviewed-by: Rafael Roquetto --- .../fontconfig/qfontconfigdatabase.cpp | 67 ++++++++++++++----- 1 file changed, 50 insertions(+), 17 deletions(-) diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 8c3ca2d229..da4007ff21 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -69,21 +69,52 @@ static inline bool requiresOpenType(int writingSystem) || writingSystem == QFontDatabase::Khmer || writingSystem == QFontDatabase::Nko); } -static int getFCWeight(int fc_weight) +static inline int weightFromFcWeight(int fcweight) { - int qtweight = QFont::Black; - if (fc_weight <= (FC_WEIGHT_LIGHT + FC_WEIGHT_REGULAR) / 2) - qtweight = QFont::Light; - else if (fc_weight <= (FC_WEIGHT_REGULAR + FC_WEIGHT_MEDIUM) / 2) - qtweight = QFont::Normal; - else if (fc_weight <= (FC_WEIGHT_MEDIUM + FC_WEIGHT_BOLD) / 2) - qtweight = QFont::DemiBold; - else if (fc_weight <= (FC_WEIGHT_BOLD + FC_WEIGHT_BLACK) / 2) - qtweight = QFont::Bold; + // Font Config uses weights from 0 to 215 (the highest enum value) while QFont ranges from + // 0 to 99. The spacing between the values for the enums are uneven so a linear mapping from + // Font Config values to Qt would give surprising results. So, we do a piecewise linear + // mapping. This ensures that where there is a corresponding enum on both sides (for example + // FC_WEIGHT_DEMIBOLD and QFont::DemiBold) we map one to the other but other values map + // to intermediate Qt weights. + const int maxWeight = 99; + int qtweight; + if (fcweight < 0) + qtweight = 0; + else if (fcweight <= FC_WEIGHT_LIGHT) + qtweight = (fcweight * QFont::Light) / FC_WEIGHT_LIGHT; + else if (fcweight <= FC_WEIGHT_NORMAL) + qtweight = QFont::Light + ((fcweight - FC_WEIGHT_LIGHT) * (QFont::Normal - QFont::Light)) / (FC_WEIGHT_NORMAL - FC_WEIGHT_LIGHT); + else if (fcweight <= FC_WEIGHT_DEMIBOLD) + qtweight = QFont::Normal + ((fcweight - FC_WEIGHT_NORMAL) * (QFont::DemiBold - QFont::Normal)) / (FC_WEIGHT_DEMIBOLD - FC_WEIGHT_NORMAL); + else if (fcweight <= FC_WEIGHT_BOLD) + qtweight = QFont::DemiBold + ((fcweight - FC_WEIGHT_DEMIBOLD) * (QFont::Bold - QFont::DemiBold)) / (FC_WEIGHT_BOLD - FC_WEIGHT_DEMIBOLD); + else if (fcweight <= FC_WEIGHT_BLACK) + qtweight = QFont::Bold + ((fcweight - FC_WEIGHT_BOLD) * (QFont::Black - QFont::Bold)) / (FC_WEIGHT_BLACK - FC_WEIGHT_BOLD); + else if (fcweight <= FC_WEIGHT_ULTRABLACK) + qtweight = QFont::Black + ((fcweight - FC_WEIGHT_BLACK) * (maxWeight - QFont::Black)) / (FC_WEIGHT_ULTRABLACK - FC_WEIGHT_BLACK); + else + qtweight = maxWeight; return qtweight; } +static inline int stretchFromFcWidth(int fcwidth) +{ + // Font Config enums for width match pretty closely with those used by Qt so just use + // Font Config values directly while enforcing the same limits imposed by QFont. + const int maxStretch = 4000; + int qtstretch; + if (fcwidth < 1) + qtstretch = 1; + else if (fcwidth > maxStretch) + qtstretch = maxStretch; + else + qtstretch = fcwidth; + + return qtstretch; +} + static const char *specialLanguages[] = { "", // Unknown "", // Inherited @@ -309,6 +340,7 @@ void QFontconfigDatabase::populateFontDatabase() int weight_value; int slant_value; int spacing_value; + int width_value; FcChar8 *file_value; int indexValue; FcChar8 *foundry_value; @@ -322,7 +354,7 @@ void QFontconfigDatabase::populateFontDatabase() const char *properties [] = { FC_FAMILY, FC_STYLE, FC_WEIGHT, FC_SLANT, FC_SPACING, FC_FILE, FC_INDEX, - FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE, FC_WEIGHT, + FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE, FC_WIDTH, #if FC_VERSION >= 20297 FC_CAPABILITY, @@ -356,6 +388,8 @@ void QFontconfigDatabase::populateFontDatabase() slant_value = FC_SLANT_ROMAN; if (FcPatternGetInteger (fonts->fonts[i], FC_WEIGHT, 0, &weight_value) != FcResultMatch) weight_value = FC_WEIGHT_REGULAR; + if (FcPatternGetInteger (fonts->fonts[i], FC_WIDTH, 0, &width_value) != FcResultMatch) + width_value = FC_WIDTH_NORMAL; if (FcPatternGetInteger (fonts->fonts[i], FC_SPACING, 0, &spacing_value) != FcResultMatch) spacing_value = FC_PROPORTIONAL; if (FcPatternGetString (fonts->fonts[i], FC_FILE, 0, &file_value) != FcResultMatch) @@ -417,17 +451,16 @@ void QFontconfigDatabase::populateFontDatabase() : ((slant_value == FC_SLANT_OBLIQUE) ? QFont::StyleOblique : QFont::StyleNormal); - QFont::Weight weight = QFont::Weight(getFCWeight(weight_value)); + // Note: weight should really be an int but registerFont incorrectly uses an enum + QFont::Weight weight = QFont::Weight(weightFromFcWeight(weight_value)); double pixel_size = 0; - if (!scalable) { - int width = 100; - FcPatternGetInteger (fonts->fonts[i], FC_WIDTH, 0, &width); + if (!scalable) FcPatternGetDouble (fonts->fonts[i], FC_PIXEL_SIZE, 0, &pixel_size); - } bool fixedPitch = spacing_value >= FC_MONO; - QFont::Stretch stretch = QFont::Unstretched; + // Note: stretch should really be an int but registerFont incorrectly uses an enum + QFont::Stretch stretch = QFont::Stretch(stretchFromFcWidth(width_value)); QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString(); QPlatformFontDatabase::registerFont(familyName,styleName,QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,fontFile); // qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size; From fc5d07cee3c2d0f90badd24ddab0b220492f474f Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 26 Oct 2013 00:45:14 +0200 Subject: [PATCH 055/684] QLCDNumber: remove unused header #include Change-Id: Ic1608a11a48c373b7ad816c1305cce0fe236425b Reviewed-by: Friedemann Kleint --- src/widgets/widgets/qlcdnumber.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/widgets/widgets/qlcdnumber.h b/src/widgets/widgets/qlcdnumber.h index 3dde1527f2..ba7b2d8494 100644 --- a/src/widgets/widgets/qlcdnumber.h +++ b/src/widgets/widgets/qlcdnumber.h @@ -43,7 +43,6 @@ #define QLCDNUMBER_H #include -#include QT_BEGIN_NAMESPACE From e913972d5268a2b1e5bfc12a0a72e4811e764d86 Mon Sep 17 00:00:00 2001 From: Oto Magaldadze Date: Tue, 17 Sep 2013 14:02:49 +0400 Subject: [PATCH 056/684] added QAbstractSpinBox::setGroupSeparatorShown function. [ChangeLog][QtWidgets][QAbstractSpinBox] QTBUG-5142 - This will allow a group (thousand) separator to be shown in QSpinBox and QDoubleSpinBox widgets. Task-number: QTBUG-5142 Change-Id: I2e23f5f83c93bb092a2dbd784e06d17d40d42909 Reviewed-by: Marc Mutz --- examples/widgets/widgets/spinboxes/window.cpp | 25 ++++++++++ examples/widgets/widgets/spinboxes/window.h | 3 ++ src/widgets/widgets/qabstractspinbox.cpp | 27 +++++++++- src/widgets/widgets/qabstractspinbox.h | 4 ++ src/widgets/widgets/qabstractspinbox_p.h | 1 + src/widgets/widgets/qspinbox.cpp | 16 +++--- .../qdoublespinbox/tst_qdoublespinbox.cpp | 46 +++++++++++++++++ .../widgets/widgets/qspinbox/tst_qspinbox.cpp | 49 +++++++++++++++++++ 8 files changed, 163 insertions(+), 8 deletions(-) diff --git a/examples/widgets/widgets/spinboxes/window.cpp b/examples/widgets/widgets/spinboxes/window.cpp index acce642ec6..7c2f6e45bc 100644 --- a/examples/widgets/widgets/spinboxes/window.cpp +++ b/examples/widgets/widgets/spinboxes/window.cpp @@ -94,6 +94,16 @@ void Window::createSpinBoxes() priceSpinBox->setValue(99); //! [4] //! [5] + groupSeparatorSpinBox = new QSpinBox; + groupSeparatorSpinBox->setRange(-99999999, 99999999); + groupSeparatorSpinBox->setValue(1000); + groupSeparatorSpinBox->setGroupSeparatorShown(true); + QCheckBox *groupSeparatorChkBox = new QCheckBox; + groupSeparatorChkBox->setText(tr("Show group separator")); + groupSeparatorChkBox->setChecked(true); + connect(groupSeparatorChkBox, &QCheckBox::toggled, groupSeparatorSpinBox, + &QSpinBox::setGroupSeparatorShown); + QLabel *hexLabel = new QLabel(tr("Enter a value between " "%1 and %2:").arg('-' + QString::number(31, 16)).arg(QString::number(31, 16))); QSpinBox *hexSpinBox = new QSpinBox; @@ -111,6 +121,8 @@ void Window::createSpinBoxes() spinBoxLayout->addWidget(priceSpinBox); spinBoxLayout->addWidget(hexLabel); spinBoxLayout->addWidget(hexSpinBox); + spinBoxLayout->addWidget(groupSeparatorChkBox); + spinBoxLayout->addWidget(groupSeparatorSpinBox); spinBoxesGroup->setLayout(spinBoxLayout); } //! [5] @@ -237,6 +249,17 @@ void Window::createDoubleSpinBoxes() //! [17] this, SLOT(changePrecision(int))); + groupSeparatorSpinBox_d = new QDoubleSpinBox; + groupSeparatorSpinBox_d->setRange(-99999999, 99999999); + groupSeparatorSpinBox_d->setDecimals(2); + groupSeparatorSpinBox_d->setValue(1000.00); + groupSeparatorSpinBox_d->setGroupSeparatorShown(true); + QCheckBox *groupSeparatorChkBox = new QCheckBox; + groupSeparatorChkBox->setText(tr("Show group separator")); + groupSeparatorChkBox->setChecked(true); + connect(groupSeparatorChkBox, &QCheckBox::toggled, groupSeparatorSpinBox_d, + &QDoubleSpinBox::setGroupSeparatorShown); + //! [18] QVBoxLayout *spinBoxLayout = new QVBoxLayout; spinBoxLayout->addWidget(precisionLabel); @@ -247,6 +270,8 @@ void Window::createDoubleSpinBoxes() spinBoxLayout->addWidget(scaleSpinBox); spinBoxLayout->addWidget(priceLabel); spinBoxLayout->addWidget(priceSpinBox); + spinBoxLayout->addWidget(groupSeparatorChkBox); + spinBoxLayout->addWidget(groupSeparatorSpinBox_d); doubleSpinBoxesGroup->setLayout(spinBoxLayout); } //! [18] diff --git a/examples/widgets/widgets/spinboxes/window.h b/examples/widgets/widgets/spinboxes/window.h index ef7af04f59..32622c2c24 100644 --- a/examples/widgets/widgets/spinboxes/window.h +++ b/examples/widgets/widgets/spinboxes/window.h @@ -45,6 +45,7 @@ QT_BEGIN_NAMESPACE class QDateTimeEdit; +class QSpinBox; class QDoubleSpinBox; class QGroupBox; class QLabel; @@ -75,6 +76,8 @@ private: QGroupBox *editsGroup; QGroupBox *doubleSpinBoxesGroup; QLabel *meetingLabel; + QSpinBox *groupSeparatorSpinBox; + QDoubleSpinBox *groupSeparatorSpinBox_d; }; //! [0] diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp index 25369a01b6..af3a4d35f9 100644 --- a/src/widgets/widgets/qabstractspinbox.cpp +++ b/src/widgets/widgets/qabstractspinbox.cpp @@ -395,6 +395,30 @@ bool QAbstractSpinBox::isAccelerated() const return d->accelerate; } +/*! + \property QAbstractSpinBox::showGroupSeparator + \since 5.3 + + + This property holds whether a thousands separator is enabled. By default this + property is false. +*/ +bool QAbstractSpinBox::isGroupSeparatorShown() const +{ + Q_D(const QAbstractSpinBox); + return d->showGroupSeparator; +} + +void QAbstractSpinBox::setGroupSeparatorShown(bool shown) +{ + Q_D(QAbstractSpinBox); + if (d->showGroupSeparator == shown) + return; + d->showGroupSeparator = shown; + d->setValue(d->value, EmitIfChanged); + updateGeometry(); +} + /*! \enum QAbstractSpinBox::CorrectionMode @@ -1316,7 +1340,8 @@ QAbstractSpinBoxPrivate::QAbstractSpinBoxPrivate() cachedState(QValidator::Invalid), pendingEmit(false), readOnly(false), wrapping(false), ignoreCursorPositionChanged(false), frame(true), accelerate(false), keyboardTracking(true), cleared(false), ignoreUpdateEdit(false), correctionMode(QAbstractSpinBox::CorrectToPreviousValue), - acceleration(0), hoverControl(QStyle::SC_None), buttonSymbols(QAbstractSpinBox::UpDownArrows), validator(0) + acceleration(0), hoverControl(QStyle::SC_None), buttonSymbols(QAbstractSpinBox::UpDownArrows), validator(0), + showGroupSeparator(0) { } diff --git a/src/widgets/widgets/qabstractspinbox.h b/src/widgets/widgets/qabstractspinbox.h index 4f6aad0cde..7989000cc8 100644 --- a/src/widgets/widgets/qabstractspinbox.h +++ b/src/widgets/widgets/qabstractspinbox.h @@ -72,6 +72,7 @@ class Q_WIDGETS_EXPORT QAbstractSpinBox : public QWidget Q_PROPERTY(CorrectionMode correctionMode READ correctionMode WRITE setCorrectionMode) Q_PROPERTY(bool acceptableInput READ hasAcceptableInput) Q_PROPERTY(bool keyboardTracking READ keyboardTracking WRITE setKeyboardTracking) + Q_PROPERTY(bool showGroupSeparator READ isGroupSeparatorShown WRITE setGroupSeparatorShown) public: explicit QAbstractSpinBox(QWidget *parent = 0); ~QAbstractSpinBox(); @@ -114,6 +115,9 @@ public: void setAccelerated(bool on); bool isAccelerated() const; + void setGroupSeparatorShown(bool shown); + bool isGroupSeparatorShown() const; + QSize sizeHint() const; QSize minimumSizeHint() const; void interpretText(); diff --git a/src/widgets/widgets/qabstractspinbox_p.h b/src/widgets/widgets/qabstractspinbox_p.h index 0eeec02abc..da9f1d9757 100644 --- a/src/widgets/widgets/qabstractspinbox_p.h +++ b/src/widgets/widgets/qabstractspinbox_p.h @@ -150,6 +150,7 @@ public: QRect hoverRect; QAbstractSpinBox::ButtonSymbols buttonSymbols; QSpinBoxValidator *validator; + uint showGroupSeparator : 1; }; class QSpinBoxValidator : public QValidator diff --git a/src/widgets/widgets/qspinbox.cpp b/src/widgets/widgets/qspinbox.cpp index bf4e130d4e..a43b937951 100644 --- a/src/widgets/widgets/qspinbox.cpp +++ b/src/widgets/widgets/qspinbox.cpp @@ -463,8 +463,8 @@ void QSpinBox::setDisplayIntegerBase(int base) display the given \a value. The default implementation returns a string containing \a value printed in the standard way using QWidget::locale().toString(), but with the thousand separator - removed. Reimplementations may return anything. (See the example - in the detailed description.) + removed unless setGroupSeparatorShown() is set. Reimplementations may + return anything. (See the example in the detailed description.) Note: QSpinBox does not call this function for specialValueText() and that neither prefix() nor suffix() should be included in the @@ -487,7 +487,7 @@ QString QSpinBox::textFromValue(int value) const str.prepend('-'); } else { str = locale().toString(value); - if (qAbs(value) >= 1000 || value == INT_MIN) { + if (!d->showGroupSeparator && (qAbs(value) >= 1000 || value == INT_MIN)) { str.remove(locale().groupSeparator()); } } @@ -538,7 +538,8 @@ QValidator::State QSpinBox::validate(QString &text, int &pos) const */ void QSpinBox::fixup(QString &input) const { - input.remove(locale().groupSeparator()); + if (!isGroupSeparatorShown()) + input.remove(locale().groupSeparator()); } @@ -891,7 +892,8 @@ void QDoubleSpinBox::setDecimals(int decimals) display the given \a value. The default implementation returns a string containing \a value printed using QWidget::locale().toString(\a value, QLatin1Char('f'), decimals()) and will remove the thousand - separator. Reimplementations may return anything. + separator unless setGroupSeparatorShown() is set. Reimplementations may + return anything. Note: QDoubleSpinBox does not call this function for specialValueText() and that neither prefix() nor suffix() should @@ -908,9 +910,9 @@ QString QDoubleSpinBox::textFromValue(double value) const { Q_D(const QDoubleSpinBox); QString str = locale().toString(value, 'f', d->decimals); - if (qAbs(value) >= 1000.0) { + if (!d->showGroupSeparator && qAbs(value) >= 1000.0) str.remove(locale().groupSeparator()); - } + return str; } diff --git a/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp b/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp index b880ebe078..49f058862d 100644 --- a/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp +++ b/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp @@ -145,6 +145,9 @@ private slots: void taskQTBUG_6670_selectAllWithPrefix(); void taskQTBUG_6496_fiddlingWithPrecision(); + void setGroupSeparatorShown_data(); + void setGroupSeparatorShown(); + public slots: void valueChangedHelper(const QString &); void valueChangedHelper(double); @@ -156,6 +159,9 @@ private: typedef QList DoubleList; +Q_DECLARE_METATYPE(QLocale::Language) +Q_DECLARE_METATYPE(QLocale::Country) + tst_QDoubleSpinBox::tst_QDoubleSpinBox() { @@ -1099,5 +1105,45 @@ void tst_QDoubleSpinBox::taskQTBUG_6496_fiddlingWithPrecision() QCOMPARE(dsb.maximum(), 0.991); } +void tst_QDoubleSpinBox::setGroupSeparatorShown_data() +{ + QTest::addColumn("lang"); + QTest::addColumn("country"); + + QTest::newRow("data0") << QLocale::English << QLocale::UnitedStates; + QTest::newRow("data1") << QLocale::Swedish << QLocale::Sweden; + QTest::newRow("data2") << QLocale::German << QLocale::Germany; + QTest::newRow("data3") << QLocale::Georgian << QLocale::Georgia; + QTest::newRow("data3") << QLocale::Macedonian << QLocale::Macedonia; +} + +void tst_QDoubleSpinBox::setGroupSeparatorShown() +{ + QFETCH(QLocale::Language, lang); + QFETCH(QLocale::Country, country); + + QLocale loc(lang, country); + QLocale::setDefault(loc); + DoubleSpinBox spinBox; + spinBox.setMaximum(99999999); + spinBox.setValue(1300000.00); + spinBox.setGroupSeparatorShown(true); + QCOMPARE(spinBox.lineEdit()->text(), spinBox.locale().toString(1300000.00, 'f', 2)); + QCOMPARE(spinBox.isGroupSeparatorShown(), true); + QCOMPARE(spinBox.textFromValue(23421),spinBox.locale().toString(23421.00, 'f', 2)); + + spinBox.setGroupSeparatorShown(false); + QCOMPARE(spinBox.lineEdit()->text(), spinBox.locale().toString(1300000.00, 'f', 2).remove( + spinBox.locale().groupSeparator())); + QCOMPARE(spinBox.isGroupSeparatorShown(), false); + + spinBox.setMaximum(72000); + spinBox.lineEdit()->setText(spinBox.locale().toString(32000.64, 'f', 2)); + QCOMPARE(spinBox.value()+1000, 33000.64); + + spinBox.lineEdit()->setText(spinBox.locale().toString(32000.44, 'f', 2)); + QCOMPARE(spinBox.value()+1000, 33000.44); +} + QTEST_MAIN(tst_QDoubleSpinBox) #include "tst_qdoublespinbox.moc" diff --git a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp index 004fdda5ef..1c97686668 100644 --- a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp +++ b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp @@ -142,6 +142,10 @@ private slots: void taskQTBUG_5008_textFromValueAndValidate(); void lineEditReturnPressed(); + + void setGroupSeparatorShown_data(); + void setGroupSeparatorShown(); + public slots: void valueChangedHelper(const QString &); void valueChangedHelper(int); @@ -152,6 +156,9 @@ private: typedef QList IntList; +Q_DECLARE_METATYPE(QLocale::Language) +Q_DECLARE_METATYPE(QLocale::Country) + // Testing get/set functions void tst_QSpinBox::getSetCheck() { @@ -1111,5 +1118,47 @@ void tst_QSpinBox::lineEditReturnPressed() QCOMPARE(spyCurrentChanged.count(), 1); } +void tst_QSpinBox::setGroupSeparatorShown_data() +{ + QTest::addColumn("lang"); + QTest::addColumn("country"); + + QTest::newRow("data0") << QLocale::English << QLocale::UnitedStates; + QTest::newRow("data1") << QLocale::Swedish << QLocale::Sweden; + QTest::newRow("data2") << QLocale::German << QLocale::Germany; + QTest::newRow("data3") << QLocale::Georgian << QLocale::Georgia; + QTest::newRow("data3") << QLocale::Macedonian << QLocale::Macedonia; +} + +void tst_QSpinBox::setGroupSeparatorShown() +{ + QFETCH(QLocale::Language, lang); + QFETCH(QLocale::Country, country); + + QLocale loc(lang, country); + QLocale::setDefault(loc); + SpinBox spinBox; + spinBox.setMaximum(99999); + spinBox.setValue(13000); + spinBox.setGroupSeparatorShown(true); + QCOMPARE(spinBox.lineEdit()->text(), spinBox.locale().toString(13000)); + QCOMPARE(spinBox.isGroupSeparatorShown(), true); + QCOMPARE(spinBox.textFromValue(23421),spinBox.locale().toString(23421)); + + spinBox.setGroupSeparatorShown(false); + QCOMPARE(spinBox.lineEdit()->text(), QStringLiteral("13000")); + QCOMPARE(spinBox.isGroupSeparatorShown(), false); + + spinBox.setMaximum(72000); + spinBox.lineEdit()->setText(spinBox.locale().toString(32000)); + QCOMPARE(spinBox.value()+1000, 33000); + + spinBox.lineEdit()->setText(QStringLiteral("32000")); + QCOMPARE(spinBox.value()+1000, 33000); + + spinBox.lineEdit()->setText(QStringLiteral("32,000")); + QCOMPARE(spinBox.value()+1000, 33000); +} + QTEST_MAIN(tst_QSpinBox) #include "tst_qspinbox.moc" From bf6a345baa21818010242566bef4f2c25cb72437 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 7 Aug 2013 12:20:53 -0700 Subject: [PATCH 057/684] Doc: update the documentation of QStandardPaths to be more thorough Specifically, note what paths can be empty and which ones can't (modulo system mis-configuration, like an empty $HOME var) and describe what implications there are for application-specific paths and for global (user) paths. Change-Id: If6c11aab466ba50f3a9685dce52dd51b86426f27 Reviewed-by: David Faure --- src/corelib/io/qstandardpaths.cpp | 206 ++++++++++++++++++++++++++---- 1 file changed, 182 insertions(+), 24 deletions(-) diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp index 186321db6e..b32f5ac576 100644 --- a/src/corelib/io/qstandardpaths.cpp +++ b/src/corelib/io/qstandardpaths.cpp @@ -72,31 +72,189 @@ QT_BEGIN_NAMESPACE methods such as QStandardPaths::writableLocation, QStandardPaths::standardLocations, and QStandardPaths::displayName. - \value DesktopLocation Returns the user's desktop directory. - \value DocumentsLocation Returns the user's document. - \value FontsLocation Returns the user's fonts. - \value ApplicationsLocation Returns the user's applications. - \value MusicLocation Returns the user's music. - \value MoviesLocation Returns the user's movies. - \value PicturesLocation Returns the user's pictures. - \value TempLocation Returns the system's temporary directory. - \value HomeLocation Returns the user's home directory. - \value DataLocation Returns a directory location where persistent - application data can be stored. QCoreApplication::organizationName - and QCoreApplication::applicationName are appended to the directory location - returned for GenericDataLocation. - \value CacheLocation Returns a directory location where user-specific - non-essential (cached) data should be written. - \value GenericCacheLocation Returns a directory location where user-specific - non-essential (cached) data, shared across applications, should be written. - \value GenericDataLocation Returns a directory location where persistent - data shared across applications can be stored. - \value RuntimeLocation Returns a directory location where runtime communication - files should be written. For instance unix local sockets. - \value ConfigLocation Returns a directory location where user-specific - configuration files should be written. - \value DownloadLocation Returns a directory for user's downloaded files. + Some of the values in this enum represent a user configuration. Such enum + values will return the same paths in different applications, so they could + be used to share data with other applications. Other values are specific to + this application. Each enum value in the table below describes whether it's + application-specific or generic. + Application-specific directories should be assumed to be unreachable by + other applications. Therefore, files placed there might not be readable by + other applications, even if run by the same user. On the other hand, generic + directories should be assumed to be accessible by all applications run by + this user, but should still be assumed to be unreachable by applications by + other users. + + The only exception is QStandardPaths::TempLocation (which is the same as + QDir::tempPath()): the path returned may be application-specific, but files + stored there may be accessed by other applications run by the same user. + + Data interchange with other users is out of the scope of QStandardPaths. + + \value DesktopLocation Returns the user's desktop directory. This is a generic value. + On systems with no concept of a desktop, this is the same as + QStandardPaths::HomeLocation. + \value DocumentsLocation Returns the directory containing user document files. + This is a generic value. The returned path is never empty. + \value FontsLocation Returns the directory containing user's fonts. This is a generic value. + Note that installing fonts may require additional, platform-specific operations. + \value ApplicationsLocation Returns the directory containing the user applications + (either executables, application bundles, or shortcuts to them). This is a generic value. + Note that installing applications may require additional, platform-specific operations. + Files, folders or shortcuts in this directory are platform-specific. + \value MusicLocation Returns the directory containing the user's music or other audio files. + This is a generic value. If no directory specific for music files exists, a sensible + fallback for storing user documents is returned. + \value MoviesLocation Returns the directory containing the user's movies and videos. + This is a generic value. If no directory specific for movie files exists, a sensible + fallback for storing user documents is returned. + \value PicturesLocation Returns the directory containing the user's pictures or photos. + This is a generic value. If no directory specific for picture files exists, a sensible + fallback for storing user documents is returned. + \value TempLocation Returns a directory where temporary files can be stored. The returned value + might be application-specific, shared among other applications for this user, or even + system-wide. The returned path is never empty. + \value HomeLocation Returns the user's home directory (the same as QDir::homePath()). On Unix + systems, this is equal to the HOME environment variable. This value might be + generic or application-specific, but the returned path is never empty. + \value DataLocation Returns a directory location where persistent + application data can be stored. This is an application-specific directory. To obtain a + path to store data to be shared with other applications, use + QStandardPaths::GenericDataLocation. The returned path is never empty. + \value CacheLocation Returns a directory location where user-specific + non-essential (cached) data should be written. This is an application-specific directory. + The returned path is never empty. + \value GenericCacheLocation Returns a directory location where user-specific non-essential + (cached) data, shared across applications, should be written. This is a generic value. + Note that the returned path may be empty if the system has no concept of shared cache. + \value GenericDataLocation Returns a directory location where persistent + data shared across applications can be stored. This is a generic value. The returned + path is never empty. + \value RuntimeLocation Returns a directory location where runtime communication + files should be written, like Unix local sockets. This is a generic value. + The returned path may be empty on some systems. + \value ConfigLocation Returns a directory location where user-specific + configuration files should be written. This may be either a generic value + or application-specific, and the returned path is never empty. + \value DownloadLocation Returns a directory for user's downloaded files. This is a generic value. + If no directory specific for downloads exists, a sensible fallback for storing user + documents is returned. + + The following table gives examples of paths on different operating systems. + The first path is the writable path (unless noted). Other, additional + paths, if any, represent non-writable locations. + + \table + \header \li Path type \li OS X \li Windows + \row \li DesktopLocation + \li "~/Desktop" + \li "C:/Users//Desktop" + \row \li DocumentsLocation + \li "~/Documents" + \li "C:/Users//Documents" + \row \li FontsLocation + \li "/System/Library/Fonts" (not writable) + \li "C:/Windows/Fonts" (not writable) + \row \li ApplicationsLocation + \li "/Applications" (not writable) + \li "C:/Users//AppData/Roaming/Microsoft/Windows/Start Menu/Programs" + \row \li MusicLocation + \li "~/Music" + \li "C:/Users//Music" + \row \li MoviesLocation + \li "~/Movies" + \li "C:/Users//Videos" + \row \li PicturesLocation + \li "~/Pictures" + \li "C:/Users//Pictures" + \row \li TempLocation + \li randomly generated by the OS + \li "C:/Users//AppData/Local/Temp" + \row \li HomeLocation + \li "~" + \li "C:/Users/" + \row \li DataLocation + \li "~/Library/Application Support/", "/Library/Application Support/" + \li "C:/Users//AppData/Local/", "C:/ProgramData/" + \row \li CacheLocation + \li "~/Library/Caches/", "/Library/Caches/" + \li "C:/Users//AppData/Local//cache" + \row \li GenericDataLocation + \li "~/Library/Application Support", "/Library/Application Support" + \li "C:/Users//AppData/Local", "C:/ProgramData" + \row \li RuntimeLocation + \li "~/Library/Application Support" + \li "C:/Users/" + \row \li ConfigLocation + \li "~/Library/Preferences" + \li "C:/Users//AppData/Local/", "C:/ProgramData/" + \row \li DownloadLocation + \li "~/Documents" + \li "C:/Users//Documents" + \row \li GenericCacheLocation + \li "~/Library/Caches", "/Library/Caches" + \li "C:/Users//AppData/Local/cache" + \endtable + + \table + \header \li Path type \li Blackberry \li Linux (including Android) + \row \li DesktopLocation + \li "/data" + \li "~/Desktop" + \row \li DocumentsLocation + \li "/shared/documents" + \li "~/Documents" + \row \li FontsLocation + \li "/base/usr/fonts" (not writable) + \li "~/.fonts" + \row \li ApplicationsLocation + \li not supported (directory not readable) + \li "~/.local/share/applications", "/usr/local/share/applications", "/usr/share/applications" + \row \li MusicLocation + \li "/shared/music" + \li "~/Music" + \row \li MoviesLocation + \li "/shared/videos" + \li "~/Videos" + \row \li PicturesLocation + \li "/shared/photos" + \li "~/Pictures" + \row \li TempLocation + \li "/var/tmp" + \li "/tmp" + \row \li HomeLocation + \li "/data" + \li "~" + \row \li DataLocation + \li "/data" + \li "~/.local/share/", "/usr/local/share/", "/usr/share/" + \row \li CacheLocation + \li "/data/Cache" + \li "~/.cache/" + \row \li GenericDataLocation + \li "/shared/misc" + \li "~/.local/share", "/usr/local/share", "/usr/share" + \row \li RuntimeLocation + \li "/var/tmp" + \li "/run/user/" + \row \li ConfigLocation + \li "/data/Settings" + \li "~/.config", "/etc/xdg" + \row \li DownloadLocation + \li "/shared/downloads" + \li "~/Downloads" + \row \li GenericCacheLocation + \li "/data/Cache" (there is no shared cache) + \li "~/.cache" + \endtable + + In the table above, \c is usually the organization name, the + application name, or both, or a unique name generated at packaging. + Similarly, is the location where this application is installed + (often a sandbox). + + The paths above should not be relied upon, as they may change according to + OS configuration, locale, or they may change in future Qt versions. \sa writableLocation(), standardLocations(), displayName(), locate(), locateAll() */ From ed827acc27530a97b84685920615359010d74f48 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 1 Mar 2012 18:52:32 +0100 Subject: [PATCH 058/684] QSignalBlocker: (new) RAII class for QObject::blockSignals() I don't think I ever worked on a project of non-trivial size that didn't at some point add a QSignalBlocker. This commit adds code, tests and documentation. Later commits will convert naked blockSignals() calls to use QSignalBlocker. The implementation is purely inline to avoid the heavy overhead of cross-dll function calls for this miniscule task. This should not be a problem because QSignalBlocker only uses public API and a pattern that we anyway need to keep working until Qt 6, at least, so even changing the implementation later will be no problem as the old implementation lurking in non-recompiled code will be acceptable, too. This implementation is an evolution from KDTools' KDSignalBlocker, with the following changes: - Implements unblock() and reblock() - Uses the return value of blockSignals() instead of a separate signalsBlocked() call. Change-Id: I1933dfd72a0f5190324be377cfca3c54cf3d6828 Reviewed-by: Olivier Goffart --- dist/changes-5.3.0 | 2 + src/corelib/kernel/qobject.cpp | 73 +++++++++++++++++++ src/corelib/kernel/qobject.h | 46 ++++++++++++ .../corelib/kernel/qobject/tst_qobject.cpp | 49 +++++++++++++ 4 files changed, 170 insertions(+) diff --git a/dist/changes-5.3.0 b/dist/changes-5.3.0 index 87d9c771e7..035d0656ed 100644 --- a/dist/changes-5.3.0 +++ b/dist/changes-5.3.0 @@ -25,5 +25,7 @@ QtWidgets QtCore ------ +- QSignalBlocker: (new) RAII wrapper around QObject::blockSignals() + QtGui ----- diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index a52fd25e08..72ce941b6e 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -482,6 +482,79 @@ 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() + + 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 diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index e2000afc82..f9239bf575 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -549,6 +549,52 @@ template 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(); + + inline void reblock(); + inline void unblock(); +private: + Q_DISABLE_COPY(QSignalBlocker) + QObject * const 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) +{} + +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/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 05d81c2bd1..f429500077 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -102,6 +102,7 @@ private slots: #ifndef QT_NO_PROCESS void recursiveSignalEmission(); #endif + void signalBlocking(); void blockingQueuedConnection(); void childEvents(); void installEventFilter(); @@ -2979,6 +2980,54 @@ void tst_QObject::recursiveSignalEmission() } #endif +void tst_QObject::signalBlocking() +{ + SenderObject sender; + ReceiverObject receiver; + + receiver.connect(&sender, SIGNAL(signal1()), SLOT(slot1())); + + sender.emitSignal1(); + QVERIFY(receiver.called(1)); + receiver.reset(); + + { + QSignalBlocker blocker(&sender); + + sender.emitSignal1(); + QVERIFY(!receiver.called(1)); + receiver.reset(); + + sender.blockSignals(false); + + sender.emitSignal1(); + QVERIFY(receiver.called(1)); + receiver.reset(); + + sender.blockSignals(true); + + sender.emitSignal1(); + QVERIFY(!receiver.called(1)); + receiver.reset(); + + blocker.unblock(); + + sender.emitSignal1(); + QVERIFY(receiver.called(1)); + receiver.reset(); + + blocker.reblock(); + + sender.emitSignal1(); + QVERIFY(!receiver.called(1)); + receiver.reset(); + } + + sender.emitSignal1(); + QVERIFY(receiver.called(1)); + receiver.reset(); +} + void tst_QObject::blockingQueuedConnection() { { From 0326c036d693b08b8649cb5f5f652683254ace4a Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 25 Oct 2013 19:46:57 +0200 Subject: [PATCH 059/684] QItemSelectionModel: use QSignalBlocker Change-Id: Ib88db7516fd7dd8f10a86444c506f3294948e79b Reviewed-by: Olivier Goffart --- src/corelib/itemmodels/qitemselectionmodel.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/corelib/itemmodels/qitemselectionmodel.cpp b/src/corelib/itemmodels/qitemselectionmodel.cpp index aff9939b87..883aa5b982 100644 --- a/src/corelib/itemmodels/qitemselectionmodel.cpp +++ b/src/corelib/itemmodels/qitemselectionmodel.cpp @@ -1271,9 +1271,8 @@ void QItemSelectionModel::clearCurrentIndex() */ void QItemSelectionModel::reset() { - bool block = blockSignals(true); + const QSignalBlocker blocker(this); clear(); - blockSignals(block); } /*! From 3549dfe8b8db536ada91607f4cfbfd830a3cb572 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 25 Oct 2013 19:47:22 +0200 Subject: [PATCH 060/684] QColorDialog: use QSignalBlocker Change-Id: Id680d9b934760cdd6a20579518199bd388b56e5d Reviewed-by: Olivier Goffart --- src/widgets/dialogs/qcolordialog.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp index d20725fc89..8956842493 100644 --- a/src/widgets/dialogs/qcolordialog.cpp +++ b/src/widgets/dialogs/qcolordialog.cpp @@ -883,10 +883,8 @@ public: QColSpinBox(QWidget *parent) : QSpinBox(parent) { setRange(0, 255); } void setValue(int i) { - bool block = signalsBlocked(); - blockSignals(true); + const QSignalBlocker blocker(this); QSpinBox::setValue(i); - blockSignals(block); } }; From 4003d44ca27863c6ec7ec1b4266496fb201fd033 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 25 Oct 2013 19:47:37 +0200 Subject: [PATCH 061/684] QFileDialog: use QSignalBlocker Change-Id: I32a631493138a777458557232da084f497adc526 Reviewed-by: Olivier Goffart --- src/widgets/dialogs/qfiledialog.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index d45f623b8d..11ad7c7a5d 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -2612,9 +2612,8 @@ void QFileDialog::accept() // special case for ".." if (lineEditText == QLatin1String("..")) { d->_q_navigateToParent(); - bool block = d->qFileDialogUi->fileNameEdit->blockSignals(true); + const QSignalBlocker blocker(d->qFileDialogUi->fileNameEdit); d->lineEdit()->selectAll(); - d->qFileDialogUi->fileNameEdit->blockSignals(block); return; } From 8d7b0a8c3ef9929aabfda53c0cbd73b148859c44 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 25 Oct 2013 19:48:05 +0200 Subject: [PATCH 062/684] QFontDialog: use QSignalBlocker Change-Id: I7be3ac4a7e6988d768e1db68f10a6920aa825a76 Reviewed-by: Olivier Goffart --- src/widgets/dialogs/qfontdialog.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/widgets/dialogs/qfontdialog.cpp b/src/widgets/dialogs/qfontdialog.cpp index d908a683a9..94e96a52c5 100644 --- a/src/widgets/dialogs/qfontdialog.cpp +++ b/src/widgets/dialogs/qfontdialog.cpp @@ -632,12 +632,11 @@ void QFontDialogPrivate::updateSizes() } sizeList->setCurrentItem(current); - sizeEdit->blockSignals(true); + const QSignalBlocker blocker(sizeEdit); sizeEdit->setText((smoothScalable ? QString::number(size) : sizeList->currentText())); if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, q) && sizeList->hasFocus()) sizeEdit->selectAll(); - sizeEdit->blockSignals(false); } else { sizeEdit->clear(); } @@ -750,9 +749,8 @@ void QFontDialogPrivate::_q_sizeChanged(const QString &s) if (sizeList->text(i).toInt() >= this->size) break; } - sizeList->blockSignals(true); + const QSignalBlocker blocker(sizeList); sizeList->setCurrentItem(i); - sizeList->blockSignals(false); } _q_updateSample(); } From 48894cc75b08964e0303c8045cb9ec0c274a4c9e Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 25 Oct 2013 19:51:33 +0200 Subject: [PATCH 063/684] QAbstractSpinBox: use QSignalBlocker This change changes the point where signals are unblocked again in QAbstractSpinBoxPrivate::updateEdit() to include the final update() call. This should not be a problem, as update() merely posts an event and shouldn't emit any signals. Change-Id: I4b2ae109f057792b573ad6ea168ca77c18c773d0 Reviewed-by: Olivier Goffart --- src/widgets/widgets/qabstractspinbox.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp index af3a4d35f9..92af91b66e 100644 --- a/src/widgets/widgets/qabstractspinbox.cpp +++ b/src/widgets/widgets/qabstractspinbox.cpp @@ -1516,13 +1516,12 @@ void QAbstractSpinBoxPrivate::_q_editorCursorPositionChanged(int oldpos, int new * (newpos < pos ? -1 : 1)) - newpos + pos : 0; - const bool wasBlocked = edit->blockSignals(true); + const QSignalBlocker blocker(edit); if (selSize != 0) { edit->setSelection(pos - selSize, selSize); } else { edit->setCursorPosition(pos); } - edit->blockSignals(wasBlocked); } ignoreCursorPositionChanged = false; } @@ -1722,7 +1721,7 @@ void QAbstractSpinBoxPrivate::updateEdit() const bool empty = edit->text().isEmpty(); int cursor = edit->cursorPosition(); int selsize = edit->selectedText().size(); - const bool sb = edit->blockSignals(true); + const QSignalBlocker blocker(edit); edit->setText(newText); if (!specialValue()) { @@ -1734,7 +1733,6 @@ void QAbstractSpinBoxPrivate::updateEdit() edit->setCursorPosition(empty ? prefix.size() : cursor); } } - edit->blockSignals(sb); q->update(); } From b2d3d6365edc312d18451e58e1a0b18c538b3f98 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 25 Oct 2013 19:56:34 +0200 Subject: [PATCH 064/684] QDateTimeEdit: use QSignalBlocker Change-Id: I4983e96a51220f40644d202d76e92a889ae9431a Reviewed-by: Olivier Goffart --- src/widgets/widgets/qdatetimeedit.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp index a0bbbbf7c7..6bfc251a2a 100644 --- a/src/widgets/widgets/qdatetimeedit.cpp +++ b/src/widgets/widgets/qdatetimeedit.cpp @@ -1718,7 +1718,7 @@ void QDateTimeEditPrivate::updateEdit() if (newText == displayText()) return; int selsize = edit->selectedText().size(); - const bool sb = edit->blockSignals(true); + const QSignalBlocker blocker(edit); edit->setText(newText); @@ -1740,7 +1740,6 @@ void QDateTimeEditPrivate::updateEdit() } } - edit->blockSignals(sb); } @@ -1871,7 +1870,7 @@ void QDateTimeEditPrivate::clearSection(int index) { const QLatin1Char space(' '); int cursorPos = edit->cursorPosition(); - bool blocked = edit->blockSignals(true); + const QSignalBlocker blocker(edit); QString t = edit->text(); const int pos = sectionPos(index); if (pos == -1) { @@ -1883,8 +1882,6 @@ void QDateTimeEditPrivate::clearSection(int index) edit->setText(t); edit->setCursorPosition(cursorPos); QDTEDEBUG << cursorPos; - - edit->blockSignals(blocked); } @@ -2574,10 +2571,9 @@ void QDateTimeEditPrivate::syncCalendarWidget() { Q_Q(QDateTimeEdit); if (monthCalendar) { - const bool sb = monthCalendar->blockSignals(true); + const QSignalBlocker blocker(monthCalendar); monthCalendar->setDateRange(q->minimumDate(), q->maximumDate()); monthCalendar->setDate(q->date()); - monthCalendar->blockSignals(sb); } } From b5a4be09aad19f01b5d83f8674ae244f126c3d4f Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 25 Oct 2013 19:58:43 +0200 Subject: [PATCH 065/684] QDockAreaLayout: use QSignalBlocker This change changes the point where signals are unblocked again in QDockAreaLayoutInfo::updateTabBar() to include the final tabBar->count() call. This should not be a problem, as count() is a const function and thus shouldn't emit any signals. Change-Id: I6f3dc5696a9c31db51fbe4cdee4b9d83ddeaf61f Reviewed-by: Olivier Goffart --- src/widgets/widgets/qdockarealayout.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp index 72a463b30b..8dab6afb81 100644 --- a/src/widgets/widgets/qdockarealayout.cpp +++ b/src/widgets/widgets/qdockarealayout.cpp @@ -2096,7 +2096,7 @@ bool QDockAreaLayoutInfo::updateTabBar() const that->tabBar->setDrawBase(true); } - bool blocked = tabBar->blockSignals(true); + const QSignalBlocker blocker(tabBar); bool gap = false; int tab_idx = 0; @@ -2147,8 +2147,6 @@ bool QDockAreaLayoutInfo::updateTabBar() const tabBar->removeTab(tab_idx); } - tabBar->blockSignals(blocked); - //returns if the tabbar is visible or not return ( (gap ? 1 : 0) + tabBar->count()) > 1; } From 91c682e7194c2c8d2dd206a543c51e7061325e3e Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 25 Oct 2013 19:59:26 +0200 Subject: [PATCH 066/684] QMdiArea: use QSignalBlocker Change-Id: I54bb64531b1b9639bec163a96baae67b9cabd16b Reviewed-by: Olivier Goffart --- src/widgets/widgets/qmdiarea.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/widgets/widgets/qmdiarea.cpp b/src/widgets/widgets/qmdiarea.cpp index 5c1d7a6c05..ea33f40806 100644 --- a/src/widgets/widgets/qmdiarea.cpp +++ b/src/widgets/widgets/qmdiarea.cpp @@ -1120,10 +1120,9 @@ void QMdiAreaPrivate::updateActiveWindow(int removedIndex, bool activeRemoved) #ifndef QT_NO_TABBAR if (tabBar && removedIndex >= 0) { - tabBar->blockSignals(true); + const QSignalBlocker blocker(tabBar); tabBar->removeTab(removedIndex); updateTabBarGeometry(); - tabBar->blockSignals(false); } #endif From abbffdd4be577ba77a06af9e9d1e565fd2c8a65e Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 25 Oct 2013 19:59:37 +0200 Subject: [PATCH 067/684] QTabWidget: use QSignalBlocker Change-Id: I4621e6b504c531903210242cf0f1cf12e7538784 Reviewed-by: Olivier Goffart --- src/widgets/widgets/qtabwidget.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/widgets/widgets/qtabwidget.cpp b/src/widgets/widgets/qtabwidget.cpp index 8c15b3e58e..fced1c01ec 100644 --- a/src/widgets/widgets/qtabwidget.cpp +++ b/src/widgets/widgets/qtabwidget.cpp @@ -759,11 +759,10 @@ void QTabWidgetPrivate::_q_removeTab(int index) void QTabWidgetPrivate::_q_tabMoved(int from, int to) { - stack->blockSignals(true); + const QSignalBlocker blocker(stack); QWidget *w = stack->widget(from); stack->removeWidget(w); stack->insertWidget(to, w); - stack->blockSignals(false); } /* From 64050fe92e7d7533151a5df8143331fef003ed23 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 26 Oct 2013 11:05:26 +0200 Subject: [PATCH 068/684] QPrintPreviewWidget: use QSignalBlocker Change-Id: Ic2d48c8e2c9c3c6f06e67ebf7e12bd4899b421aa Reviewed-by: Olivier Goffart --- src/printsupport/widgets/qprintpreviewwidget.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/printsupport/widgets/qprintpreviewwidget.cpp b/src/printsupport/widgets/qprintpreviewwidget.cpp index f788663041..3ef1e882fe 100644 --- a/src/printsupport/widgets/qprintpreviewwidget.cpp +++ b/src/printsupport/widgets/qprintpreviewwidget.cpp @@ -162,9 +162,10 @@ signals: protected: void resizeEvent(QResizeEvent* e) { - const bool blocked = verticalScrollBar()->blockSignals(true); // Don't change page, QTBUG-14517 - QGraphicsView::resizeEvent(e); - verticalScrollBar()->blockSignals(blocked); + { + const QSignalBlocker blocker(verticalScrollBar()); // Don't change page, QTBUG-14517 + QGraphicsView::resizeEvent(e); + } emit resized(); } From 694e822080dacd7a574729188a295bf6e6e512e4 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 26 Oct 2013 11:05:42 +0200 Subject: [PATCH 069/684] QInputDialog: use QSignalBlocker Change-Id: I711dbc0c35bc51ad3149e3d7b41e716bc9ab94b5 Reviewed-by: Olivier Goffart --- src/widgets/dialogs/qinputdialog.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/widgets/dialogs/qinputdialog.cpp b/src/widgets/dialogs/qinputdialog.cpp index 4eec2eb3e2..10d693b4a3 100644 --- a/src/widgets/dialogs/qinputdialog.cpp +++ b/src/widgets/dialogs/qinputdialog.cpp @@ -771,10 +771,11 @@ void QInputDialog::setComboBoxItems(const QStringList &items) Q_D(QInputDialog); d->ensureComboBox(); - d->comboBox->blockSignals(true); - d->comboBox->clear(); - d->comboBox->addItems(items); - d->comboBox->blockSignals(false); + { + const QSignalBlocker blocker(d->comboBox); + d->comboBox->clear(); + d->comboBox->addItems(items); + } if (inputMode() == TextInput) d->chooseRightTextInputWidget(); From 180e28ef5086fe82c69ec6406ab5bc4202f7fc4d Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 26 Oct 2013 11:06:12 +0200 Subject: [PATCH 070/684] QTreeWidget: use QSignalBlocker Change-Id: I0b69cd5680dfae6349bd4a952f358fe0b4acb2ff Reviewed-by: Friedemann Kleint Reviewed-by: Olivier Goffart --- src/widgets/itemviews/qtreewidget.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/widgets/itemviews/qtreewidget.cpp b/src/widgets/itemviews/qtreewidget.cpp index e75f602e90..3ce757847c 100644 --- a/src/widgets/itemviews/qtreewidget.cpp +++ b/src/widgets/itemviews/qtreewidget.cpp @@ -493,8 +493,7 @@ bool QTreeModel::removeRows(int row, int count, const QModelIndex &parent) { beginRemoveRows(parent, row, row + count - 1); - bool blockSignal = signalsBlocked(); - blockSignals(true); + QSignalBlocker blocker(this); QTreeWidgetItem *itm = item(parent); for (int i = row + count - 1; i >= row; --i) { @@ -504,7 +503,7 @@ bool QTreeModel::removeRows(int row, int count, const QModelIndex &parent) { delete child; child = 0; } - blockSignals(blockSignal); + blocker.unblock(); endRemoveRows(); return true; From 6861fb25771e3e574a9b5c229d0cdd26119f6bf3 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 26 Oct 2013 11:06:43 +0200 Subject: [PATCH 071/684] QFontComboBox: use QSignalBlocker Change-Id: I6a9eab39088275427e4282ee590fda439b2f2901 Reviewed-by: Olivier Goffart --- src/widgets/widgets/qfontcombobox.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/widgets/widgets/qfontcombobox.cpp b/src/widgets/widgets/qfontcombobox.cpp index 0b0efa2bdf..2bbf3730db 100644 --- a/src/widgets/widgets/qfontcombobox.cpp +++ b/src/widgets/widgets/qfontcombobox.cpp @@ -346,9 +346,10 @@ void QFontComboBoxPrivate::_q_updateModel() //this prevents the current index from changing //it will be updated just after this ///TODO: we should finda way to avoid blocking signals and have a real update of the model - const bool old = m->blockSignals(true); - m->setStringList(list); - m->blockSignals(old); + { + const QSignalBlocker blocker(m); + m->setStringList(list); + } if (list.isEmpty()) { if (currentFont != QFont()) { From a6f0f07782602ece7602f0c2d859ecfe9f3d97a0 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 26 Oct 2013 11:07:11 +0200 Subject: [PATCH 072/684] QMenu: use QSignalBlocker Change-Id: I41006d2b6f1454382b8c0bede20999d882b66f26 Reviewed-by: Olivier Goffart --- src/widgets/widgets/qmenu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 3a4fd449c8..d1b0da1a55 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -435,7 +435,7 @@ void QMenuPrivate::hideMenu(QMenu *menu) if (!menu) return; #if !defined(QT_NO_EFFECTS) - menu->blockSignals(true); + QSignalBlocker blocker(menu); aboutToHide = true; // Flash item which is about to trigger (if any). if (menu->style()->styleHint(QStyle::SH_Menu_FlashTriggeredItem) @@ -455,7 +455,7 @@ void QMenuPrivate::hideMenu(QMenu *menu) } aboutToHide = false; - menu->blockSignals(false); + blocker.unblock(); #endif // QT_NO_EFFECTS menu->close(); } From 94fd108ea42a99dacefa819bc3fd4363fb95e886 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 26 Oct 2013 11:07:46 +0200 Subject: [PATCH 073/684] QPlainTextEdit: use QSignalBlocker Change-Id: I581e60c4efd985fb909614459229806185f9501c Reviewed-by: Olivier Goffart --- src/widgets/widgets/qplaintextedit.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp index 90f2e47cd3..df86d141b4 100644 --- a/src/widgets/widgets/qplaintextedit.cpp +++ b/src/widgets/widgets/qplaintextedit.cpp @@ -639,9 +639,10 @@ void QPlainTextEditPrivate::setTopBlock(int blockNumber, int lineNumber, int dx) lineNumber = maxTopLine - block.firstLineNumber(); } - bool vbarSignalsBlocked = vbar->blockSignals(true); - vbar->setValue(newTopLine); - vbar->blockSignals(vbarSignalsBlocked); + { + const QSignalBlocker blocker(vbar); + vbar->setValue(newTopLine); + } if (!dx && blockNumber == control->topBlock && lineNumber == topLine) return; @@ -657,9 +658,10 @@ void QPlainTextEditPrivate::setTopBlock(int blockNumber, int lineNumber, int dx) control->topBlock = blockNumber; topLine = lineNumber; - bool vbarSignalsBlocked = vbar->blockSignals(true); - vbar->setValue(block.firstLineNumber() + lineNumber); - vbar->blockSignals(vbarSignalsBlocked); + { + const QSignalBlocker blocker(vbar); + vbar->setValue(block.firstLineNumber() + lineNumber); + } if (dx || dy) { viewport->scroll(q->isRightToLeft() ? -dx : dx, dy); @@ -1006,9 +1008,11 @@ void QPlainTextEditPrivate::_q_adjustScrollbars() QTextBlock firstVisibleBlock = q->firstVisibleBlock(); if (firstVisibleBlock.isValid()) visualTopLine = firstVisibleBlock.firstLineNumber() + topLine; - bool vbarSignalsBlocked = vbar->blockSignals(true); - vbar->setValue(visualTopLine); - vbar->blockSignals(vbarSignalsBlocked); + + { + const QSignalBlocker blocker(vbar); + vbar->setValue(visualTopLine); + } hbar->setRange(0, (int)documentSize.width() - viewport->width()); hbar->setPageStep(viewport->width()); From a9b6a78e54670a70b96c122b10ad7bd64d166514 Mon Sep 17 00:00:00 2001 From: David Faure Date: Mon, 24 Jun 2013 19:20:24 +0200 Subject: [PATCH 074/684] QThreadPool: fix race at time of thread expiry. The current synchronization mechanism was racy: decrementing waitingThreads and then hoping that the wakeOne will wake a thread before its expiry timeout happens. In other words, on timeout, a just-assigned task would never run. And then no other task would run, if maxThreadCount is reached. Fixed by using a queue of waiting threads (rather than just a count), and by moving the wait condition into the thread itself, so we know precisely which one we're waking up, and we can remove it from the set of waiting threads before waking it up, and therefore it can determine on wakeup whether it has work to do (caller removed it from the queue) or it expired (it's still in the queue). This is reliable, whereas the return value from QWaitCondition::wait isn't reliable, when the main thread has already decided that this thread has work to do. Task-number: QTBUG-3786 Change-Id: I1eac5d6c309daed7f483ac7a8074297bfda6ee32 Reviewed-by: Thiago Macieira --- src/corelib/thread/qthreadpool.cpp | 28 ++++++++----------- src/corelib/thread/qthreadpool_p.h | 3 +- .../thread/qthreadpool/tst_qthreadpool.cpp | 25 ++++++++++++++--- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp index fb1d1ee7cc..269f561a91 100644 --- a/src/corelib/thread/qthreadpool.cpp +++ b/src/corelib/thread/qthreadpool.cpp @@ -61,6 +61,7 @@ public: void run(); void registerThreadInactive(); + QWaitCondition runnableReady; QThreadPoolPrivate *manager; QRunnable *runnable; }; @@ -128,14 +129,13 @@ void QThreadPoolThread::run() // if too many threads are active, expire this thread bool expired = manager->tooManyThreadsActive(); if (!expired) { - ++manager->waitingThreads; + manager->waitingThreads.enqueue(this); registerThreadInactive(); // wait for work, exiting after the expiry timeout is reached - expired = !manager->runnableReady.wait(locker.mutex(), manager->expiryTimeout); + runnableReady.wait(locker.mutex(), manager->expiryTimeout); ++manager->activeThreads; - - if (expired) - --manager->waitingThreads; + if (manager->waitingThreads.removeOne(this)) + expired = true; } if (expired) { manager->expiredThreads.enqueue(this); @@ -160,7 +160,6 @@ QThreadPoolPrivate:: QThreadPoolPrivate() expiryTimeout(30000), maxThreadCount(qAbs(QThread::idealThreadCount())), reservedThreads(0), - waitingThreads(0), activeThreads(0) { } @@ -176,11 +175,10 @@ bool QThreadPoolPrivate::tryStart(QRunnable *task) if (activeThreadCount() >= maxThreadCount) return false; - if (waitingThreads > 0) { + if (waitingThreads.count() > 0) { // recycle an available thread - --waitingThreads; enqueueTask(task); - runnableReady.wakeOne(); + waitingThreads.takeFirst()->runnableReady.wakeOne(); return true; } @@ -225,7 +223,7 @@ int QThreadPoolPrivate::activeThreadCount() const { return (allThreads.count() - expiredThreads.count() - - waitingThreads + - waitingThreads.count() + reservedThreads); } @@ -266,7 +264,6 @@ void QThreadPoolPrivate::reset() { QMutexLocker locker(&mutex); isExiting = true; - runnableReady.wakeAll(); while (!allThreads.empty()) { // move the contents of the set out so that we can iterate without the lock @@ -275,6 +272,7 @@ void QThreadPoolPrivate::reset() locker.unlock(); foreach (QThreadPoolThread *thread, allThreadsCopy) { + thread->runnableReady.wakeAll(); thread->wait(); delete thread; } @@ -283,7 +281,7 @@ void QThreadPoolPrivate::reset() // repeat until all newly arrived threads have also completed } - waitingThreads = 0; + waitingThreads.clear(); expiredThreads.clear(); isExiting = false; @@ -459,10 +457,8 @@ void QThreadPool::start(QRunnable *runnable, int priority) if (!d->tryStart(runnable)) { d->enqueueTask(runnable, priority); - if (d->waitingThreads > 0) { - --d->waitingThreads; - d->runnableReady.wakeOne(); - } + if (!d->waitingThreads.isEmpty()) + d->waitingThreads.takeFirst()->runnableReady.wakeOne(); } } diff --git a/src/corelib/thread/qthreadpool_p.h b/src/corelib/thread/qthreadpool_p.h index ba77f7e57c..bd5f546fdb 100644 --- a/src/corelib/thread/qthreadpool_p.h +++ b/src/corelib/thread/qthreadpool_p.h @@ -87,8 +87,8 @@ public: void stealRunnable(QRunnable *); mutable QMutex mutex; - QWaitCondition runnableReady; QSet allThreads; + QQueue waitingThreads; QQueue expiredThreads; QList > queue; QWaitCondition noActiveThreads; @@ -97,7 +97,6 @@ public: int expiryTimeout; int maxThreadCount; int reservedThreads; - int waitingThreads; int activeThreads; }; diff --git a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp index 4a9932798c..f43149c3eb 100644 --- a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp +++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp @@ -80,6 +80,7 @@ private slots: void destruction(); void threadRecycling(); void expiryTimeout(); + void expiryTimeoutRace(); #ifndef QT_NO_EXCEPTIONS void exceptions(); #endif @@ -315,7 +316,7 @@ class ExpiryTimeoutTask : public QRunnable { public: QThread *thread; - int runCount; + QAtomicInt runCount; QSemaphore semaphore; ExpiryTimeoutTask() @@ -327,7 +328,7 @@ public: void run() { thread = QThread::currentThread(); - ++runCount; + runCount.ref(); semaphore.release(); } }; @@ -346,7 +347,7 @@ void tst_QThreadPool::expiryTimeout() // run the task threadPool.start(&task); QVERIFY(task.semaphore.tryAcquire(1, 10000)); - QCOMPARE(task.runCount, 1); + QCOMPARE(task.runCount.load(), 1); QVERIFY(!task.thread->wait(100)); // thread should expire QThread *firstThread = task.thread; @@ -355,7 +356,7 @@ void tst_QThreadPool::expiryTimeout() // run task again, thread should be restarted threadPool.start(&task); QVERIFY(task.semaphore.tryAcquire(1, 10000)); - QCOMPARE(task.runCount, 2); + QCOMPARE(task.runCount.load(), 2); QVERIFY(!task.thread->wait(100)); // thread should expire again QVERIFY(task.thread->wait(10000)); @@ -368,6 +369,22 @@ void tst_QThreadPool::expiryTimeout() QCOMPARE(threadPool.expiryTimeout(), expiryTimeout); } +void tst_QThreadPool::expiryTimeoutRace() // QTBUG-3786 +{ + ExpiryTimeoutTask task; + + QThreadPool threadPool; + threadPool.setMaxThreadCount(1); + threadPool.setExpiryTimeout(50); + const int numTasks = 20; + for (int i = 0; i < numTasks; ++i) { + threadPool.start(&task); + QThread::msleep(50); // exactly the same as the expiry timeout + } + QCOMPARE(task.runCount.load(), numTasks); + QVERIFY(threadPool.waitForDone(2000)); +} + #ifndef QT_NO_EXCEPTIONS class ExceptionTask : public QRunnable { From 4f563f6beec488ee03a1b4bc53df350c50103805 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Thu, 31 Oct 2013 15:09:39 +0100 Subject: [PATCH 075/684] Avoid adding empty arguments QByteArray split does create one item even if the string is empty. Hence check if the launch arguments string needs to be parsed at all. Change-Id: I0a355212aaa7254fe0f417c61a59c30223311915 Reviewed-by: Friedemann Kleint --- src/winmain/qtmain_winrt.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/winmain/qtmain_winrt.cpp b/src/winmain/qtmain_winrt.cpp index c0542ff242..8ad5f56bee 100644 --- a/src/winmain/qtmain_winrt.cpp +++ b/src/winmain/qtmain_winrt.cpp @@ -115,11 +115,13 @@ private: m_argv.resize(m_argc); HSTRING arguments; launchArgs->get_Arguments(&arguments); - foreach (const QByteArray &arg, QString::fromWCharArray( - WindowsGetStringRawBuffer(arguments, nullptr)).toLocal8Bit().split(' ')) { - m_argv.append(qstrdup(arg.constData())); - if (arg == "-qdebug") - m_debugWait = true; + if (arguments) { + foreach (const QByteArray &arg, QString::fromWCharArray( + WindowsGetStringRawBuffer(arguments, nullptr)).toLocal8Bit().split(' ')) { + m_argv.append(qstrdup(arg.constData())); + if (arg == "-qdebug") + m_debugWait = true; + } } } return S_OK; From 4058b284942891478a3b73f012b7c98255240e87 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Thu, 31 Oct 2013 15:11:03 +0100 Subject: [PATCH 076/684] Ignore debugger arguments on WinRT Visual Studio debuggers send an argument to specify the debugger port. This argument needs to be skipped while parsing and not to be interpreted as an option or test function. Change-Id: I24efb52fbd668a7bc3388c876f5ea0d950de1d5b Reviewed-by: Friedemann Kleint --- src/testlib/qtestcase.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 260ace642e..f3dee047c1 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -1540,6 +1540,10 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml) } else if (strcmp(argv[i], "-vb") == 0) { QBenchmarkGlobalData::current->verboseOutput = true; +#ifdef Q_OS_WINRT + } else if (strncmp(argv[i], "-ServerName:", 12) == 0) { + continue; +#endif } else if (argv[i][0] == '-') { fprintf(stderr, "Unknown option: '%s'\n\n%s", argv[i], testOptions); if (qml) { From 8120083436d4ba2aaf8fbcd422f7e046e6e5e40f Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Fri, 18 Oct 2013 09:26:52 +0300 Subject: [PATCH 077/684] Replace use of putenv in test case This should be using qputenv; putenv is deprecated on MSVC. Change-Id: I7c27cf5f7955624fa3553b7a34ab11c6fae462b8 Reviewed-by: Oliver Wolff --- tests/auto/corelib/codecs/qtextcodec/echo/main.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/auto/corelib/codecs/qtextcodec/echo/main.cpp b/tests/auto/corelib/codecs/qtextcodec/echo/main.cpp index 55c831bd35..09c3ac3c09 100644 --- a/tests/auto/corelib/codecs/qtextcodec/echo/main.cpp +++ b/tests/auto/corelib/codecs/qtextcodec/echo/main.cpp @@ -47,8 +47,7 @@ int main(int argc, char **argv) { - static char lc_all[] = "LC_ALL=C"; - putenv(lc_all); + qputenv("LC_ALL", "C"); QCoreApplication app(argc, argv); QString string(QChar(0x410)); From 04d1da1c1b4d834326a961371f9b34f3fbe9eaa4 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Tue, 15 Oct 2013 23:27:32 +0300 Subject: [PATCH 078/684] Fix QTimeZone test compilation on WinRT WinRT doesn't use the Windows Timezone backend, so don't build the Windows test. Change-Id: I32620546de3ad1f19402cc1359f8038200c915ec Reviewed-by: Oliver Wolff --- tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp index ed08bcefbf..28245b5e6a 100644 --- a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp +++ b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp @@ -746,7 +746,7 @@ void tst_QTimeZone::macTest() void tst_QTimeZone::winTest() { -#if defined(QT_BUILD_INTERNAL) && defined(Q_OS_WIN) +#if defined(QT_BUILD_INTERNAL) && defined(Q_OS_WIN) && !defined(Q_OS_WINRT) // Known datetimes qint64 std = QDateTime(QDate(2012, 1, 1), QTime(0, 0, 0), Qt::UTC).toMSecsSinceEpoch(); qint64 dst = QDateTime(QDate(2012, 6, 1), QTime(0, 0, 0), Qt::UTC).toMSecsSinceEpoch(); From fac56f3866a9f7a6047be64b40b3e1a6172bc5eb Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Tue, 15 Oct 2013 23:04:26 +0300 Subject: [PATCH 079/684] WinRT: Remove Windows metadata flags from common mkspec Winmd is not used, so there is no reason to embed it. Change-Id: I0820256aecd9c3c71b0b0c8afa53941b03f97363 Reviewed-by: Oliver Wolff --- mkspecs/common/winrt_winphone/qmake.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mkspecs/common/winrt_winphone/qmake.conf b/mkspecs/common/winrt_winphone/qmake.conf index 39b5ddc0c4..6d2aa39b87 100644 --- a/mkspecs/common/winrt_winphone/qmake.conf +++ b/mkspecs/common/winrt_winphone/qmake.conf @@ -68,8 +68,8 @@ QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO = /DEBUG /OPT:REF QMAKE_LFLAGS_DEBUG = /DEBUG QMAKE_LFLAGS_CONSOLE = /SUBSYSTEM:CONSOLE QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS -QMAKE_LFLAGS_EXE = /WINMD /MANIFEST:NO -QMAKE_LFLAGS_DLL = /WINMD /MANIFEST:NO /DLL /WINMDFILE:$(DESTDIR_TARGET).winmd +QMAKE_LFLAGS_EXE = /MANIFEST:NO +QMAKE_LFLAGS_DLL = /MANIFEST:NO /DLL QMAKE_LFLAGS_LTCG = /LTCG QMAKE_EXTENSION_STATICLIB = lib From af0409d336e07c61734777117f79906e0e82cd95 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Mon, 4 Nov 2013 12:59:40 +0200 Subject: [PATCH 080/684] WinRT compatibility functions: properly return ERANGE from getenv ...when the buffer's size is smaller than the value size. Change-Id: Id345982c9fc4ceed6505d0c192680c47c554fcb4 Reviewed-by: Oliver Wolff --- src/corelib/kernel/qfunctions_winrt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/kernel/qfunctions_winrt.cpp b/src/corelib/kernel/qfunctions_winrt.cpp index f4a278dc43..1348af2acb 100644 --- a/src/corelib/kernel/qfunctions_winrt.cpp +++ b/src/corelib/kernel/qfunctions_winrt.cpp @@ -71,7 +71,7 @@ errno_t qt_winrt_getenv_s(size_t* sizeNeeded, char* buffer, size_t bufferSize, c if (bufferSize < (size_t)value.size()) { *sizeNeeded = value.size(); - return 0; + return ERANGE; } strcpy(buffer, value.constData()); From 2ff0746e97acf37600b104838c96468f00953737 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Fri, 1 Nov 2013 16:16:15 +0100 Subject: [PATCH 081/684] Refactor plugin loading for WinRT Specify the root directory to be the package root. Only plugins inside the root can be opened (actually also only files). Furthermore current defaults to the package root now, which in most cases is identical to previous behavior. When attempting to load a plugin the path can either be specified in host format "C:/..." or as plugin absolute "/platforms/...". Check for both, with preference of latter case, like when qt.conf is used with / being used as plugin path. Change-Id: I7e3da293362488b62a3357c4882ebf5e048dcf95 Reviewed-by: Friedemann Kleint Reviewed-by: Andrew Knight Reviewed-by: Oliver Wolff --- src/corelib/io/qdir.cpp | 2 +- src/corelib/io/qfilesystemengine_win.cpp | 30 ++++++++++++++++++++++++ src/corelib/io/qfilesystementry.cpp | 6 +++++ src/corelib/kernel/qcoreapplication.cpp | 4 ++++ src/corelib/plugin/qlibrary_win.cpp | 6 ++++- 5 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index 148ae5b202..bb2b2e99f3 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -2141,7 +2141,7 @@ QString QDir::cleanPath(const QString &path) name.replace(dir_separator, QLatin1Char('/')); bool allowUncPaths = false; -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) //allow unc paths +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) //allow unc paths allowUncPaths = true; #endif diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index 77304b2cb9..896a232299 100644 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -77,11 +77,13 @@ # include # include # include +# include using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::Windows::Foundation; using namespace ABI::Windows::Storage; +using namespace ABI::Windows::ApplicationModel; #endif // Q_OS_WINRT #ifndef SPI_GETPLATFORMTYPE @@ -1180,6 +1182,30 @@ QString QFileSystemEngine::rootPath() { #if defined(Q_OS_WINCE) QString ret = QLatin1String("/"); +#elif defined(Q_OS_WINRT) + // We specify the package root as root directory + QString ret = QLatin1String("/"); + // Get package location + ComPtr statics; + if (FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_Package).Get(), &statics))) + return ret; + ComPtr package; + if (FAILED(statics->get_Current(&package))) + return ret; + ComPtr installedLocation; + if (FAILED(package->get_InstalledLocation(&installedLocation))) + return ret; + + ComPtr item; + if (FAILED(installedLocation.As(&item))) + return ret; + + HSTRING finalWinPath; + if (FAILED(item->get_Path(&finalWinPath))) + return ret; + + ret = QDir::fromNativeSeparators(QString::fromWCharArray(WindowsGetStringRawBuffer(finalWinPath, nullptr))); + #else QString ret = QString::fromLatin1(qgetenv("SystemDrive").constData()); if (ret.isEmpty()) @@ -1329,7 +1355,11 @@ QFileSystemEntry QFileSystemEngine::currentPath() #else // !Q_OS_WINCE && !Q_OS_WINRT //TODO - a race condition exists when using currentPath / setCurrentPath from multiple threads if (qfsPrivateCurrentDir.isEmpty()) +#ifndef Q_OS_WINRT qfsPrivateCurrentDir = QCoreApplication::applicationDirPath(); +#else + qfsPrivateCurrentDir = QDir::rootPath(); +#endif ret = qfsPrivateCurrentDir; #endif // Q_OS_WINCE || Q_OS_WINRT diff --git a/src/corelib/io/qfilesystementry.cpp b/src/corelib/io/qfilesystementry.cpp index 3934c6a673..42a724670e 100644 --- a/src/corelib/io/qfilesystementry.cpp +++ b/src/corelib/io/qfilesystementry.cpp @@ -169,6 +169,12 @@ void QFileSystemEntry::resolveNativeFilePath() const m_nativeFilePath = QDir::toNativeSeparators(m_filePath); #else m_nativeFilePath = QFile::encodeName(QDir::toNativeSeparators(m_filePath)); +#endif +#ifdef Q_OS_WINRT + while (m_nativeFilePath.startsWith(QLatin1Char('\\'))) + m_nativeFilePath.remove(0,1); + if (m_nativeFilePath.isEmpty()) + m_nativeFilePath.append(QLatin1Char('.')); #endif } } diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 2e70d40bd2..00e98a69bc 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -525,6 +525,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); diff --git a/src/corelib/plugin/qlibrary_win.cpp b/src/corelib/plugin/qlibrary_win.cpp index 928f2c5eb1..b9494a3041 100644 --- a/src/corelib/plugin/qlibrary_win.cpp +++ b/src/corelib/plugin/qlibrary_win.cpp @@ -107,12 +107,16 @@ bool QLibraryPrivate::load_sys() attempts.append(QFileInfo(fileName).absoluteFilePath()); #endif } +#ifdef Q_OS_WINRT + if (fileName.startsWith(QLatin1Char('/'))) + attempts.prepend(QDir::rootPath() + fileName); +#endif Q_FOREACH (const QString &attempt, attempts) { #ifndef Q_OS_WINRT pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16()); #else // Q_OS_WINRT - QString path = QDir::toNativeSeparators(QDir::current().relativeFilePath(fileName)); + QString path = QDir::toNativeSeparators(QDir::current().relativeFilePath(attempt)); pHnd = LoadPackagedLibrary((LPCWSTR)path.utf16(), 0); if (pHnd) qualifiedFileName = attempt; From 3604280b4103df44cbe561c1adcacf28d4ea96ab Mon Sep 17 00:00:00 2001 From: David Faure Date: Fri, 1 Nov 2013 10:06:50 +0100 Subject: [PATCH 082/684] QStandardPaths: Add GenericConfigLocation to the documentation The actual feature comes from a merge from the stable branch. Change-Id: Id067fb2b26cb3c6b78c7705b77bd741e3bd8f090 Reviewed-by: Thiago Macieira --- src/corelib/io/qstandardpaths.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp index b32f5ac576..5e2428527c 100644 --- a/src/corelib/io/qstandardpaths.cpp +++ b/src/corelib/io/qstandardpaths.cpp @@ -188,6 +188,9 @@ QT_BEGIN_NAMESPACE \row \li ConfigLocation \li "~/Library/Preferences" \li "C:/Users//AppData/Local/", "C:/ProgramData/" + \row \li GenericConfigLocation + \li "~/Library/Preferences" + \li "C:/Users//AppData/Local", "C:/ProgramData" \row \li DownloadLocation \li "~/Documents" \li "C:/Users//Documents" @@ -240,6 +243,9 @@ QT_BEGIN_NAMESPACE \row \li ConfigLocation \li "/data/Settings" \li "~/.config", "/etc/xdg" + \row \li GenericConfigLocation + \li "/data/Settings" + \li "~/.config", "/etc/xdg" \row \li DownloadLocation \li "/shared/downloads" \li "~/Downloads" From 1de459a6dddd1671164b171ff36d87b18f07b700 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 5 Nov 2013 15:26:55 +0100 Subject: [PATCH 083/684] use apartment threading for CoInitializeEx otherwise we are risking a lock by freeing resources from other threads when calling CoUnitialized() Change-Id: I1fe09d7d3b1674a00b44ababfc90da79580278b3 Reviewed-by: Friedemann Kleint --- src/corelib/kernel/qeventdispatcher_winrt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp index c94c69b90f..daef8428e1 100644 --- a/src/corelib/kernel/qeventdispatcher_winrt.cpp +++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp @@ -317,7 +317,7 @@ QEventDispatcherWinRTPrivate::QEventDispatcherWinRTPrivate() : interrupt(false) , timerFactory(0) { - CoInitializeEx(NULL, COINIT_MULTITHREADED); + 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); From 60dc35e4286074263f2d18a585ee270da55275ce Mon Sep 17 00:00:00 2001 From: Mandeep Sandhu Date: Thu, 17 Oct 2013 13:51:18 +0530 Subject: [PATCH 084/684] Examples: Add support for custom nameserver to dnslookup Updated dnslookup example to take an optional nameserver argument for doing DNS lookup against a specific nameserver. Task-number: QTBUG-30166 Change-Id: I9f46f9f766b56f770d2c8372e3bfad5c71023c73 Reviewed-by: Thiago Macieira --- examples/network/dnslookup/dnslookup.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/examples/network/dnslookup/dnslookup.cpp b/examples/network/dnslookup/dnslookup.cpp index 77e8abc927..202a5f9580 100644 --- a/examples/network/dnslookup/dnslookup.cpp +++ b/examples/network/dnslookup/dnslookup.cpp @@ -50,7 +50,7 @@ static void usage() { printf("Qt DNS example - performs DNS lookups\n" - "Usage: dnslookup [-t ] name\n\n"); + "Usage: dnslookup [-t ] [-s nameserver] name\n\n"); } DnsManager::DnsManager() @@ -93,6 +93,17 @@ void DnsManager::execute() return; } } + if (args.size() > 1 && args.first() == "-s") { + args.takeFirst(); + const QString ns = args.takeFirst(); + QHostAddress nameserver(ns); + if (nameserver.isNull() || nameserver.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) { + printf("Bad nameserver address: %s\n", qPrintable(ns)); + QCoreApplication::instance()->quit(); + return; + } + dns->setNameserver(nameserver); + } if (args.isEmpty()) { usage(); QCoreApplication::instance()->quit(); From 18bb8d6b16548c669f8dfe33a865f7f1cff80e1d Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Thu, 7 Nov 2013 09:50:44 +0100 Subject: [PATCH 085/684] compile fix if no QFileSystemWatcher is available Change-Id: I22d0cd90da96e6b6f651768955c7f445dfbcf6bc Reviewed-by: Friedemann Kleint Reviewed-by: Andrew Knight Reviewed-by: Oliver Wolff --- tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp index f2fa1f87fa..16bd4a6f7b 100644 --- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp @@ -2274,7 +2274,9 @@ Q_GLOBAL_STATIC(QLocale, tst_qapp_locale); #ifndef QT_NO_PROCESS Q_GLOBAL_STATIC(QProcess, tst_qapp_process); #endif +#ifndef QT_NO_FILESYSTEMWATCHER Q_GLOBAL_STATIC(QFileSystemWatcher, tst_qapp_fileSystemWatcher); +#endif #ifndef QT_NO_SHAREDMEMORY Q_GLOBAL_STATIC(QSharedMemory, tst_qapp_sharedMemory); #endif @@ -2297,7 +2299,9 @@ void tst_QApplication::globalStaticObjectDestruction() #ifndef QT_NO_PROCESS QVERIFY(tst_qapp_process()); #endif +#ifndef QT_NO_FILESYSTEMWATCHER QVERIFY(tst_qapp_fileSystemWatcher()); +#endif #ifndef QT_NO_SHAREDMEMORY QVERIFY(tst_qapp_sharedMemory()); #endif From 560d33ad0489aab17799ab5166ebadf9150d680a Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Thu, 7 Nov 2013 10:44:28 +0100 Subject: [PATCH 086/684] Introduce proper QSurfaceFormat's setters/testers for format options Fixes several things * setOption(options) has the wrong name (singular) * setOption(options) doesn't set the current options to the argument, but ORs the current options with the argument and sets the result * testOption(options) has the wrong name The old methods get deprecated, and new methods and overloads get introduced here. Old code behavior is thereby preserved. Change-Id: I51bba49f22810c80e6b4980892600d616503af6b Reviewed-by: Gunnar Sletta --- src/gui/kernel/qsurfaceformat.cpp | 75 +++++++++++++++++++++++++++++-- src/gui/kernel/qsurfaceformat.h | 9 +++- 2 files changed, 79 insertions(+), 5 deletions(-) diff --git a/src/gui/kernel/qsurfaceformat.cpp b/src/gui/kernel/qsurfaceformat.cpp index 2f1b30ae4a..ebfd71b4d3 100644 --- a/src/gui/kernel/qsurfaceformat.cpp +++ b/src/gui/kernel/qsurfaceformat.cpp @@ -311,9 +311,15 @@ void QSurfaceFormat::setSamples(int numSamples) } /*! - Sets the format option to \a opt. + \obsolete + \overload - \sa testOption() + Use setOption(QSurfaceFormat::FormatOption, bool) or setOptions() instead. + + Sets the format options to the OR combination of \a opt and the + current format options. + + \sa options(), testOption() */ void QSurfaceFormat::setOption(QSurfaceFormat::FormatOptions opt) { @@ -325,7 +331,13 @@ void QSurfaceFormat::setOption(QSurfaceFormat::FormatOptions opt) } /*! - Returns \c true if format option \a opt is set; otherwise returns \c false. + \obsolete + \overload + + Use testOption(QSurfaceFormat::FormatOption) instead. + + Returns \c true if any of the options in \a opt is currently set + on this object; otherwise returns false. \sa setOption() */ @@ -334,6 +346,63 @@ bool QSurfaceFormat::testOption(QSurfaceFormat::FormatOptions opt) const return d->opts & opt; } +/*! + \since 5.3 + + Sets the format options to \a options. + + \sa options(), testOption() +*/ +void QSurfaceFormat::setOptions(QSurfaceFormat::FormatOptions options) +{ + if (int(d->opts) != int(options)) { + detach(); + d->opts = options; + } +} + +/*! + \since 5.3 + + Sets the format option \a option if \a on is true; otherwise, clears the option. + + \sa setOptions(), options(), testOption() +*/ +void QSurfaceFormat::setOption(QSurfaceFormat::FormatOption option, bool on) +{ + if (testOption(option) == on) + return; + detach(); + if (on) + d->opts |= option; + else + d->opts &= ~option; +} + +/*! + \since 5.3 + + Returns true if the format option \a option is set; otherwise returns false. + + \sa options(), testOption() +*/ +bool QSurfaceFormat::testOption(QSurfaceFormat::FormatOption option) const +{ + return d->opts & option; +} + +/*! + \since 5.3 + + Returns the currently set format options. + + \sa setOption(), setOptions(), testOption() +*/ +QSurfaceFormat::FormatOptions QSurfaceFormat::options() const +{ + return d->opts; +} + /*! Set the minimum depth buffer size to \a size. diff --git a/src/gui/kernel/qsurfaceformat.h b/src/gui/kernel/qsurfaceformat.h index 7c3c846df3..d182aa9f13 100644 --- a/src/gui/kernel/qsurfaceformat.h +++ b/src/gui/kernel/qsurfaceformat.h @@ -127,8 +127,13 @@ public: bool stereo() const; void setStereo(bool enable); - void setOption(QSurfaceFormat::FormatOptions opt); - bool testOption(QSurfaceFormat::FormatOptions opt) const; + QT_DEPRECATED void setOption(QSurfaceFormat::FormatOptions opt); + QT_DEPRECATED bool testOption(QSurfaceFormat::FormatOptions opt) const; + + void setOptions(QSurfaceFormat::FormatOptions options); + void setOption(FormatOption option, bool on = true); + bool testOption(FormatOption option) const; + QSurfaceFormat::FormatOptions options() const; private: QSurfaceFormatPrivate *d; From 05345f2a55b00fa604a3224efadf0dcbc7412460 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Fri, 8 Nov 2013 08:21:33 +0100 Subject: [PATCH 087/684] Disable error message box on WinRT While exception handling methods are not available on WinRT, the debug mode ones are. This way we can suppress error dialogs from popping up like on desktop windows. Change-Id: Id6e9666af9274d373e7d46e3f9e44892a2bd0dbc Reviewed-by: Friedemann Kleint --- src/testlib/qtestcase.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index f3dee047c1..755720a98c 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -2175,13 +2175,15 @@ int QTest::qExec(QObject *testObject, int argc, char **argv) qtest_qParseArgs(argc, argv, false); -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) if (!noCrashHandler) { # ifndef Q_CC_MINGW _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG); # endif +# ifndef Q_OS_WINRT SetErrorMode(SetErrorMode(0) | SEM_NOGPFAULTERRORBOX); SetUnhandledExceptionFilter(windowsFaultHandler); +# endif } // !noCrashHandler #endif // Q_OS_WIN) && !Q_OS_WINCE && !Q_OS_WINRT From 4fb04b0bd7d93f54ddab13b2e6fd981413baad59 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 26 Oct 2013 11:04:52 +0200 Subject: [PATCH 088/684] QSocks5SocketEngine: use QSignalBlocker Change-Id: Ib30daf8d716401cf3e2c562dc3ab7924b026189d Reviewed-by: Richard J. Moore --- src/network/socket/qsocks5socketengine.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp index 6818ff6354..b62c4a6bef 100644 --- a/src/network/socket/qsocks5socketengine.cpp +++ b/src/network/socket/qsocks5socketengine.cpp @@ -735,9 +735,10 @@ void QSocks5SocketEnginePrivate::reauthenticate() proxyInfo.setPassword(auth.password()); data->authenticator = new QSocks5PasswordAuthenticator(proxyInfo.user(), proxyInfo.password()); - data->controlSocket->blockSignals(true); - data->controlSocket->abort(); - data->controlSocket->blockSignals(false); + { + const QSignalBlocker blocker(data->controlSocket); + data->controlSocket->abort(); + } data->controlSocket->connectToHost(proxyInfo.hostName(), proxyInfo.port()); } else { // authentication failure From 9fda89f97d666c732a592a5fc1f97a649b295718 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 4 Nov 2013 22:09:20 +0100 Subject: [PATCH 089/684] Make use of the internal space for enum in QVariant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enums are movable even if they have not been tagged as such, and therefore can safely make use of the internal storage. Change-Id: I3bec8556bfeb4a07cb30d918f8d1dd2565d6d94a Reviewed-by: Jędrzej Nowacki --- src/corelib/kernel/qvariant.cpp | 2 +- src/corelib/kernel/qvariant_p.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 5754af42ac..db3b96d202 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -841,7 +841,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 struct QVariantIntegrator { static const bool CanUseInternalSpace = sizeof(T) <= sizeof(QVariant::Private::Data) - && (!QTypeInfo::isStatic); + && ((!QTypeInfo::isStatic) || Q_IS_ENUM(T)); }; Q_STATIC_ASSERT(QVariantIntegrator::CanUseInternalSpace); Q_STATIC_ASSERT(QVariantIntegrator::CanUseInternalSpace); From a4446c299a9eab7e1844ca6b94823984c8e7d67b Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 25 Oct 2013 19:55:41 +0200 Subject: [PATCH 090/684] QComboBox: use QSignalBlocker Change-Id: If805652d05007de9206951f09499acf931990df2 Reviewed-by: Olivier Goffart --- src/widgets/widgets/qcombobox.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 37a14d3eb3..fd74ab7595 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -2608,9 +2608,9 @@ void QComboBox::hidePopup() Q_D(QComboBox); if (d->container && d->container->isVisible()) { #if !defined(QT_NO_EFFECTS) - d->model->blockSignals(true); - d->container->itemView()->blockSignals(true); - d->container->blockSignals(true); + QSignalBlocker modelBlocker(d->model); + QSignalBlocker viewBlocker(d->container->itemView()); + QSignalBlocker containerBlocker(d->container); // Flash selected/triggered item (if any). if (style()->styleHint(QStyle::SH_Menu_FlashTriggeredItem)) { QItemSelectionModel *selectionModel = view() ? view()->selectionModel() : 0; @@ -2646,9 +2646,9 @@ void QComboBox::hidePopup() #endif // Q_OS_MAC // Other platform implementations welcome :-) } - d->model->blockSignals(false); - d->container->itemView()->blockSignals(false); - d->container->blockSignals(false); + containerBlocker.unblock(); + viewBlocker.unblock(); + modelBlocker.unblock(); if (!didFade) #endif // QT_NO_EFFECTS From 459fb114818eaf6a209e80ff7d59ccefeee881e3 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 11 Nov 2013 14:52:11 +0100 Subject: [PATCH 091/684] uic: Accept an -include argument to generate a #include. Change-Id: I2854619ab995b4ba3c820fec58e998ad04ac9858 Reviewed-by: Friedemann Kleint --- src/tools/uic/cpp/cppwriteincludes.cpp | 3 ++ src/tools/uic/main.cpp | 6 +++ src/tools/uic/option.h | 1 + .../translation/Dialog_without_Buttons_tr.h | 50 ++++++++++++++++++ tests/auto/tools/uic/tst_uic.cpp | 52 +++++++++++++++++++ 5 files changed, 112 insertions(+) create mode 100644 tests/auto/tools/uic/baseline/translation/Dialog_without_Buttons_tr.h diff --git a/src/tools/uic/cpp/cppwriteincludes.cpp b/src/tools/uic/cpp/cppwriteincludes.cpp index c473566e3a..5b7403bf06 100644 --- a/src/tools/uic/cpp/cppwriteincludes.cpp +++ b/src/tools/uic/cpp/cppwriteincludes.cpp @@ -127,6 +127,9 @@ void WriteIncludes::acceptUI(DomUI *node) TreeWalker::acceptUI(node); + if (!m_uic->option().includeFile.isEmpty()) + m_globalIncludes.insert(m_uic->option().includeFile, true); + writeHeaders(m_globalIncludes, true); writeHeaders(m_localIncludes, false); diff --git a/src/tools/uic/main.cpp b/src/tools/uic/main.cpp index c29292a99b..cb2bd430ff 100644 --- a/src/tools/uic/main.cpp +++ b/src/tools/uic/main.cpp @@ -95,6 +95,11 @@ int runUic(int argc, char *argv[]) translateOption.setValueName(QStringLiteral("function")); parser.addOption(translateOption); + QCommandLineOption includeOption(QStringList() << QStringLiteral("include")); + includeOption.setDescription(QStringLiteral("Add #include to .")); + includeOption.setValueName(QStringLiteral("include-file")); + parser.addOption(includeOption); + QCommandLineOption generatorOption(QStringList() << QStringLiteral("g") << QStringLiteral("generator")); generatorOption.setDescription(QStringLiteral("Select generator.")); generatorOption.setValueName(QStringLiteral("java|cpp")); @@ -110,6 +115,7 @@ int runUic(int argc, char *argv[]) driver.option().implicitIncludes = !parser.isSet(noImplicitIncludesOption); driver.option().postfix = parser.value(postfixOption); driver.option().translateFunction = parser.value(translateOption); + driver.option().includeFile = parser.value(includeOption); driver.option().generator = (parser.value(generatorOption).toLower() == QLatin1String("java")) ? Option::JavaGenerator : Option::CppGenerator; QString inputFile; diff --git a/src/tools/uic/option.h b/src/tools/uic/option.h index 14ed422d63..52dc731057 100644 --- a/src/tools/uic/option.h +++ b/src/tools/uic/option.h @@ -73,6 +73,7 @@ struct Option QString prefix; QString postfix; QString translateFunction; + QString includeFile; #ifdef QT_UIC_JAVA_GENERATOR QString javaPackage; QString javaOutputDirectory; diff --git a/tests/auto/tools/uic/baseline/translation/Dialog_without_Buttons_tr.h b/tests/auto/tools/uic/baseline/translation/Dialog_without_Buttons_tr.h new file mode 100644 index 0000000000..597728e207 --- /dev/null +++ b/tests/auto/tools/uic/baseline/translation/Dialog_without_Buttons_tr.h @@ -0,0 +1,50 @@ +/******************************************************************************** +** Form generated from reading UI file 'Dialog_without_Buttons.ui' +** +** Created by: Qt User Interface Compiler version 5.3.0 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef DIALOG_WITHOUT_BUTTONS_TR_H +#define DIALOG_WITHOUT_BUTTONS_TR_H + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_Dialog +{ +public: + + void setupUi(QDialog *Dialog) + { + if (Dialog->objectName().isEmpty()) + Dialog->setObjectName(QStringLiteral("Dialog")); + Dialog->resize(400, 300); + + retranslateUi(Dialog); + + QMetaObject::connectSlotsByName(Dialog); + } // setupUi + + void retranslateUi(QDialog *Dialog) + { + Dialog->setWindowTitle(i18n("Dialog", 0)); + } // retranslateUi + +}; + +namespace Ui { + class Dialog: public Ui_Dialog {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // DIALOG_WITHOUT_BUTTONS_TR_H diff --git a/tests/auto/tools/uic/tst_uic.cpp b/tests/auto/tools/uic/tst_uic.cpp index c6e8466d89..02a19c0c33 100644 --- a/tests/auto/tools/uic/tst_uic.cpp +++ b/tests/auto/tools/uic/tst_uic.cpp @@ -64,9 +64,13 @@ private Q_SLOTS: void run(); void run_data() const; + void runTranslation(); + void compare(); void compare_data() const; + void runCompare(); + private: const QString m_command; QString m_baseline; @@ -220,5 +224,53 @@ void tst_uic::compare_data() const } } +void tst_uic::runTranslation() +{ + QProcess process; + + QDir baseline(m_baseline); + + QDir generated(m_generated.path()); + generated.mkdir(QLatin1String("translation")); + QString generatedFile = generated.absolutePath() + QLatin1String("/translation/Dialog_without_Buttons_tr.h"); + + process.start(m_command, QStringList(baseline.filePath("Dialog_without_Buttons.ui")) + << QString(QLatin1String("-tr")) << "i18n" + << QString(QLatin1String("-include")) << "ki18n.h" + << QString(QLatin1String("-o")) << generatedFile); + QVERIFY2(process.waitForStarted(), msgProcessStartFailed(m_command, process.errorString())); + QVERIFY(process.waitForFinished()); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); + QCOMPARE(QFileInfo(generatedFile).exists(), true); +} + + +void tst_uic::runCompare() +{ + QFile orgFile(m_baseline + QLatin1String("/translation/Dialog_without_Buttons_tr.h")); + + QDir generated(m_generated.path()); + QFile genFile(generated.absolutePath() + QLatin1String("/translation/Dialog_without_Buttons_tr.h")); + + if (!orgFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + QString err(QLatin1String("Could not read file: %1...")); + QFAIL(err.arg(orgFile.fileName()).toUtf8()); + } + + if (!genFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + QString err(QLatin1String("Could not read file: %1...")); + QFAIL(err.arg(genFile.fileName()).toUtf8()); + } + + QString originalFile = orgFile.readAll(); + originalFile.replace(QRegExp(QLatin1String("Created by: Qt User Interface Compiler version [.\\d]{5,5}")), ""); + + QString generatedFile = genFile.readAll(); + generatedFile.replace(QRegExp(QLatin1String("Created by: Qt User Interface Compiler version [.\\d]{5,5}")), ""); + + QCOMPARE(generatedFile, originalFile); +} + QTEST_MAIN(tst_uic) #include "tst_uic.moc" From 0de83705316d82273e0d445119ab1d4ee1c2f980 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Mon, 11 Nov 2013 15:37:49 +0100 Subject: [PATCH 092/684] Enable qfile tests for platforms without network Currently network is only required to gather the host info for one test case. That does not justify to disable all other tests, which can provide useful information on the state when doing a port. Hence disable that testcase if no network is available. Change-Id: I202ef49b3e07ae69ec85ee0432ae0a771a90e816 Reviewed-by: Friedemann Kleint --- tests/auto/corelib/io/io.pro | 1 - tests/auto/corelib/io/qfile/test/test.pro | 5 ++++- tests/auto/corelib/io/qfile/tst_qfile.cpp | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/auto/corelib/io/io.pro b/tests/auto/corelib/io/io.pro index 11815c6160..259463f976 100644 --- a/tests/auto/corelib/io/io.pro +++ b/tests/auto/corelib/io/io.pro @@ -43,7 +43,6 @@ SUBDIRS=\ qsettings !qtHaveModule(network): SUBDIRS -= \ - qfile \ qiodevice \ qprocess \ qtextstream diff --git a/tests/auto/corelib/io/qfile/test/test.pro b/tests/auto/corelib/io/qfile/test/test.pro index e282bd091c..03863e9943 100644 --- a/tests/auto/corelib/io/qfile/test/test.pro +++ b/tests/auto/corelib/io/qfile/test/test.pro @@ -1,7 +1,10 @@ CONFIG += testcase CONFIG += parallel_test CONFIG -= app_bundle debug_and_release_target -QT = core-private core network testlib +QT = core-private core testlib +qtHaveModule(network): QT += network +else: DEFINES += QT_NO_NETWORK + TARGET = ../tst_qfile SOURCES = ../tst_qfile.cpp wince*: SOURCES += $$QT_SOURCE_TREE/src/corelib/kernel/qfunctions_wince.cpp diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp index 78cb27ee30..77ac4bcd86 100644 --- a/tests/auto/corelib/io/qfile/tst_qfile.cpp +++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp @@ -59,7 +59,7 @@ extern Q_CORE_EXPORT int qt_ntfs_permission_lookup; QT_END_NAMESPACE #endif -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(QT_NO_NETWORK) #include #endif #include @@ -2245,7 +2245,7 @@ void tst_QFile::writeLargeDataBlock_data() QTest::newRow("localfile-Fd") << "./largeblockfile.txt" << (int)OpenFd; QTest::newRow("localfile-Stream") << "./largeblockfile.txt" << (int)OpenStream; -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(QT_NO_NETWORK) // Some semi-randomness to avoid collisions. QTest::newRow("unc file") << QString("//" + QtNetworkSettings::winServerName() + "/TESTSHAREWRITABLE/largefile-%1-%2.txt") From f7f9126ed7d2fcf7a995409d0b8bbeab766d1c14 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 12 Nov 2013 09:54:53 +0100 Subject: [PATCH 093/684] change to basic file info on WinRT FILE_FULL_DIR_INFO failed under certain circumstances on WinRT and provides far more information than required. Hence prefer the basic version in every case and standard for files with size description. Change-Id: I63f1365f83cdd5d69f81278411f822dbd361fa92 Reviewed-by: Oliver Wolff --- src/corelib/io/qfilesystemengine_win.cpp | 27 ++++++++++++++---------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index 896a232299..46b2f041c1 100644 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -956,17 +956,22 @@ bool QFileSystemEngine::fillMetaData(HANDLE fHandle, QFileSystemMetaData &data, } SetErrorMode(oldmode); #else // !Q_OS_WINRT - FILE_FULL_DIR_INFO fileInfo; - if (GetFileInformationByHandleEx(fHandle, FileFullDirectoryInfo, &fileInfo, sizeof(fileInfo))) { - data.fillFromFileAttribute(fileInfo.FileAttributes); - data.creationTime_.dwHighDateTime = fileInfo.CreationTime.HighPart; - data.creationTime_.dwLowDateTime = fileInfo.CreationTime.LowPart; - data.lastAccessTime_.dwHighDateTime = fileInfo.LastAccessTime.HighPart; - data.lastAccessTime_.dwLowDateTime = fileInfo.LastAccessTime.LowPart; - data.lastWriteTime_.dwHighDateTime = fileInfo.LastWriteTime.HighPart; - data.lastWriteTime_.dwLowDateTime = fileInfo.LastWriteTime.LowPart; - data.fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY ? data.size_ = 0 : data.size_ = fileInfo.AllocationSize.QuadPart; - data.knownFlagsMask |= data.Times | data.SizeAttribute; + FILE_BASIC_INFO fileBasicInfo; + if (GetFileInformationByHandleEx(fHandle, FileBasicInfo, &fileBasicInfo, sizeof(fileBasicInfo))) { + data.fillFromFileAttribute(fileBasicInfo.FileAttributes); + data.creationTime_.dwHighDateTime = fileBasicInfo.CreationTime.HighPart; + data.creationTime_.dwLowDateTime = fileBasicInfo.CreationTime.LowPart; + data.lastAccessTime_.dwHighDateTime = fileBasicInfo.LastAccessTime.HighPart; + data.lastAccessTime_.dwLowDateTime = fileBasicInfo.LastAccessTime.LowPart; + data.lastWriteTime_.dwHighDateTime = fileBasicInfo.LastWriteTime.HighPart; + data.lastWriteTime_.dwLowDateTime = fileBasicInfo.LastWriteTime.LowPart; + if (!(data.fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY)) { + FILE_STANDARD_INFO fileStandardInfo; + if (GetFileInformationByHandleEx(fHandle, FileStandardInfo, &fileStandardInfo, sizeof(fileStandardInfo))) + data.size_ = fileStandardInfo.EndOfFile.QuadPart; + } else + data.size_ = 0; + data.knownFlagsMask |= QFileSystemMetaData::Times | QFileSystemMetaData::SizeAttribute; } #endif // Q_OS_WINRT return data.hasFlags(what); From 7ea584f8304ddc302315ca207e88db45ec443d20 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 12 Nov 2013 11:52:11 +0100 Subject: [PATCH 094/684] fix directory separators for WinRT internally we always use forward slashes Change-Id: I0573d63b993bb76bc5798ee060fe9bdfb7304658 Reviewed-by: Oliver Wolff --- src/corelib/io/qfilesystemengine_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index 46b2f041c1..dbc6d28846 100644 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -1308,7 +1308,7 @@ QString QFileSystemEngine::tempPath() HSTRING path; if (FAILED(tempFolderItem->get_Path(&path))) return ret; - ret = QString::fromWCharArray(WindowsGetStringRawBuffer(path, nullptr)); + ret = QDir::fromNativeSeparators(QString::fromWCharArray(WindowsGetStringRawBuffer(path, nullptr))); #endif // Q_OS_WINRT if (ret.isEmpty()) { #if !defined(Q_OS_WINCE) From c784ec00faf022476c10fc622ca43f4c68d544e1 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 12 Nov 2013 11:48:52 +0100 Subject: [PATCH 095/684] WinRT: implement QStandardPaths need to leave some items out like media folder access, as this is not available by default and also requires certain capabilities to use those. Furthermore updated the tests for sandboxing as well as skip cmd.exe related tests as that does not exist on WinRT. Change-Id: I992b1e195b79615bea0be4f84f56cfb8f0d902bf Reviewed-by: Oliver Wolff --- src/corelib/io/qstandardpaths_winrt.cpp | 59 ++++++++++++++++++- .../io/qstandardpaths/tst_qstandardpaths.cpp | 6 +- 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/src/corelib/io/qstandardpaths_winrt.cpp b/src/corelib/io/qstandardpaths_winrt.cpp index 55a801332e..9b6a088a30 100644 --- a/src/corelib/io/qstandardpaths_winrt.cpp +++ b/src/corelib/io/qstandardpaths_winrt.cpp @@ -48,6 +48,17 @@ #include +#include +#include +#include +#include + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Storage; +using namespace ABI::Windows::ApplicationModel; + #ifndef QT_NO_STANDARDPATHS QT_BEGIN_NAMESPACE @@ -59,9 +70,51 @@ static QString convertCharArray(const wchar_t *path) QString QStandardPaths::writableLocation(StandardLocation type) { - Q_UNUSED(type) - Q_UNIMPLEMENTED(); - return QString(); + QString result; + + switch (type) { + case ConfigLocation: // same as DataLocation, on Windows + case DataLocation: + case GenericDataLocation: { + ComPtr applicationDataStatics; + if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_ApplicationData).Get(), &applicationDataStatics))) + break; + ComPtr applicationData; + if (FAILED(applicationDataStatics->get_Current(&applicationData))) + break; + ComPtr settingsFolder; + if (FAILED(applicationData->get_LocalFolder(&settingsFolder))) + break; + ComPtr settingsFolderItem; + if (FAILED(settingsFolder.As(&settingsFolderItem))) + break; + HSTRING path; + if (FAILED(settingsFolderItem->get_Path(&path))) + break; + result = convertCharArray(WindowsGetStringRawBuffer(path, nullptr)); + if (isTestModeEnabled()) + result += QLatin1String("/qttest"); + break; + } + case CacheLocation: + return writableLocation(DataLocation) + QLatin1String("/cache"); + + case GenericCacheLocation: + return writableLocation(GenericDataLocation) + QLatin1String("/cache"); + + case RuntimeLocation: + case HomeLocation: + result = QDir::homePath(); + break; + + case TempLocation: + result = QDir::tempPath(); + break; + default: + Q_UNIMPLEMENTED(); + } + return result; + } QStringList QStandardPaths::standardLocations(StandardLocation type) diff --git a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp index 9ac1526f07..c3a1ad206d 100644 --- a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp +++ b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp @@ -283,9 +283,9 @@ void tst_qstandardpaths::testDataLocation() { // On all platforms, DataLocation should be GenericDataLocation / organization name / app name // This allows one app to access the data of another app. - // Blackberry OS is an exception to this case, owing to the fact that + // Blackberry OS and WinRT are an exception to this case, owing to the fact that // applications are sandboxed. -#ifndef Q_OS_BLACKBERRY +#if !defined(Q_OS_BLACKBERRY) && !defined(Q_OS_WINRT) const QString base = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::DataLocation), base + "/tst_qstandardpaths"); QCoreApplication::instance()->setOrganizationName("Qt"); @@ -329,6 +329,7 @@ void tst_qstandardpaths::testFindExecutable_data() QTest::addColumn("needle"); QTest::addColumn("expected"); #ifdef Q_OS_WIN +# ifndef Q_OS_WINRT const QFileInfo cmdFi = QFileInfo(QDir::cleanPath(QString::fromLocal8Bit(qgetenv("COMSPEC")))); const QString cmdPath = cmdFi.absoluteFilePath(); @@ -352,6 +353,7 @@ void tst_qstandardpaths::testFindExecutable_data() QTest::newRow("win8-logo-nosuffix") << QString() << logo << logoPath; } +# endif // Q_OS_WINRT #else const QFileInfo shFi = findSh(); Q_ASSERT(shFi.exists()); From 5dd94b75e37930e9941aaea06497d7e41c9c921f Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 6 Nov 2013 16:00:23 +0100 Subject: [PATCH 096/684] Add swapInterval to QSurfaceFormat Implement swap interval support for EGL, GLX and WGL. The environment variable QT_QPA_EGLFS_SWAPINTERVAL is renamed to QT_QPA_EGL_SWAPINTERVAL and can be used to override the applications' setting of the swap interval. Task-number: QTBUG-31939 Change-Id: I644325d5d3306b7604bffd7efccda3c00ed37d36 Reviewed-by: Friedemann Kleint Reviewed-by: Giuseppe D'Angelo Reviewed-by: Gunnar Sletta --- dist/changes-5.3.0 | 4 ++ src/gui/kernel/qsurfaceformat.cpp | 49 ++++++++++++++++++- src/gui/kernel/qsurfaceformat.h | 3 ++ .../eglconvenience/qeglconvenience.cpp | 1 + .../eglconvenience/qeglplatformcontext.cpp | 24 +++++++++ .../eglconvenience/qeglplatformcontext_p.h | 3 ++ src/plugins/platforms/eglfs/qeglfscontext.cpp | 20 +------- src/plugins/platforms/eglfs/qeglfscontext.h | 3 -- src/plugins/platforms/eglfs/qeglfswindow.cpp | 2 +- .../platforms/windows/qwindowsglcontext.cpp | 26 +++++++--- .../platforms/windows/qwindowsglcontext.h | 6 +-- src/plugins/platforms/xcb/qglxintegration.cpp | 38 ++++++++++++-- src/plugins/platforms/xcb/qglxintegration.h | 1 + src/plugins/platforms/xcb/qxcbwindow.cpp | 2 +- 14 files changed, 144 insertions(+), 38 deletions(-) diff --git a/dist/changes-5.3.0 b/dist/changes-5.3.0 index 035d0656ed..7bcab28032 100644 --- a/dist/changes-5.3.0 +++ b/dist/changes-5.3.0 @@ -29,3 +29,7 @@ QtCore QtGui ----- + +- Added setSwapInterval() to QSurfaceFormat. Platforms that support + setting the swap interval are now defaulting to the value of 1, + meaning vsync is enabled. diff --git a/src/gui/kernel/qsurfaceformat.cpp b/src/gui/kernel/qsurfaceformat.cpp index ebfd71b4d3..b8fe55adc0 100644 --- a/src/gui/kernel/qsurfaceformat.cpp +++ b/src/gui/kernel/qsurfaceformat.cpp @@ -72,6 +72,7 @@ public: , profile(QSurfaceFormat::NoProfile) , major(2) , minor(0) + , swapInterval(1) // default to vsync { } @@ -89,7 +90,8 @@ public: renderableType(other->renderableType), profile(other->profile), major(other->major), - minor(other->minor) + minor(other->minor), + swapInterval(other->swapInterval) { } @@ -107,6 +109,7 @@ public: QSurfaceFormat::OpenGLContextProfile profile; int major; int minor; + int swapInterval; }; /*! @@ -675,6 +678,46 @@ void QSurfaceFormat::setVersion(int major, int minor) } } +/*! + Sets the preferred swap interval. The swap interval specifies the + minimum number of video frames that are displayed before a buffer + swap occurs. This can be used to sync the GL drawing into a window + to the vertical refresh of the screen. + + Setting an \a interval value of 0 will turn the vertical refresh + syncing off, any value higher than 0 will turn the vertical + syncing on. Setting \a interval to a higher value, for example 10, + results in having 10 vertical retraces between every buffer swap. + + The default interval is 1. + + Changing the swap interval may not be supported by the underlying + platform. In this case, the request will be silently ignored. + + \since 5.3 + + \sa swapInterval() + */ +void QSurfaceFormat::setSwapInterval(int interval) +{ + if (d->swapInterval != interval) { + detach(); + d->swapInterval = interval; + } +} + +/*! + Returns the swap interval. + + \since 5.3 + + \sa setSwapInterval() +*/ +int QSurfaceFormat::swapInterval() const +{ + return d->swapInterval; +} + /*! Returns \c true if all the options of the two QSurfaceFormat objects \a a and \a b are equal. @@ -694,7 +737,8 @@ bool operator==(const QSurfaceFormat& a, const QSurfaceFormat& b) && a.d->swapBehavior == b.d->swapBehavior && a.d->profile == b.d->profile && a.d->major == b.d->major - && a.d->minor == b.d->minor); + && a.d->minor == b.d->minor + && a.d->swapInterval == b.d->swapInterval); } /*! @@ -724,6 +768,7 @@ QDebug operator<<(QDebug dbg, const QSurfaceFormat &f) << ", stencilBufferSize " << d->stencilSize << ", samples " << d->numSamples << ", swapBehavior " << d->swapBehavior + << ", swapInterval " << d->swapInterval << ", profile " << d->profile << ')'; diff --git a/src/gui/kernel/qsurfaceformat.h b/src/gui/kernel/qsurfaceformat.h index d182aa9f13..453beac5cd 100644 --- a/src/gui/kernel/qsurfaceformat.h +++ b/src/gui/kernel/qsurfaceformat.h @@ -135,6 +135,9 @@ public: bool testOption(FormatOption option) const; QSurfaceFormat::FormatOptions options() const; + int swapInterval() const; + void setSwapInterval(int interval); + private: QSurfaceFormatPrivate *d; diff --git a/src/platformsupport/eglconvenience/qeglconvenience.cpp b/src/platformsupport/eglconvenience/qeglconvenience.cpp index b711a2aebd..50baf6f06d 100644 --- a/src/platformsupport/eglconvenience/qeglconvenience.cpp +++ b/src/platformsupport/eglconvenience/qeglconvenience.cpp @@ -350,6 +350,7 @@ QSurfaceFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config, format.setStencilBufferSize(stencilSize); format.setSamples(sampleCount); format.setStereo(false); // EGL doesn't support stereo buffers + format.setSwapInterval(referenceFormat.swapInterval()); // Clear the EGL error state because some of the above may // have errored out because the attribute is not applicable diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp index 34ba21afdc..2bfa7a8a02 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp @@ -64,6 +64,9 @@ QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatform : m_eglDisplay(display) , m_eglApi(eglApi) , m_eglConfig(q_configFromGLFormat(display, format)) + , m_swapInterval(-1) + , m_swapIntervalEnvChecked(false) + , m_swapIntervalFromEnv(-1) { init(format, share); } @@ -136,6 +139,27 @@ bool QEGLPlatformContext::makeCurrent(QPlatformSurface *surface) } #endif + + if (ok) { + if (!m_swapIntervalEnvChecked) { + m_swapIntervalEnvChecked = true; + if (qEnvironmentVariableIsSet("QT_QPA_EGL_SWAPINTERVAL")) { + QByteArray swapIntervalString = qgetenv("QT_QPA_EGL_SWAPINTERVAL"); + bool ok; + const int swapInterval = swapIntervalString.toInt(&ok); + if (ok) + m_swapIntervalFromEnv = swapInterval; + } + } + const int requestedSwapInterval = m_swapIntervalFromEnv >= 0 + ? m_swapIntervalFromEnv + : surface->format().swapInterval(); + if (requestedSwapInterval >= 0 && m_swapInterval != requestedSwapInterval) { + m_swapInterval = requestedSwapInterval; + eglSwapInterval(eglDisplay(), m_swapInterval); + } + } + return ok; } diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h index 952f5a856a..3d81a1c56e 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h @@ -80,6 +80,9 @@ private: EGLenum m_eglApi; EGLConfig m_eglConfig; QSurfaceFormat m_format; + int m_swapInterval; + bool m_swapIntervalEnvChecked; + int m_swapIntervalFromEnv; }; #endif //QEGLPLATFORMCONTEXT_H diff --git a/src/plugins/platforms/eglfs/qeglfscontext.cpp b/src/plugins/platforms/eglfs/qeglfscontext.cpp index 2c6846132d..dd3f272d8b 100644 --- a/src/plugins/platforms/eglfs/qeglfscontext.cpp +++ b/src/plugins/platforms/eglfs/qeglfscontext.cpp @@ -54,29 +54,13 @@ QT_BEGIN_NAMESPACE QEglFSContext::QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLenum eglApi) : QEGLPlatformContext(QEglFSHooks::hooks()->surfaceFormatFor(format), share, display, - QEglFSIntegration::chooseConfig(display, QEglFSHooks::hooks()->surfaceFormatFor(format)), eglApi), - m_swapIntervalSet(false) + QEglFSIntegration::chooseConfig(display, QEglFSHooks::hooks()->surfaceFormatFor(format)), eglApi) { } bool QEglFSContext::makeCurrent(QPlatformSurface *surface) { - bool success = QEGLPlatformContext::makeCurrent(surface); - - if (success && !m_swapIntervalSet) { - m_swapIntervalSet = true; - int swapInterval = 1; - QByteArray swapIntervalString = qgetenv("QT_QPA_EGLFS_SWAPINTERVAL"); - if (!swapIntervalString.isEmpty()) { - bool ok; - swapInterval = swapIntervalString.toInt(&ok); - if (!ok) - swapInterval = 1; - } - eglSwapInterval(eglDisplay(), swapInterval); - } - - return success; + return QEGLPlatformContext::makeCurrent(surface); } EGLSurface QEglFSContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface) diff --git a/src/plugins/platforms/eglfs/qeglfscontext.h b/src/plugins/platforms/eglfs/qeglfscontext.h index 8db340252c..6caa49ab4f 100644 --- a/src/plugins/platforms/eglfs/qeglfscontext.h +++ b/src/plugins/platforms/eglfs/qeglfscontext.h @@ -55,9 +55,6 @@ public: bool makeCurrent(QPlatformSurface *surface); EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface); void swapBuffers(QPlatformSurface *surface); - -private: - bool m_swapIntervalSet; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp index 70f0e437b2..d6f233b6c5 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -126,7 +126,7 @@ void QEglFSWindow::create() EGLDisplay display = static_cast(screen)->display(); QSurfaceFormat platformFormat = QEglFSHooks::hooks()->surfaceFormatFor(window()->requestedFormat()); m_config = QEglFSIntegration::chooseConfig(display, platformFormat); - m_format = q_glFormatFromConfig(display, m_config); + m_format = q_glFormatFromConfig(display, m_config, platformFormat); resetSurface(); diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index d1ede39549..93f2b53672 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -880,7 +880,9 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex m_staticContext(staticContext), m_context(context), m_renderingContext(0), - m_pixelFormat(0), m_extensionsUsed(false) + m_pixelFormat(0), + m_extensionsUsed(false), + m_swapInterval(-1) { QSurfaceFormat format = context->format(); if (format.renderableType() == QSurfaceFormat::DefaultRenderableType) @@ -977,11 +979,9 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex QWindowsOpenGLContextFormat::current().apply(&m_obtainedFormat); - if (requestedAdditional.swapInterval != -1 && m_staticContext->wglSwapInternalExt) { - m_staticContext->wglSwapInternalExt(requestedAdditional.swapInterval); - if (m_staticContext->wglGetSwapInternalExt) - obtainedSwapInternal = m_staticContext->wglGetSwapInternalExt(); - } + if (m_staticContext->wglGetSwapInternalExt) + obtainedSwapInternal = m_staticContext->wglGetSwapInternalExt(); + wglMakeCurrent(0, 0); } while (false); if (hdc) @@ -1085,7 +1085,19 @@ bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface) window->setFlag(QWindowsWindow::OpenGLDoubleBuffered); } m_windowContexts.append(newContext); - return wglMakeCurrent(newContext.hdc, newContext.renderingContext); + + bool success = wglMakeCurrent(newContext.hdc, newContext.renderingContext); + + // Set the swap interval + if (m_staticContext->wglSwapInternalExt) { + const int interval = surface->format().swapInterval(); + if (interval >= 0 && m_swapInterval != interval) { + m_swapInterval = interval; + m_staticContext->wglSwapInternalExt(interval); + } + } + + return success; } void QWindowsGLContext::doneCurrent() diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h index 730e90bf70..c6b477128a 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.h +++ b/src/plugins/platforms/windows/qwindowsglcontext.h @@ -64,11 +64,10 @@ enum QWindowsGLFormatFlags // Additional format information for Windows. struct QWindowsOpenGLAdditionalFormat { - QWindowsOpenGLAdditionalFormat(unsigned formatFlagsIn = 0, unsigned pixmapDepthIn = 0, unsigned swapIntervalIn = -1) : - formatFlags(formatFlagsIn), pixmapDepth(pixmapDepthIn), swapInterval(swapIntervalIn) {} + QWindowsOpenGLAdditionalFormat(unsigned formatFlagsIn = 0, unsigned pixmapDepthIn = 0) : + formatFlags(formatFlagsIn), pixmapDepth(pixmapDepthIn) { } unsigned formatFlags; // QWindowsGLFormatFlags. unsigned pixmapDepth; // for QWindowsGLRenderToPixmap - int swapInterval; }; // Per-window data for active OpenGL contexts. @@ -178,6 +177,7 @@ private: PIXELFORMATDESCRIPTOR m_obtainedPixelFormatDescriptor; int m_pixelFormat; bool m_extensionsUsed; + int m_swapInterval; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp index cbfbdf495f..5fc5b4ba97 100644 --- a/src/plugins/platforms/xcb/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/qglxintegration.cpp @@ -167,6 +167,7 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat , m_shareContext(0) , m_format(format) , m_isPBufferCurrent(false) + , m_swapInterval(-1) { if (m_format.renderableType() == QSurfaceFormat::DefaultRenderableType) m_format.setRenderableType(QSurfaceFormat::OpenGL); @@ -326,19 +327,50 @@ QGLXContext::~QGLXContext() bool QGLXContext::makeCurrent(QPlatformSurface *surface) { + bool success = false; Q_ASSERT(surface->surface()->surfaceType() == QSurface::OpenGLSurface); + Display *dpy = DISPLAY_FROM_XCB(m_screen); + GLXDrawable glxDrawable = 0; QSurface::SurfaceClass surfaceClass = surface->surface()->surfaceClass(); if (surfaceClass == QSurface::Window) { m_isPBufferCurrent = false; QXcbWindow *window = static_cast(surface); - return glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), window->xcb_window(), m_context); + glxDrawable = window->xcb_window(); + success = glXMakeCurrent(dpy, glxDrawable, m_context); } else if (surfaceClass == QSurface::Offscreen) { m_isPBufferCurrent = true; QGLXPbuffer *pbuffer = static_cast(surface); - return glXMakeContextCurrent(DISPLAY_FROM_XCB(m_screen), pbuffer->pbuffer(), pbuffer->pbuffer(), m_context); + glxDrawable = pbuffer->pbuffer(); + success = glXMakeContextCurrent(dpy, glxDrawable, glxDrawable, m_context); } - return false; + + if (success) { + int interval = surface->format().swapInterval(); + if (interval >= 0 && m_swapInterval != interval) { + m_swapInterval = interval; + typedef void (*qt_glXSwapIntervalEXT)(Display *, GLXDrawable, int); + typedef void (*qt_glXSwapIntervalMESA)(unsigned int); + static qt_glXSwapIntervalEXT glXSwapIntervalEXT = 0; + static qt_glXSwapIntervalMESA glXSwapIntervalMESA = 0; + static bool resolved = false; + if (!resolved) { + resolved = true; + QList glxExt = QByteArray(glXQueryExtensionsString(dpy, + m_screen->screenNumber())).split(' '); + if (glxExt.contains("GLX_EXT_swap_control")) + glXSwapIntervalEXT = (qt_glXSwapIntervalEXT) getProcAddress("glXSwapIntervalEXT"); + if (glxExt.contains("GLX_MESA_swap_control")) + glXSwapIntervalMESA = (qt_glXSwapIntervalMESA) getProcAddress("glXSwapIntervalMESA"); + } + if (glXSwapIntervalEXT) + glXSwapIntervalEXT(dpy, glxDrawable, interval); + else if (glXSwapIntervalMESA) + glXSwapIntervalMESA(interval); + } + } + + return success; } void QGLXContext::doneCurrent() diff --git a/src/plugins/platforms/xcb/qglxintegration.h b/src/plugins/platforms/xcb/qglxintegration.h index 7116b2389d..1666f71060 100644 --- a/src/plugins/platforms/xcb/qglxintegration.h +++ b/src/plugins/platforms/xcb/qglxintegration.h @@ -78,6 +78,7 @@ private: GLXContext m_shareContext; QSurfaceFormat m_format; bool m_isPBufferCurrent; + int m_swapInterval; }; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index aa53093868..832f871bb7 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -293,7 +293,7 @@ void QXcbWindow::create() #elif defined(XCB_USE_EGL) EGLDisplay eglDisplay = connection()->egl_display(); EGLConfig eglConfig = q_configFromGLFormat(eglDisplay, m_format, true); - m_format = q_glFormatFromConfig(eglDisplay, eglConfig); + m_format = q_glFormatFromConfig(eglDisplay, eglConfig, m_format); VisualID id = QXlibEglIntegration::getCompatibleVisualId(DISPLAY_FROM_XCB(this), eglDisplay, eglConfig); From 34ff885bff3703d6e4d8d05192bce6f4d26edb90 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 13 Nov 2013 14:07:53 +0100 Subject: [PATCH 097/684] Make drawing to and from RGBA8888 images faster After profiling drawing with RGBA8888 images most of the time appears to be spend in converting to and from ARGB32PM. This patch adds four small converters that are 3-4 times faster than the generic converter. Change-Id: I3c7498756f440ca3ea9c1417b26dd8e1953b9d06 Reviewed-by: Gunnar Sletta --- src/gui/painting/qdrawhelper.cpp | 44 +++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index a037545dc2..8b36a0e28f 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -118,6 +118,22 @@ static const uint *QT_FASTCALL convertARGB32ToARGB32PM(uint *buffer, const uint return buffer; } +static const uint *QT_FASTCALL convertRGBA8888PMToARGB32PM(uint *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ + for (int i = 0; i < count; ++i) + buffer[i] = RGBA2ARGB(src[i]); + return buffer; +} + +static const uint *QT_FASTCALL convertRGBA8888ToARGB32PM(uint *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ + for (int i = 0; i < count; ++i) + buffer[i] = PREMUL(RGBA2ARGB(src[i])); + return buffer; +} + static const uint *QT_FASTCALL convertToRGB32(uint *buffer, const uint *src, int count, const QPixelLayout *layout, const QRgb *) { @@ -222,6 +238,22 @@ static const uint *QT_FASTCALL convertARGB32FromARGB32PM(uint *buffer, const uin return buffer; } +static const uint *QT_FASTCALL convertRGBA8888PMFromARGB32PM(uint *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ + for (int i = 0; i < count; ++i) + buffer[i] = ARGB2RGBA(src[i]); + return buffer; +} + +static const uint *QT_FASTCALL convertRGBA8888FromARGB32PM(uint *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ + for (int i = 0; i < count; ++i) + buffer[i] = ARGB2RGBA(INV_PREMUL(src[i])); + return buffer; +} + static const uint *QT_FASTCALL convertFromARGB32PM(uint *buffer, const uint *src, int count, const QPixelLayout *layout, const QRgb *) { @@ -415,13 +447,13 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = { { 4, 8, 4, 4, 4, 0, 0, 0, false, QPixelLayout::BPP16, convertToRGB32, convertFromARGB32PM }, // Format_RGB444 { 4, 8, 4, 4, 4, 0, 4, 12, true, QPixelLayout::BPP16, convertToARGB32PM, convertFromARGB32PM }, // Format_ARGB4444_Premultiplied #if Q_BYTE_ORDER == Q_BIG_ENDIAN - { 8, 24, 8, 16, 8, 8, 0, 0, false, QPixelLayout::BPP32, convertToRGB32, convertRGBFromARGB32PM }, // Format_RGBX8888 - { 8, 24, 8, 16, 8, 8, 8, 0, false, QPixelLayout::BPP32, convertToARGB32PM, convertFromARGB32PM }, // Format_RGBA8888 - { 8, 24, 8, 16, 8, 8, 8, 0, true, QPixelLayout::BPP32, convertToARGB32PM, convertFromARGB32PM }, // Format_RGBA8888_Premultiplied + { 8, 24, 8, 16, 8, 8, 0, 0, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBFromARGB32PM }, // Format_RGBX8888 + { 8, 24, 8, 16, 8, 8, 8, 0, false, QPixelLayout::BPP32, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM }, // Format_RGBA8888 + { 8, 24, 8, 16, 8, 8, 8, 0, true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM }, // Format_RGBA8888_Premultiplied #else - { 8, 0, 8, 8, 8, 16, 0, 24, false, QPixelLayout::BPP32, convertToRGB32, convertRGBFromARGB32PM }, // Format_RGBX8888 - { 8, 0, 8, 8, 8, 16, 8, 24, false, QPixelLayout::BPP32, convertToARGB32PM, convertFromARGB32PM }, // Format_RGBA8888 (ABGR32) - { 8, 0, 8, 8, 8, 16, 8, 24, true, QPixelLayout::BPP32, convertToARGB32PM, convertFromARGB32PM } // Format_RGBA8888_Premultiplied + { 8, 0, 8, 8, 8, 16, 0, 24, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBFromARGB32PM }, // Format_RGBX8888 + { 8, 0, 8, 8, 8, 16, 8, 24, false, QPixelLayout::BPP32, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM }, // Format_RGBA8888 (ABGR32) + { 8, 0, 8, 8, 8, 16, 8, 24, true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM } // Format_RGBA8888_Premultiplied #endif }; From 06d1c149c7709b4e4e09ae72fc14c0b4bae32c84 Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Wed, 13 Nov 2013 11:38:18 +0100 Subject: [PATCH 098/684] update bundled sqlite to 3.8.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Id75bf901c9014419eddbe2d0e5a75ee274b17914 Reviewed-by: Friedemann Kleint Reviewed-by: Konstantin Ritt Reviewed-by: Fatih Aşıcı Reviewed-by: Mark Brand --- src/3rdparty/sqlite/shell.c | 551 +- src/3rdparty/sqlite/sqlite3.c | 15548 +++++++++++++++++++------------- src/3rdparty/sqlite/sqlite3.h | 148 +- 3 files changed, 9811 insertions(+), 6436 deletions(-) diff --git a/src/3rdparty/sqlite/shell.c b/src/3rdparty/sqlite/shell.c index 1be2871fed..41ea56492e 100644 --- a/src/3rdparty/sqlite/shell.c +++ b/src/3rdparty/sqlite/shell.c @@ -53,7 +53,6 @@ # include #endif #if !defined(HAVE_EDITLINE) && (!defined(HAVE_READLINE) || HAVE_READLINE!=1) -# define readline(p) local_getline(p,stdin,0) # define add_history(X) # define read_history(X) # define write_history(X) @@ -65,13 +64,18 @@ #define isatty(h) _isatty(h) #define access(f,m) _access((f),(m)) #undef popen -#define popen(a,b) _popen((a),(b)) +#define popen _popen #undef pclose -#define pclose(x) _pclose(x) +#define pclose _pclose #else /* Make sure isatty() has a prototype. */ extern int isatty(int); + +/* popen and pclose are not C89 functions and so are sometimes omitted from +** the header */ +extern FILE *popen(const char*,const char*); +extern int pclose(FILE*); #endif #if defined(_WIN32_WCE) @@ -332,23 +336,13 @@ static void shellstaticFunc( ** to the text. NULL is returned at end of file, or if malloc() ** fails. ** -** The interface is like "readline" but no command-line editing -** is done. +** If zLine is not NULL then it is a malloced buffer returned from +** a previous call to this routine that may be reused. */ -static char *local_getline(char *zPrompt, FILE *in, int csvFlag){ - char *zLine; - int nLine; - int n; - int inQuote = 0; +static char *local_getline(char *zLine, FILE *in){ + int nLine = zLine==0 ? 0 : 100; + int n = 0; - if( zPrompt && *zPrompt ){ - printf("%s",zPrompt); - fflush(stdout); - } - nLine = 100; - zLine = malloc( nLine ); - if( zLine==0 ) return 0; - n = 0; while( 1 ){ if( n+100>nLine ){ nLine = nLine*2 + 100; @@ -363,42 +357,48 @@ static char *local_getline(char *zPrompt, FILE *in, int csvFlag){ zLine[n] = 0; break; } - while( zLine[n] ){ - if( zLine[n]=='"' ) inQuote = !inQuote; - n++; - } - if( n>0 && zLine[n-1]=='\n' && (!inQuote || !csvFlag) ){ + while( zLine[n] ) n++; + if( n>0 && zLine[n-1]=='\n' ){ n--; if( n>0 && zLine[n-1]=='\r' ) n--; zLine[n] = 0; break; } } - zLine = realloc( zLine, n+1 ); return zLine; } /* ** Retrieve a single line of input text. ** -** zPrior is a string of prior text retrieved. If not the empty -** string, then issue a continuation prompt. +** If in==0 then read from standard input and prompt before each line. +** If isContinuation is true, then a continuation prompt is appropriate. +** If isContinuation is zero, then the main prompt should be used. +** +** If zPrior is not NULL then it is a buffer from a prior call to this +** routine that can be reused. +** +** The result is stored in space obtained from malloc() and must either +** be freed by the caller or else passed back into this routine via the +** zPrior argument for reuse. */ -static char *one_input_line(const char *zPrior, FILE *in){ +static char *one_input_line(FILE *in, char *zPrior, int isContinuation){ char *zPrompt; char *zResult; if( in!=0 ){ - return local_getline(0, in, 0); - } - if( zPrior && zPrior[0] ){ - zPrompt = continuePrompt; + zResult = local_getline(zPrior, in); }else{ - zPrompt = mainPrompt; - } - zResult = readline(zPrompt); + zPrompt = isContinuation ? continuePrompt : mainPrompt; #if defined(HAVE_READLINE) && HAVE_READLINE==1 - if( zResult && *zResult ) add_history(zResult); + free(zPrior); + zResult = readline(zPrompt); + if( zResult && *zResult ) add_history(zResult); +#else + printf("%s", zPrompt); + fflush(stdout); + zResult = local_getline(zPrior, stdin); #endif + } return zResult; } @@ -554,7 +554,7 @@ static void output_c_string(FILE *out, const char *z){ }else if( c=='\r' ){ fputc('\\', out); fputc('r', out); - }else if( !isprint(c) ){ + }else if( !isprint(c&0xff) ){ fprintf(out, "\\%03o", c&0xff); }else{ fputc(c, out); @@ -974,7 +974,7 @@ static int run_table_dump_query( rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0); if( rc!=SQLITE_OK || !pSelect ){ fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db)); - p->nErr++; + if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; return rc; } rc = sqlite3_step(pSelect); @@ -1001,7 +1001,7 @@ static int run_table_dump_query( rc = sqlite3_finalize(pSelect); if( rc!=SQLITE_OK ){ fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db)); - p->nErr++; + if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; } return rc; } @@ -1109,6 +1109,8 @@ static int display_stats( fprintf(pArg->out, "Sort Operations: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX, bReset); fprintf(pArg->out, "Autoindex Inserts: %d\n", iCur); + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset); + fprintf(pArg->out, "Virtual Machine Steps: %d\n", iCur); } return 0; @@ -1192,7 +1194,7 @@ static int shell_exec( char **azCols = (char **)pData; /* Names of result columns */ char **azVals = &azCols[nCol]; /* Results */ int *aiTypes = (int *)&azVals[nCol]; /* Result types */ - int i; + int i, x; assert(sizeof(int) <= sizeof(char *)); /* save off ptrs to column names */ for(i=0; imode==MODE_Insert ){ + azVals[i] = ""; + }else{ + azVals[i] = (char*)sqlite3_column_text(pStmt, i); + } if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){ rc = SQLITE_NOMEM; break; /* from for */ @@ -1278,7 +1284,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ if( strcmp(zTable, "sqlite_sequence")==0 ){ zPrepStmt = "DELETE FROM sqlite_sequence;\n"; - }else if( strcmp(zTable, "sqlite_stat1")==0 ){ + }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){ fprintf(p->out, "ANALYZE sqlite_master;\n"); }else if( strncmp(zTable, "sqlite_", 7)==0 ){ return 0; @@ -1490,6 +1496,7 @@ static void open_db(struct callback_data *p){ ** \t -> tab ** \n -> newline ** \r -> carriage return +** \" -> " ** \NNN -> ascii character NNN in octal ** \\ -> backslash */ @@ -1505,6 +1512,8 @@ static void resolve_backslashes(char *z){ c = '\t'; }else if( c=='r' ){ c = '\r'; + }else if( c=='\\' ){ + c = '\\'; }else if( c>='0' && c<='7' ){ c -= '0'; if( z[i+1]>='0' && z[i+1]<='7' ){ @@ -1523,21 +1532,14 @@ static void resolve_backslashes(char *z){ } /* -** Interpret zArg as a boolean value. Return either 0 or 1. +** Return the value of a hexadecimal digit. Return -1 if the input +** is not a hex digit. */ -static int booleanValue(char *zArg){ - int i; - for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){} - if( i>0 && zArg[i]==0 ) return atoi(zArg); - if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){ - return 1; - } - if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){ - return 0; - } - fprintf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n", - zArg); - return 0; +static int hexDigitValue(char c){ + if( c>='0' && c<='9' ) return c - '0'; + if( c>='a' && c<='f' ) return c - 'a' + 10; + if( c>='A' && c<='F' ) return c - 'A' + 10; + return -1; } /* @@ -1564,11 +1566,20 @@ static sqlite3_int64 integerValue(const char *zArg){ }else if( zArg[0]=='+' ){ zArg++; } - while( isdigit(zArg[0]) ){ - v = v*10 + zArg[0] - '0'; - zArg++; + if( zArg[0]=='0' && zArg[1]=='x' ){ + int x; + zArg += 2; + while( (x = hexDigitValue(zArg[0]))>=0 ){ + v = (v<<4) + x; + zArg++; + } + }else{ + while( IsDigit(zArg[0]) ){ + v = v*10 + zArg[0] - '0'; + zArg++; + } } - for(i=0; i=0; i++){} + }else{ + for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){} + } + if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff); + if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){ + return 1; + } + if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){ + return 0; + } + fprintf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n", + zArg); + return 0; +} + /* ** Close an output file, assuming it is not stderr or stdout */ @@ -1623,6 +1657,105 @@ static void test_breakpoint(void){ nCall++; } +/* +** An object used to read a CSV file +*/ +typedef struct CSVReader CSVReader; +struct CSVReader { + const char *zFile; /* Name of the input file */ + FILE *in; /* Read the CSV text from this input stream */ + char *z; /* Accumulated text for a field */ + int n; /* Number of bytes in z */ + int nAlloc; /* Space allocated for z[] */ + int nLine; /* Current line number */ + int cTerm; /* Character that terminated the most recent field */ + int cSeparator; /* The separator character. (Usually ",") */ +}; + +/* Append a single byte to z[] */ +static void csv_append_char(CSVReader *p, int c){ + if( p->n+1>=p->nAlloc ){ + p->nAlloc += p->nAlloc + 100; + p->z = sqlite3_realloc(p->z, p->nAlloc); + if( p->z==0 ){ + fprintf(stderr, "out of memory\n"); + exit(1); + } + } + p->z[p->n++] = (char)c; +} + +/* Read a single field of CSV text. Compatible with rfc4180 and extended +** with the option of having a separator other than ",". +** +** + Input comes from p->in. +** + Store results in p->z of length p->n. Space to hold p->z comes +** from sqlite3_malloc(). +** + Use p->cSep as the separator. The default is ",". +** + Keep track of the line number in p->nLine. +** + Store the character that terminates the field in p->cTerm. Store +** EOF on end-of-file. +** + Report syntax errors on stderr +*/ +static char *csv_read_one_field(CSVReader *p){ + int c, pc; + int cSep = p->cSeparator; + p->n = 0; + c = fgetc(p->in); + if( c==EOF || seenInterrupt ){ + p->cTerm = EOF; + return 0; + } + if( c=='"' ){ + int startLine = p->nLine; + int cQuote = c; + pc = 0; + while( 1 ){ + c = fgetc(p->in); + if( c=='\n' ) p->nLine++; + if( c==cQuote ){ + if( pc==cQuote ){ + pc = 0; + continue; + } + } + if( (c==cSep && pc==cQuote) + || (c=='\n' && pc==cQuote) + || (c=='\n' && pc=='\r' && p->n>=2 && p->z[p->n-2]==cQuote) + || (c==EOF && pc==cQuote) + ){ + do{ p->n--; }while( p->z[p->n]!=cQuote ); + p->cTerm = c; + break; + } + if( pc==cQuote && c!='\r' ){ + fprintf(stderr, "%s:%d: unescaped %c character\n", + p->zFile, p->nLine, cQuote); + } + if( c==EOF ){ + fprintf(stderr, "%s:%d: unterminated %c-quoted field\n", + p->zFile, startLine, cQuote); + p->cTerm = EOF; + break; + } + csv_append_char(p, c); + pc = c; + } + }else{ + while( c!=EOF && c!=cSep && c!='\n' ){ + csv_append_char(p, c); + c = fgetc(p->in); + } + if( c=='\n' ){ + p->nLine++; + if( p->n>1 && p->z[p->n-1]=='\r' ) p->n--; + } + p->cTerm = c; + } + if( p->z ) p->z[p->n] = 0; + return p->z; +} + /* ** If an input line begins with "." then invoke this routine to ** process that line. @@ -1644,7 +1777,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){ if( zLine[i]=='\'' || zLine[i]=='"' ){ int delim = zLine[i++]; azArg[nArg++] = &zLine[i]; - while( zLine[i] && zLine[i]!=delim ){ i++; } + while( zLine[i] && zLine[i]!=delim ){ + if( zLine[i]=='\\' && delim=='"' && zLine[i+1]!=0 ) i++; + i++; + } if( zLine[i]==delim ){ zLine[i++] = 0; } @@ -1665,7 +1801,6 @@ static int do_meta_command(char *zLine, struct callback_data *p){ if( c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0 ){ const char *zDestFile = 0; const char *zDb = 0; - const char *zKey = 0; sqlite3 *pDest; sqlite3_backup *pBackup; int j; @@ -1673,9 +1808,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ const char *z = azArg[j]; if( z[0]=='-' ){ while( z[0]=='-' ) z++; - if( strcmp(z,"key")==0 && jdb, zDb); if( pBackup==0 ){ @@ -1808,7 +1936,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ }else if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){ - if( nArg>1 && (rc = atoi(azArg[1]))!=0 ) exit(rc); + if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc); rc = 2; }else @@ -1861,48 +1989,98 @@ static int do_meta_command(char *zLine, struct callback_data *p){ if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg==3 ){ char *zTable = azArg[2]; /* Insert data into this table */ - char *zFile = azArg[1]; /* The file from which to extract data */ + char *zFile = azArg[1]; /* Name of file to extra content from */ sqlite3_stmt *pStmt = NULL; /* A statement */ int nCol; /* Number of columns in the table */ int nByte; /* Number of bytes in an SQL string */ int i, j; /* Loop counters */ + int needCommit; /* True to COMMIT or ROLLBACK at end */ int nSep; /* Number of bytes in p->separator[] */ char *zSql; /* An SQL statement */ - char *zLine; /* A single line of input from the file */ - char **azCol; /* zLine[] broken up into columns */ - char *zCommit; /* How to commit changes */ - FILE *in; /* The input file */ - int lineno = 0; /* Line number of input file */ + CSVReader sCsv; /* Reader context */ + int (*xCloser)(FILE*); /* Procedure to close th3 connection */ + seenInterrupt = 0; + memset(&sCsv, 0, sizeof(sCsv)); open_db(p); nSep = strlen30(p->separator); if( nSep==0 ){ fprintf(stderr, "Error: non-null separator required for import\n"); return 1; } + if( nSep>1 ){ + fprintf(stderr, "Error: multi-character separators not allowed" + " for import\n"); + return 1; + } + sCsv.zFile = zFile; + sCsv.nLine = 1; + if( sCsv.zFile[0]=='|' ){ + sCsv.in = popen(sCsv.zFile+1, "r"); + sCsv.zFile = ""; + xCloser = pclose; + }else{ + sCsv.in = fopen(sCsv.zFile, "rb"); + xCloser = fclose; + } + if( sCsv.in==0 ){ + fprintf(stderr, "Error: cannot open \"%s\"\n", zFile); + return 1; + } + sCsv.cSeparator = p->separator[0]; zSql = sqlite3_mprintf("SELECT * FROM %s", zTable); if( zSql==0 ){ fprintf(stderr, "Error: out of memory\n"); + xCloser(sCsv.in); return 1; } nByte = strlen30(zSql); rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); + if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){ + char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable); + char cSep = '('; + while( csv_read_one_field(&sCsv) ){ + zCreate = sqlite3_mprintf("%z%c\n \"%s\" TEXT", zCreate, cSep, sCsv.z); + cSep = ','; + if( sCsv.cTerm!=sCsv.cSeparator ) break; + } + if( cSep=='(' ){ + sqlite3_free(zCreate); + sqlite3_free(sCsv.z); + xCloser(sCsv.in); + fprintf(stderr,"%s: empty file\n", sCsv.zFile); + return 1; + } + zCreate = sqlite3_mprintf("%z\n)", zCreate); + rc = sqlite3_exec(p->db, zCreate, 0, 0, 0); + sqlite3_free(zCreate); + if( rc ){ + fprintf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable, + sqlite3_errmsg(db)); + sqlite3_free(sCsv.z); + xCloser(sCsv.in); + return 1; + } + rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); + } sqlite3_free(zSql); if( rc ){ if (pStmt) sqlite3_finalize(pStmt); fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db)); + xCloser(sCsv.in); return 1; } nCol = sqlite3_column_count(pStmt); sqlite3_finalize(pStmt); pStmt = 0; if( nCol==0 ) return 0; /* no columns, no error */ - zSql = malloc( nByte + 20 + nCol*2 ); + zSql = sqlite3_malloc( nByte*2 + 20 + nCol*2 ); if( zSql==0 ){ fprintf(stderr, "Error: out of memory\n"); + xCloser(sCsv.in); return 1; } - sqlite3_snprintf(nByte+20, zSql, "INSERT INTO %s VALUES(?", zTable); + sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable); j = strlen30(zSql); for(i=1; idb, zSql, -1, &pStmt, 0); - free(zSql); + sqlite3_free(zSql); if( rc ){ fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db)); if (pStmt) sqlite3_finalize(pStmt); + xCloser(sCsv.in); return 1; } - in = fopen(zFile, "rb"); - if( in==0 ){ - fprintf(stderr, "Error: cannot open \"%s\"\n", zFile); - sqlite3_finalize(pStmt); - return 1; - } - azCol = malloc( sizeof(azCol[0])*(nCol+1) ); - if( azCol==0 ){ - fprintf(stderr, "Error: out of memory\n"); - fclose(in); - sqlite3_finalize(pStmt); - return 1; - } - sqlite3_exec(p->db, "BEGIN", 0, 0, 0); - zCommit = "COMMIT"; - while( (zLine = local_getline(0, in, 1))!=0 ){ - char *z, c; - int inQuote = 0; - lineno++; - azCol[0] = zLine; - for(i=0, z=zLine; (c = *z)!=0; z++){ - if( c=='"' ) inQuote = !inQuote; - if( c=='\n' ) lineno++; - if( !inQuote && c==p->separator[0] && strncmp(z,p->separator,nSep)==0 ){ - *z = 0; - i++; - if( i=nCol ){ + sqlite3_step(pStmt); + rc = sqlite3_reset(pStmt); + if( rc!=SQLITE_OK ){ + fprintf(stderr, "%s:%d: INSERT failed: %s\n", sCsv.zFile, startLine, + sqlite3_errmsg(db)); + } + } + }while( sCsv.cTerm!=EOF ); + + xCloser(sCsv.in); + sqlite3_free(sCsv.z); sqlite3_finalize(pStmt); - sqlite3_exec(p->db, zCommit, 0, 0, 0); + if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0); }else if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg<3 ){ @@ -2305,6 +2456,29 @@ static int do_meta_command(char *zLine, struct callback_data *p){ } }else +#ifdef SQLITE_DEBUG + /* Undocumented commands for internal testing. Subject to change + ** without notice. */ + if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){ + if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){ + int i, v; + for(i=1; iout, "%s: %d 0x%x\n", azArg[i], v, v); + } + } + if( strncmp(azArg[0]+9, "integer", n-9)==0 ){ + int i; sqlite3_int64 v; + for(i=1; iout, "%s", zBuf); + } + } + }else +#endif + if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){ sqlite3_snprintf(sizeof(p->separator), p->separator, "%.*s", (int)sizeof(p->separator)-1, azArg[1]); @@ -2458,7 +2632,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ } } } - if( testctrl<0 ) testctrl = atoi(azArg[1]); + if( testctrl<0 ) testctrl = (int)integerValue(azArg[1]); if( (testctrlSQLITE_TESTCTRL_LAST) ){ fprintf(stderr,"Error: invalid testctrl option: %s\n", azArg[1]); }else{ @@ -2492,7 +2666,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ /* sqlite3_test_control(int, uint) */ case SQLITE_TESTCTRL_PENDING_BYTE: if( nArg==3 ){ - unsigned int opt = (unsigned int)integerValue(azArg[2]); + unsigned int opt = (unsigned int)integerValue(azArg[2]); rc = sqlite3_test_control(testctrl, opt); fprintf(p->out, "%d (0x%08x)\n", rc, rc); } else { @@ -2505,7 +2679,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ case SQLITE_TESTCTRL_ASSERT: case SQLITE_TESTCTRL_ALWAYS: if( nArg==3 ){ - int opt = atoi(azArg[2]); + int opt = booleanValue(azArg[2]); rc = sqlite3_test_control(testctrl, opt); fprintf(p->out, "%d (0x%08x)\n", rc, rc); } else { @@ -2542,7 +2716,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 && nArg==2 ){ open_db(p); - sqlite3_busy_timeout(p->db, atoi(azArg[1])); + sqlite3_busy_timeout(p->db, (int)integerValue(azArg[1])); }else if( HAS_TIMER && c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 @@ -2592,7 +2766,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ int j; assert( nArg<=ArraySize(azArg) ); for(j=1; jcolWidth); j++){ - p->colWidth[j-1] = atoi(azArg[j]); + p->colWidth[j-1] = (int)integerValue(azArg[j]); } }else @@ -2609,7 +2783,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ ** Return TRUE if a semicolon occurs anywhere in the first N characters ** of string z[]. */ -static int _contains_semicolon(const char *z, int N){ +static int line_contains_semicolon(const char *z, int N){ int i; for(i=0; iout); - free(zLine); - zLine = one_input_line(zSql, in); + zLine = one_input_line(in, zLine, nSql>0); if( zLine==0 ){ /* End of input */ if( stdin_is_interactive ) printf("\n"); @@ -2704,7 +2879,7 @@ static int process_input(struct callback_data *p, FILE *in){ seenInterrupt = 0; } lineno++; - if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue; + if( nSql==0 && _all_whitespace(zLine) ) continue; if( zLine && zLine[0]=='.' && nSql==0 ){ if( p->echoOn ) printf("%s\n", zLine); rc = do_meta_command(zLine, p); @@ -2715,35 +2890,32 @@ static int process_input(struct callback_data *p, FILE *in){ } continue; } - if( _is_command_terminator(zLine) && _is_complete(zSql, nSql) ){ + if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){ memcpy(zLine,";",2); } - nSqlPrior = nSql; - if( zSql==0 ){ - int i; - for(i=0; zLine[i] && IsSpace(zLine[i]); i++){} - if( zLine[i]!=0 ){ - nSql = strlen30(zLine); - zSql = malloc( nSql+3 ); - if( zSql==0 ){ - fprintf(stderr, "Error: out of memory\n"); - exit(1); - } - memcpy(zSql, zLine, nSql+1); - startline = lineno; - } - }else{ - int len = strlen30(zLine); - zSql = realloc( zSql, nSql + len + 4 ); + nLine = strlen30(zLine); + if( nSql+nLine+2>=nAlloc ){ + nAlloc = nSql+nLine+100; + zSql = realloc(zSql, nAlloc); if( zSql==0 ){ - fprintf(stderr,"Error: out of memory\n"); + fprintf(stderr, "Error: out of memory\n"); exit(1); } - zSql[nSql++] = '\n'; - memcpy(&zSql[nSql], zLine, len+1); - nSql += len; } - if( zSql && _contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior) + nSqlPrior = nSql; + if( nSql==0 ){ + int i; + for(i=0; zLine[i] && IsSpace(zLine[i]); i++){} + assert( nAlloc>0 && zSql!=0 ); + memcpy(zSql, zLine+i, nLine+1-i); + startline = lineno; + nSql = nLine-i; + }else{ + zSql[nSql++] = '\n'; + memcpy(zSql+nSql, zLine, nLine+1); + nSql += nLine; + } + if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior) && sqlite3_complete(zSql) ){ p->cnt = 0; open_db(p); @@ -2767,16 +2939,12 @@ static int process_input(struct callback_data *p, FILE *in){ } errCnt++; } - free(zSql); - zSql = 0; nSql = 0; - }else if( zSql && _all_whitespace(zSql) ){ - free(zSql); - zSql = 0; + }else if( nSql && _all_whitespace(zSql) ){ nSql = 0; } } - if( zSql ){ + if( nSql ){ if( !_all_whitespace(zSql) ){ fprintf(stderr, "Error: incomplete SQL: %s\n", zSql); } @@ -3024,7 +3192,6 @@ int main(int argc, char **argv){ stdin_is_interactive = 0; }else if( strcmp(z,"-heap")==0 ){ #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) - int j, c; const char *zSize; sqlite3_int64 szHeap; diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c index 03fa649610..2d27e750d0 100644 --- a/src/3rdparty/sqlite/sqlite3.c +++ b/src/3rdparty/sqlite/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.7.17. By combining all the individual C code files into this +** version 3.8.1. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -25,549 +25,6 @@ #ifndef SQLITE_API # define SQLITE_API #endif -/************** Begin file sqliteInt.h ***************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Internal interface definitions for SQLite. -** -*/ -#ifndef _SQLITEINT_H_ -#define _SQLITEINT_H_ - -/* -** These #defines should enable >2GB file support on POSIX if the -** underlying operating system supports it. If the OS lacks -** large file support, or if the OS is windows, these should be no-ops. -** -** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any -** system #includes. Hence, this block of code must be the very first -** code in all source files. -** -** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch -** on the compiler command line. This is necessary if you are compiling -** on a recent machine (ex: Red Hat 7.2) but you want your code to work -** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2 -** without this option, LFS is enable. But LFS does not exist in the kernel -** in Red Hat 6.0, so the code won't work. Hence, for maximum binary -** portability you should omit LFS. -** -** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later. -*/ -#ifndef SQLITE_DISABLE_LFS -# define _LARGE_FILE 1 -# ifndef _FILE_OFFSET_BITS -# define _FILE_OFFSET_BITS 64 -# endif -# define _LARGEFILE_SOURCE 1 -#endif - -/* -** Include the configuration header output by 'configure' if we're using the -** autoconf-based build -*/ -#ifdef _HAVE_SQLITE_CONFIG_H -#include "config.h" -#endif - -/************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/ -/************** Begin file sqliteLimit.h *************************************/ -/* -** 2007 May 7 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file defines various limits of what SQLite can process. -*/ - -/* -** The maximum length of a TEXT or BLOB in bytes. This also -** limits the size of a row in a table or index. -** -** The hard limit is the ability of a 32-bit signed integer -** to count the size: 2^31-1 or 2147483647. -*/ -#ifndef SQLITE_MAX_LENGTH -# define SQLITE_MAX_LENGTH 1000000000 -#endif - -/* -** This is the maximum number of -** -** * Columns in a table -** * Columns in an index -** * Columns in a view -** * Terms in the SET clause of an UPDATE statement -** * Terms in the result set of a SELECT statement -** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement. -** * Terms in the VALUES clause of an INSERT statement -** -** The hard upper limit here is 32676. Most database people will -** tell you that in a well-normalized database, you usually should -** not have more than a dozen or so columns in any table. And if -** that is the case, there is no point in having more than a few -** dozen values in any of the other situations described above. -*/ -#ifndef SQLITE_MAX_COLUMN -# define SQLITE_MAX_COLUMN 2000 -#endif - -/* -** The maximum length of a single SQL statement in bytes. -** -** It used to be the case that setting this value to zero would -** turn the limit off. That is no longer true. It is not possible -** to turn this limit off. -*/ -#ifndef SQLITE_MAX_SQL_LENGTH -# define SQLITE_MAX_SQL_LENGTH 1000000000 -#endif - -/* -** The maximum depth of an expression tree. This is limited to -** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might -** want to place more severe limits on the complexity of an -** expression. -** -** A value of 0 used to mean that the limit was not enforced. -** But that is no longer true. The limit is now strictly enforced -** at all times. -*/ -#ifndef SQLITE_MAX_EXPR_DEPTH -# define SQLITE_MAX_EXPR_DEPTH 1000 -#endif - -/* -** The maximum number of terms in a compound SELECT statement. -** The code generator for compound SELECT statements does one -** level of recursion for each term. A stack overflow can result -** if the number of terms is too large. In practice, most SQL -** never has more than 3 or 4 terms. Use a value of 0 to disable -** any limit on the number of terms in a compount SELECT. -*/ -#ifndef SQLITE_MAX_COMPOUND_SELECT -# define SQLITE_MAX_COMPOUND_SELECT 500 -#endif - -/* -** The maximum number of opcodes in a VDBE program. -** Not currently enforced. -*/ -#ifndef SQLITE_MAX_VDBE_OP -# define SQLITE_MAX_VDBE_OP 25000 -#endif - -/* -** The maximum number of arguments to an SQL function. -*/ -#ifndef SQLITE_MAX_FUNCTION_ARG -# define SQLITE_MAX_FUNCTION_ARG 127 -#endif - -/* -** The maximum number of in-memory pages to use for the main database -** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE -*/ -#ifndef SQLITE_DEFAULT_CACHE_SIZE -# define SQLITE_DEFAULT_CACHE_SIZE 2000 -#endif -#ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE -# define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500 -#endif - -/* -** The default number of frames to accumulate in the log file before -** checkpointing the database in WAL mode. -*/ -#ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT -# define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT 1000 -#endif - -/* -** The maximum number of attached databases. This must be between 0 -** and 62. The upper bound on 62 is because a 64-bit integer bitmap -** is used internally to track attached databases. -*/ -#ifndef SQLITE_MAX_ATTACHED -# define SQLITE_MAX_ATTACHED 10 -#endif - - -/* -** The maximum value of a ?nnn wildcard that the parser will accept. -*/ -#ifndef SQLITE_MAX_VARIABLE_NUMBER -# define SQLITE_MAX_VARIABLE_NUMBER 999 -#endif - -/* Maximum page size. The upper bound on this value is 65536. This a limit -** imposed by the use of 16-bit offsets within each page. -** -** Earlier versions of SQLite allowed the user to change this value at -** compile time. This is no longer permitted, on the grounds that it creates -** a library that is technically incompatible with an SQLite library -** compiled with a different limit. If a process operating on a database -** with a page-size of 65536 bytes crashes, then an instance of SQLite -** compiled with the default page-size limit will not be able to rollback -** the aborted transaction. This could lead to database corruption. -*/ -#ifdef SQLITE_MAX_PAGE_SIZE -# undef SQLITE_MAX_PAGE_SIZE -#endif -#define SQLITE_MAX_PAGE_SIZE 65536 - - -/* -** The default size of a database page. -*/ -#ifndef SQLITE_DEFAULT_PAGE_SIZE -# define SQLITE_DEFAULT_PAGE_SIZE 1024 -#endif -#if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE -# undef SQLITE_DEFAULT_PAGE_SIZE -# define SQLITE_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE -#endif - -/* -** Ordinarily, if no value is explicitly provided, SQLite creates databases -** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain -** device characteristics (sector-size and atomic write() support), -** SQLite may choose a larger value. This constant is the maximum value -** SQLite will choose on its own. -*/ -#ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE -# define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192 -#endif -#if SQLITE_MAX_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE -# undef SQLITE_MAX_DEFAULT_PAGE_SIZE -# define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE -#endif - - -/* -** Maximum number of pages in one database file. -** -** This is really just the default value for the max_page_count pragma. -** This value can be lowered (or raised) at run-time using that the -** max_page_count macro. -*/ -#ifndef SQLITE_MAX_PAGE_COUNT -# define SQLITE_MAX_PAGE_COUNT 1073741823 -#endif - -/* -** Maximum length (in bytes) of the pattern in a LIKE or GLOB -** operator. -*/ -#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH -# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000 -#endif - -/* -** Maximum depth of recursion for triggers. -** -** A value of 1 means that a trigger program will not be able to itself -** fire any triggers. A value of 0 means that no trigger programs at all -** may be executed. -*/ -#ifndef SQLITE_MAX_TRIGGER_DEPTH -# define SQLITE_MAX_TRIGGER_DEPTH 1000 -#endif - -/************** End of sqliteLimit.h *****************************************/ -/************** Continuing where we left off in sqliteInt.h ******************/ - -/* Disable nuisance warnings on Borland compilers */ -#if defined(__BORLANDC__) -#pragma warn -rch /* unreachable code */ -#pragma warn -ccc /* Condition is always true or false */ -#pragma warn -aus /* Assigned value is never used */ -#pragma warn -csu /* Comparing signed and unsigned */ -#pragma warn -spa /* Suspicious pointer arithmetic */ -#endif - -/* Needed for various definitions... */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif - -#if defined(__OpenBSD__) && !defined(_BSD_SOURCE) -# define _BSD_SOURCE -#endif - -/* -** Include standard header files as necessary -*/ -#ifdef HAVE_STDINT_H -#include -#endif -#ifdef HAVE_INTTYPES_H -#include -#endif - -/* -** The following macros are used to cast pointers to integers and -** integers to pointers. The way you do this varies from one compiler -** to the next, so we have developed the following set of #if statements -** to generate appropriate macros for a wide range of compilers. -** -** The correct "ANSI" way to do this is to use the intptr_t type. -** Unfortunately, that typedef is not available on all compilers, or -** if it is available, it requires an #include of specific headers -** that vary from one machine to the next. -** -** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on -** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)). -** So we have to define the macros in different ways depending on the -** compiler. -*/ -#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */ -# define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X)) -# define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X)) -#elif !defined(__GNUC__) /* Works for compilers other than LLVM */ -# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X]) -# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0)) -#elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */ -# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X)) -# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X)) -#else /* Generates a warning - but it always works */ -# define SQLITE_INT_TO_PTR(X) ((void*)(X)) -# define SQLITE_PTR_TO_INT(X) ((int)(X)) -#endif - -/* -** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2. -** 0 means mutexes are permanently disable and the library is never -** threadsafe. 1 means the library is serialized which is the highest -** level of threadsafety. 2 means the libary is multithreaded - multiple -** threads can use SQLite as long as no two threads try to use the same -** database connection at the same time. -** -** Older versions of SQLite used an optional THREADSAFE macro. -** We support that for legacy. -*/ -#if !defined(SQLITE_THREADSAFE) -# if defined(THREADSAFE) -# define SQLITE_THREADSAFE THREADSAFE -# else -# define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */ -# endif -#endif - -/* -** Powersafe overwrite is on by default. But can be turned off using -** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option. -*/ -#ifndef SQLITE_POWERSAFE_OVERWRITE -# define SQLITE_POWERSAFE_OVERWRITE 1 -#endif - -/* -** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1. -** It determines whether or not the features related to -** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can -** be overridden at runtime using the sqlite3_config() API. -*/ -#if !defined(SQLITE_DEFAULT_MEMSTATUS) -# define SQLITE_DEFAULT_MEMSTATUS 1 -#endif - -/* -** Exactly one of the following macros must be defined in order to -** specify which memory allocation subsystem to use. -** -** SQLITE_SYSTEM_MALLOC // Use normal system malloc() -** SQLITE_WIN32_MALLOC // Use Win32 native heap API -** SQLITE_ZERO_MALLOC // Use a stub allocator that always fails -** SQLITE_MEMDEBUG // Debugging version of system malloc() -** -** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the -** assert() macro is enabled, each call into the Win32 native heap subsystem -** will cause HeapValidate to be called. If heap validation should fail, an -** assertion will be triggered. -** -** (Historical note: There used to be several other options, but we've -** pared it down to just these three.) -** -** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as -** the default. -*/ -#if defined(SQLITE_SYSTEM_MALLOC) \ - + defined(SQLITE_WIN32_MALLOC) \ - + defined(SQLITE_ZERO_MALLOC) \ - + defined(SQLITE_MEMDEBUG)>1 -# error "Two or more of the following compile-time configuration options\ - are defined but at most one is allowed:\ - SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG,\ - SQLITE_ZERO_MALLOC" -#endif -#if defined(SQLITE_SYSTEM_MALLOC) \ - + defined(SQLITE_WIN32_MALLOC) \ - + defined(SQLITE_ZERO_MALLOC) \ - + defined(SQLITE_MEMDEBUG)==0 -# define SQLITE_SYSTEM_MALLOC 1 -#endif - -/* -** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the -** sizes of memory allocations below this value where possible. -*/ -#if !defined(SQLITE_MALLOC_SOFT_LIMIT) -# define SQLITE_MALLOC_SOFT_LIMIT 1024 -#endif - -/* -** We need to define _XOPEN_SOURCE as follows in order to enable -** recursive mutexes on most Unix systems. But Mac OS X is different. -** The _XOPEN_SOURCE define causes problems for Mac OS X we are told, -** so it is omitted there. See ticket #2673. -** -** Later we learn that _XOPEN_SOURCE is poorly or incorrectly -** implemented on some systems. So we avoid defining it at all -** if it is already defined or if it is unneeded because we are -** not doing a threadsafe build. Ticket #2681. -** -** See also ticket #2741. -*/ -#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) \ - && !defined(__APPLE__) && SQLITE_THREADSAFE -# define _XOPEN_SOURCE 500 /* Needed to enable pthread recursive mutexes */ -#endif - -/* -** The TCL headers are only needed when compiling the TCL bindings. -*/ -#if defined(SQLITE_TCL) || defined(TCLSH) -# include -#endif - -/* -** NDEBUG and SQLITE_DEBUG are opposites. It should always be true that -** defined(NDEBUG)==!defined(SQLITE_DEBUG). If this is not currently true, -** make it true by defining or undefining NDEBUG. -** -** Setting NDEBUG makes the code smaller and run faster by disabling the -** number assert() statements in the code. So we want the default action -** to be for NDEBUG to be set and NDEBUG to be undefined only if SQLITE_DEBUG -** is set. Thus NDEBUG becomes an opt-in rather than an opt-out -** feature. -*/ -#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) -# define NDEBUG 1 -#endif -#if defined(NDEBUG) && defined(SQLITE_DEBUG) -# undef NDEBUG -#endif - -/* -** The testcase() macro is used to aid in coverage testing. When -** doing coverage testing, the condition inside the argument to -** testcase() must be evaluated both true and false in order to -** get full branch coverage. The testcase() macro is inserted -** to help ensure adequate test coverage in places where simple -** condition/decision coverage is inadequate. For example, testcase() -** can be used to make sure boundary values are tested. For -** bitmask tests, testcase() can be used to make sure each bit -** is significant and used at least once. On switch statements -** where multiple cases go to the same block of code, testcase() -** can insure that all cases are evaluated. -** -*/ -#ifdef SQLITE_COVERAGE_TEST -SQLITE_PRIVATE void sqlite3Coverage(int); -# define testcase(X) if( X ){ sqlite3Coverage(__LINE__); } -#else -# define testcase(X) -#endif - -/* -** The TESTONLY macro is used to enclose variable declarations or -** other bits of code that are needed to support the arguments -** within testcase() and assert() macros. -*/ -#if !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST) -# define TESTONLY(X) X -#else -# define TESTONLY(X) -#endif - -/* -** Sometimes we need a small amount of code such as a variable initialization -** to setup for a later assert() statement. We do not want this code to -** appear when assert() is disabled. The following macro is therefore -** used to contain that setup code. The "VVA" acronym stands for -** "Verification, Validation, and Accreditation". In other words, the -** code within VVA_ONLY() will only run during verification processes. -*/ -#ifndef NDEBUG -# define VVA_ONLY(X) X -#else -# define VVA_ONLY(X) -#endif - -/* -** The ALWAYS and NEVER macros surround boolean expressions which -** are intended to always be true or false, respectively. Such -** expressions could be omitted from the code completely. But they -** are included in a few cases in order to enhance the resilience -** of SQLite to unexpected behavior - to make the code "self-healing" -** or "ductile" rather than being "brittle" and crashing at the first -** hint of unplanned behavior. -** -** In other words, ALWAYS and NEVER are added for defensive code. -** -** When doing coverage testing ALWAYS and NEVER are hard-coded to -** be true and false so that the unreachable code then specify will -** not be counted as untested code. -*/ -#if defined(SQLITE_COVERAGE_TEST) -# define ALWAYS(X) (1) -# define NEVER(X) (0) -#elif !defined(NDEBUG) -# define ALWAYS(X) ((X)?1:(assert(0),0)) -# define NEVER(X) ((X)?(assert(0),1):0) -#else -# define ALWAYS(X) (X) -# define NEVER(X) (X) -#endif - -/* -** Return true (non-zero) if the input is a integer that is too large -** to fit in 32-bits. This macro is used inside of various testcase() -** macros to verify that we have tested SQLite for large-file support. -*/ -#define IS_BIG_INT(X) (((X)&~(i64)0xffffffff)!=0) - -/* -** The macro unlikely() is a hint that surrounds a boolean -** expression that is usually false. Macro likely() surrounds -** a boolean expression that is usually true. GCC is able to -** use these hints to generate better code, sometimes. -*/ -#if defined(__GNUC__) && 0 -# define likely(X) __builtin_expect((X),1) -# define unlikely(X) __builtin_expect((X),0) -#else -# define likely(X) !!(X) -# define unlikely(X) !!(X) -#endif - -/************** Include sqlite3.h in the middle of sqliteInt.h ***************/ /************** Begin file sqlite3.h *****************************************/ /* ** 2001 September 15 @@ -678,9 +135,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.7.17" -#define SQLITE_VERSION_NUMBER 3007017 -#define SQLITE_SOURCE_ID "2013-05-20 00:56:22 118a3b35693b134d56ebd780123b7fd6f1497668" +#define SQLITE_VERSION "3.8.1" +#define SQLITE_VERSION_NUMBER 3008001 +#define SQLITE_SOURCE_ID "2013-10-17 12:57:35 c78be6d786c19073b3a6730dfe3fb1be54f5657a" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -1049,11 +506,15 @@ SQLITE_API int sqlite3_exec( #define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8)) #define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8)) #define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8)) +#define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8)) +#define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) +#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) +#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) @@ -1070,6 +531,7 @@ SQLITE_API int sqlite3_exec( #define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8)) #define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8)) #define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8)) +#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8)) /* ** CAPI3REF: Flags For File Open Operations @@ -2183,27 +1645,27 @@ struct sqlite3_mem_methods { ** function must be threadsafe. ** ** [[SQLITE_CONFIG_URI]]
SQLITE_CONFIG_URI -**
This option takes a single argument of type int. If non-zero, then +**
^(This option takes a single argument of type int. If non-zero, then ** URI handling is globally enabled. If the parameter is zero, then URI handling -** is globally disabled. If URI handling is globally enabled, all filenames +** is globally disabled.)^ ^If URI handling is globally enabled, all filenames ** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or ** specified as part of [ATTACH] commands are interpreted as URIs, regardless ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database -** connection is opened. If it is globally disabled, filenames are +** connection is opened. ^If it is globally disabled, filenames are ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the -** database connection is opened. By default, URI handling is globally +** database connection is opened. ^(By default, URI handling is globally ** disabled. The default value may be changed by compiling with the -** [SQLITE_USE_URI] symbol defined. +** [SQLITE_USE_URI] symbol defined.)^ ** ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]]
SQLITE_CONFIG_COVERING_INDEX_SCAN -**
This option takes a single integer argument which is interpreted as +**
^This option takes a single integer argument which is interpreted as ** a boolean in order to enable or disable the use of covering indices for -** full table scans in the query optimizer. The default setting is determined +** full table scans in the query optimizer. ^The default setting is determined ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" ** if that compile-time option is omitted. ** The ability to disable the use of covering indices for full table scans ** is because some incorrectly coded legacy applications might malfunction -** malfunction when the optimization is enabled. Providing the ability to +** when the optimization is enabled. Providing the ability to ** disable the optimization allows the older, buggy application code to work ** without change even with newer versions of SQLite. ** @@ -2232,16 +1694,16 @@ struct sqlite3_mem_methods { ** ** [[SQLITE_CONFIG_MMAP_SIZE]] **
SQLITE_CONFIG_MMAP_SIZE -**
SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values +**
^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values ** that are the default mmap size limit (the default setting for ** [PRAGMA mmap_size]) and the maximum allowed mmap size limit. -** The default setting can be overridden by each database connection using +** ^The default setting can be overridden by each database connection using ** either the [PRAGMA mmap_size] command, or by using the -** [SQLITE_FCNTL_MMAP_SIZE] file control. The maximum allowed mmap size +** [SQLITE_FCNTL_MMAP_SIZE] file control. ^(The maximum allowed mmap size ** cannot be changed at run-time. Nor may the maximum allowed mmap size ** exceed the compile-time maximum mmap size set by the -** [SQLITE_MAX_MMAP_SIZE] compile-time option. -** If either argument to this option is negative, then that argument is +** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^ +** ^If either argument to this option is negative, then that argument is ** changed to its compile-time default. ** */ @@ -3128,9 +2590,10 @@ SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*, ** interface is to keep a GUI updated during a large query. ** ** ^The parameter P is passed through as the only parameter to the -** callback function X. ^The parameter N is the number of +** callback function X. ^The parameter N is the approximate number of ** [virtual machine instructions] that are evaluated between successive -** invocations of the callback X. +** invocations of the callback X. ^If N is less than one then the progress +** handler is disabled. ** ** ^Only a single progress handler may be defined at one time per ** [database connection]; setting a new progress handler cancels the @@ -4750,41 +4213,49 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); /* ** CAPI3REF: Function Auxiliary Data ** -** The following two functions may be used by scalar SQL functions to +** These functions may be used by (non-aggregate) SQL functions to ** associate metadata with argument values. If the same value is passed to ** multiple invocations of the same SQL function during query execution, under -** some circumstances the associated metadata may be preserved. This may -** be used, for example, to add a regular-expression matching scalar -** function. The compiled version of the regular expression is stored as -** metadata associated with the SQL value passed as the regular expression -** pattern. The compiled regular expression can be reused on multiple -** invocations of the same function so that the original pattern string -** does not need to be recompiled on each invocation. +** some circumstances the associated metadata may be preserved. An example +** of where this might be useful is in a regular-expression matching +** function. The compiled version of the regular expression can be stored as +** metadata associated with the pattern string. +** Then as long as the pattern string remains the same, +** the compiled regular expression can be reused on multiple +** invocations of the same function. ** ** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata ** associated by the sqlite3_set_auxdata() function with the Nth argument -** value to the application-defined function. ^If no metadata has been ever -** been set for the Nth argument of the function, or if the corresponding -** function parameter has changed since the meta-data was set, -** then sqlite3_get_auxdata() returns a NULL pointer. +** value to the application-defined function. ^If there is no metadata +** associated with the function argument, this sqlite3_get_auxdata() interface +** returns a NULL pointer. ** -** ^The sqlite3_set_auxdata() interface saves the metadata -** pointed to by its 3rd parameter as the metadata for the N-th -** argument of the application-defined function. Subsequent -** calls to sqlite3_get_auxdata() might return this data, if it has -** not been destroyed. -** ^If it is not NULL, SQLite will invoke the destructor -** function given by the 4th parameter to sqlite3_set_auxdata() on -** the metadata when the corresponding function parameter changes -** or when the SQL statement completes, whichever comes first. +** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th +** argument of the application-defined function. ^Subsequent +** calls to sqlite3_get_auxdata(C,N) return P from the most recent +** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or +** NULL if the metadata has been discarded. +** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL, +** SQLite will invoke the destructor function X with parameter P exactly +** once, when the metadata is discarded. +** SQLite is free to discard the metadata at any time, including:
    +**
  • when the corresponding function parameter changes, or +**
  • when [sqlite3_reset()] or [sqlite3_finalize()] is called for the +** SQL statement, or +**
  • when sqlite3_set_auxdata() is invoked again on the same parameter, or +**
  • during the original sqlite3_set_auxdata() call when a memory +** allocation error occurs.
)^ ** -** SQLite is free to call the destructor and drop metadata on any -** parameter of any function at any time. ^The only guarantee is that -** the destructor will be called before the metadata is dropped. +** Note the last bullet in particular. The destructor X in +** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the +** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata() +** should be called near the end of the function implementation and the +** function implementation should not make any use of P after +** sqlite3_set_auxdata() has been called. ** ** ^(In practice, metadata is preserved between function calls for -** expressions that are constant at compile time. This includes literal -** values and [parameters].)^ +** function parameters that are compile-time constants, including literal +** values and [parameters] and expressions composed from the same.)^ ** ** These routines must be called from the same thread in which ** the SQL function is running. @@ -5089,6 +4560,11 @@ SQLITE_API int sqlite3_key( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The key */ ); +SQLITE_API int sqlite3_key_v2( + sqlite3 *db, /* Database to be rekeyed */ + const char *zDbName, /* Name of the database */ + const void *pKey, int nKey /* The key */ +); /* ** Change the key on an open database. If the current database is not @@ -5102,6 +4578,11 @@ SQLITE_API int sqlite3_rekey( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The new key */ ); +SQLITE_API int sqlite3_rekey_v2( + sqlite3 *db, /* Database to be rekeyed */ + const char *zDbName, /* Name of the database */ + const void *pKey, int nKey /* The new key */ +); /* ** Specify the activation key for a SEE database. Unless @@ -5687,10 +5168,23 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); ** on the list of automatic extensions is a harmless no-op. ^No entry point ** will be called more than once for each database connection that is opened. ** -** See also: [sqlite3_reset_auto_extension()]. +** See also: [sqlite3_reset_auto_extension()] +** and [sqlite3_cancel_auto_extension()] */ SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); +/* +** CAPI3REF: Cancel Automatic Extension Loading +** +** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the +** initialization routine X that was registered using a prior call to +** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)] +** routine returns 1 if initialization routine X was successfully +** unregistered and it returns 0 if X was not on the list of initialization +** routines. +*/ +SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void)); + /* ** CAPI3REF: Reset Automatic Extension Loading ** @@ -6803,6 +6297,12 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r ** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. **
+** +** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(
SQLITE_DBSTATUS_DEFERRED_FKS
+**
This parameter returns zero for the current value if and only if +** all foreign key constraints (deferred or immediate) have been +** resolved.)^ ^The highwater mark is always 0. +**
** */ #define SQLITE_DBSTATUS_LOOKASIDE_USED 0 @@ -6815,7 +6315,8 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r #define SQLITE_DBSTATUS_CACHE_HIT 7 #define SQLITE_DBSTATUS_CACHE_MISS 8 #define SQLITE_DBSTATUS_CACHE_WRITE 9 -#define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */ +#define SQLITE_DBSTATUS_DEFERRED_FKS 10 +#define SQLITE_DBSTATUS_MAX 10 /* Largest defined DBSTATUS */ /* @@ -6869,11 +6370,21 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); ** A non-zero value in this counter may indicate an opportunity to ** improvement performance by adding permanent indices that do not ** need to be reinitialized each time the statement is run. +** +** [[SQLITE_STMTSTATUS_VM_STEP]]
SQLITE_STMTSTATUS_VM_STEP
+**
^This is the number of virtual machine operations executed +** by the prepared statement if that number is less than or equal +** to 2147483647. The number of virtual machine operations can be +** used as a proxy for the total work done by the prepared statement. +** If the number of virtual machine operations exceeds 2147483647 +** then the value returned by this statement status code is undefined. +**
** */ #define SQLITE_STMTSTATUS_FULLSCAN_STEP 1 #define SQLITE_STMTSTATUS_SORT 2 #define SQLITE_STMTSTATUS_AUTOINDEX 3 +#define SQLITE_STMTSTATUS_VM_STEP 4 /* ** CAPI3REF: Custom Page Cache Object @@ -7752,7 +7263,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); #if 0 } /* End of the 'extern "C"' block */ #endif -#endif +#endif /* _SQLITE3_H_ */ /* ** 2010 August 30 @@ -7816,7 +7327,526 @@ struct sqlite3_rtree_geometry { /************** End of sqlite3.h *********************************************/ +/************** Begin file sqliteInt.h ***************************************/ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** Internal interface definitions for SQLite. +** +*/ +#ifndef _SQLITEINT_H_ +#define _SQLITEINT_H_ + +/* +** These #defines should enable >2GB file support on POSIX if the +** underlying operating system supports it. If the OS lacks +** large file support, or if the OS is windows, these should be no-ops. +** +** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any +** system #includes. Hence, this block of code must be the very first +** code in all source files. +** +** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch +** on the compiler command line. This is necessary if you are compiling +** on a recent machine (ex: Red Hat 7.2) but you want your code to work +** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2 +** without this option, LFS is enable. But LFS does not exist in the kernel +** in Red Hat 6.0, so the code won't work. Hence, for maximum binary +** portability you should omit LFS. +** +** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later. +*/ +#ifndef SQLITE_DISABLE_LFS +# define _LARGE_FILE 1 +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# define _LARGEFILE_SOURCE 1 +#endif + +/* +** Include the configuration header output by 'configure' if we're using the +** autoconf-based build +*/ +#ifdef _HAVE_SQLITE_CONFIG_H +#include "config.h" +#endif + +/************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/ +/************** Begin file sqliteLimit.h *************************************/ +/* +** 2007 May 7 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file defines various limits of what SQLite can process. +*/ + +/* +** The maximum length of a TEXT or BLOB in bytes. This also +** limits the size of a row in a table or index. +** +** The hard limit is the ability of a 32-bit signed integer +** to count the size: 2^31-1 or 2147483647. +*/ +#ifndef SQLITE_MAX_LENGTH +# define SQLITE_MAX_LENGTH 1000000000 +#endif + +/* +** This is the maximum number of +** +** * Columns in a table +** * Columns in an index +** * Columns in a view +** * Terms in the SET clause of an UPDATE statement +** * Terms in the result set of a SELECT statement +** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement. +** * Terms in the VALUES clause of an INSERT statement +** +** The hard upper limit here is 32676. Most database people will +** tell you that in a well-normalized database, you usually should +** not have more than a dozen or so columns in any table. And if +** that is the case, there is no point in having more than a few +** dozen values in any of the other situations described above. +*/ +#ifndef SQLITE_MAX_COLUMN +# define SQLITE_MAX_COLUMN 2000 +#endif + +/* +** The maximum length of a single SQL statement in bytes. +** +** It used to be the case that setting this value to zero would +** turn the limit off. That is no longer true. It is not possible +** to turn this limit off. +*/ +#ifndef SQLITE_MAX_SQL_LENGTH +# define SQLITE_MAX_SQL_LENGTH 1000000000 +#endif + +/* +** The maximum depth of an expression tree. This is limited to +** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might +** want to place more severe limits on the complexity of an +** expression. +** +** A value of 0 used to mean that the limit was not enforced. +** But that is no longer true. The limit is now strictly enforced +** at all times. +*/ +#ifndef SQLITE_MAX_EXPR_DEPTH +# define SQLITE_MAX_EXPR_DEPTH 1000 +#endif + +/* +** The maximum number of terms in a compound SELECT statement. +** The code generator for compound SELECT statements does one +** level of recursion for each term. A stack overflow can result +** if the number of terms is too large. In practice, most SQL +** never has more than 3 or 4 terms. Use a value of 0 to disable +** any limit on the number of terms in a compount SELECT. +*/ +#ifndef SQLITE_MAX_COMPOUND_SELECT +# define SQLITE_MAX_COMPOUND_SELECT 500 +#endif + +/* +** The maximum number of opcodes in a VDBE program. +** Not currently enforced. +*/ +#ifndef SQLITE_MAX_VDBE_OP +# define SQLITE_MAX_VDBE_OP 25000 +#endif + +/* +** The maximum number of arguments to an SQL function. +*/ +#ifndef SQLITE_MAX_FUNCTION_ARG +# define SQLITE_MAX_FUNCTION_ARG 127 +#endif + +/* +** The maximum number of in-memory pages to use for the main database +** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE +*/ +#ifndef SQLITE_DEFAULT_CACHE_SIZE +# define SQLITE_DEFAULT_CACHE_SIZE 2000 +#endif +#ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE +# define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500 +#endif + +/* +** The default number of frames to accumulate in the log file before +** checkpointing the database in WAL mode. +*/ +#ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT +# define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT 1000 +#endif + +/* +** The maximum number of attached databases. This must be between 0 +** and 62. The upper bound on 62 is because a 64-bit integer bitmap +** is used internally to track attached databases. +*/ +#ifndef SQLITE_MAX_ATTACHED +# define SQLITE_MAX_ATTACHED 10 +#endif + + +/* +** The maximum value of a ?nnn wildcard that the parser will accept. +*/ +#ifndef SQLITE_MAX_VARIABLE_NUMBER +# define SQLITE_MAX_VARIABLE_NUMBER 999 +#endif + +/* Maximum page size. The upper bound on this value is 65536. This a limit +** imposed by the use of 16-bit offsets within each page. +** +** Earlier versions of SQLite allowed the user to change this value at +** compile time. This is no longer permitted, on the grounds that it creates +** a library that is technically incompatible with an SQLite library +** compiled with a different limit. If a process operating on a database +** with a page-size of 65536 bytes crashes, then an instance of SQLite +** compiled with the default page-size limit will not be able to rollback +** the aborted transaction. This could lead to database corruption. +*/ +#ifdef SQLITE_MAX_PAGE_SIZE +# undef SQLITE_MAX_PAGE_SIZE +#endif +#define SQLITE_MAX_PAGE_SIZE 65536 + + +/* +** The default size of a database page. +*/ +#ifndef SQLITE_DEFAULT_PAGE_SIZE +# define SQLITE_DEFAULT_PAGE_SIZE 1024 +#endif +#if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE +# undef SQLITE_DEFAULT_PAGE_SIZE +# define SQLITE_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE +#endif + +/* +** Ordinarily, if no value is explicitly provided, SQLite creates databases +** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain +** device characteristics (sector-size and atomic write() support), +** SQLite may choose a larger value. This constant is the maximum value +** SQLite will choose on its own. +*/ +#ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE +# define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192 +#endif +#if SQLITE_MAX_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE +# undef SQLITE_MAX_DEFAULT_PAGE_SIZE +# define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE +#endif + + +/* +** Maximum number of pages in one database file. +** +** This is really just the default value for the max_page_count pragma. +** This value can be lowered (or raised) at run-time using that the +** max_page_count macro. +*/ +#ifndef SQLITE_MAX_PAGE_COUNT +# define SQLITE_MAX_PAGE_COUNT 1073741823 +#endif + +/* +** Maximum length (in bytes) of the pattern in a LIKE or GLOB +** operator. +*/ +#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH +# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000 +#endif + +/* +** Maximum depth of recursion for triggers. +** +** A value of 1 means that a trigger program will not be able to itself +** fire any triggers. A value of 0 means that no trigger programs at all +** may be executed. +*/ +#ifndef SQLITE_MAX_TRIGGER_DEPTH +# define SQLITE_MAX_TRIGGER_DEPTH 1000 +#endif + +/************** End of sqliteLimit.h *****************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ + +/* Disable nuisance warnings on Borland compilers */ +#if defined(__BORLANDC__) +#pragma warn -rch /* unreachable code */ +#pragma warn -ccc /* Condition is always true or false */ +#pragma warn -aus /* Assigned value is never used */ +#pragma warn -csu /* Comparing signed and unsigned */ +#pragma warn -spa /* Suspicious pointer arithmetic */ +#endif + +/* Needed for various definitions... */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +#if defined(__OpenBSD__) && !defined(_BSD_SOURCE) +# define _BSD_SOURCE +#endif + +/* +** Include standard header files as necessary +*/ +#ifdef HAVE_STDINT_H +#include +#endif +#ifdef HAVE_INTTYPES_H +#include +#endif + +/* +** The following macros are used to cast pointers to integers and +** integers to pointers. The way you do this varies from one compiler +** to the next, so we have developed the following set of #if statements +** to generate appropriate macros for a wide range of compilers. +** +** The correct "ANSI" way to do this is to use the intptr_t type. +** Unfortunately, that typedef is not available on all compilers, or +** if it is available, it requires an #include of specific headers +** that vary from one machine to the next. +** +** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on +** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)). +** So we have to define the macros in different ways depending on the +** compiler. +*/ +#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */ +# define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X)) +# define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X)) +#elif !defined(__GNUC__) /* Works for compilers other than LLVM */ +# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X]) +# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0)) +#elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */ +# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X)) +# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X)) +#else /* Generates a warning - but it always works */ +# define SQLITE_INT_TO_PTR(X) ((void*)(X)) +# define SQLITE_PTR_TO_INT(X) ((int)(X)) +#endif + +/* +** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2. +** 0 means mutexes are permanently disable and the library is never +** threadsafe. 1 means the library is serialized which is the highest +** level of threadsafety. 2 means the library is multithreaded - multiple +** threads can use SQLite as long as no two threads try to use the same +** database connection at the same time. +** +** Older versions of SQLite used an optional THREADSAFE macro. +** We support that for legacy. +*/ +#if !defined(SQLITE_THREADSAFE) +# if defined(THREADSAFE) +# define SQLITE_THREADSAFE THREADSAFE +# else +# define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */ +# endif +#endif + +/* +** Powersafe overwrite is on by default. But can be turned off using +** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option. +*/ +#ifndef SQLITE_POWERSAFE_OVERWRITE +# define SQLITE_POWERSAFE_OVERWRITE 1 +#endif + +/* +** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1. +** It determines whether or not the features related to +** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can +** be overridden at runtime using the sqlite3_config() API. +*/ +#if !defined(SQLITE_DEFAULT_MEMSTATUS) +# define SQLITE_DEFAULT_MEMSTATUS 1 +#endif + +/* +** Exactly one of the following macros must be defined in order to +** specify which memory allocation subsystem to use. +** +** SQLITE_SYSTEM_MALLOC // Use normal system malloc() +** SQLITE_WIN32_MALLOC // Use Win32 native heap API +** SQLITE_ZERO_MALLOC // Use a stub allocator that always fails +** SQLITE_MEMDEBUG // Debugging version of system malloc() +** +** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the +** assert() macro is enabled, each call into the Win32 native heap subsystem +** will cause HeapValidate to be called. If heap validation should fail, an +** assertion will be triggered. +** +** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as +** the default. +*/ +#if defined(SQLITE_SYSTEM_MALLOC) \ + + defined(SQLITE_WIN32_MALLOC) \ + + defined(SQLITE_ZERO_MALLOC) \ + + defined(SQLITE_MEMDEBUG)>1 +# error "Two or more of the following compile-time configuration options\ + are defined but at most one is allowed:\ + SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG,\ + SQLITE_ZERO_MALLOC" +#endif +#if defined(SQLITE_SYSTEM_MALLOC) \ + + defined(SQLITE_WIN32_MALLOC) \ + + defined(SQLITE_ZERO_MALLOC) \ + + defined(SQLITE_MEMDEBUG)==0 +# define SQLITE_SYSTEM_MALLOC 1 +#endif + +/* +** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the +** sizes of memory allocations below this value where possible. +*/ +#if !defined(SQLITE_MALLOC_SOFT_LIMIT) +# define SQLITE_MALLOC_SOFT_LIMIT 1024 +#endif + +/* +** We need to define _XOPEN_SOURCE as follows in order to enable +** recursive mutexes on most Unix systems and fchmod() on OpenBSD. +** But _XOPEN_SOURCE define causes problems for Mac OS X, so omit +** it. +*/ +#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__) +# define _XOPEN_SOURCE 600 +#endif + +/* +** NDEBUG and SQLITE_DEBUG are opposites. It should always be true that +** defined(NDEBUG)==!defined(SQLITE_DEBUG). If this is not currently true, +** make it true by defining or undefining NDEBUG. +** +** Setting NDEBUG makes the code smaller and faster by disabling the +** assert() statements in the code. So we want the default action +** to be for NDEBUG to be set and NDEBUG to be undefined only if SQLITE_DEBUG +** is set. Thus NDEBUG becomes an opt-in rather than an opt-out +** feature. +*/ +#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) +# define NDEBUG 1 +#endif +#if defined(NDEBUG) && defined(SQLITE_DEBUG) +# undef NDEBUG +#endif + +/* +** The testcase() macro is used to aid in coverage testing. When +** doing coverage testing, the condition inside the argument to +** testcase() must be evaluated both true and false in order to +** get full branch coverage. The testcase() macro is inserted +** to help ensure adequate test coverage in places where simple +** condition/decision coverage is inadequate. For example, testcase() +** can be used to make sure boundary values are tested. For +** bitmask tests, testcase() can be used to make sure each bit +** is significant and used at least once. On switch statements +** where multiple cases go to the same block of code, testcase() +** can insure that all cases are evaluated. +** +*/ +#ifdef SQLITE_COVERAGE_TEST +SQLITE_PRIVATE void sqlite3Coverage(int); +# define testcase(X) if( X ){ sqlite3Coverage(__LINE__); } +#else +# define testcase(X) +#endif + +/* +** The TESTONLY macro is used to enclose variable declarations or +** other bits of code that are needed to support the arguments +** within testcase() and assert() macros. +*/ +#if !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST) +# define TESTONLY(X) X +#else +# define TESTONLY(X) +#endif + +/* +** Sometimes we need a small amount of code such as a variable initialization +** to setup for a later assert() statement. We do not want this code to +** appear when assert() is disabled. The following macro is therefore +** used to contain that setup code. The "VVA" acronym stands for +** "Verification, Validation, and Accreditation". In other words, the +** code within VVA_ONLY() will only run during verification processes. +*/ +#ifndef NDEBUG +# define VVA_ONLY(X) X +#else +# define VVA_ONLY(X) +#endif + +/* +** The ALWAYS and NEVER macros surround boolean expressions which +** are intended to always be true or false, respectively. Such +** expressions could be omitted from the code completely. But they +** are included in a few cases in order to enhance the resilience +** of SQLite to unexpected behavior - to make the code "self-healing" +** or "ductile" rather than being "brittle" and crashing at the first +** hint of unplanned behavior. +** +** In other words, ALWAYS and NEVER are added for defensive code. +** +** When doing coverage testing ALWAYS and NEVER are hard-coded to +** be true and false so that the unreachable code they specify will +** not be counted as untested code. +*/ +#if defined(SQLITE_COVERAGE_TEST) +# define ALWAYS(X) (1) +# define NEVER(X) (0) +#elif !defined(NDEBUG) +# define ALWAYS(X) ((X)?1:(assert(0),0)) +# define NEVER(X) ((X)?(assert(0),1):0) +#else +# define ALWAYS(X) (X) +# define NEVER(X) (X) +#endif + +/* +** Return true (non-zero) if the input is a integer that is too large +** to fit in 32-bits. This macro is used inside of various testcase() +** macros to verify that we have tested SQLite for large-file support. +*/ +#define IS_BIG_INT(X) (((X)&~(i64)0xffffffff)!=0) + +/* +** The macro unlikely() is a hint that surrounds a boolean +** expression that is usually false. Macro likely() surrounds +** a boolean expression that is usually true. These hints could, +** in theory, be used by the compiler to generate better code, but +** currently they are just comments for human readers. +*/ +#define likely(X) (X) +#define unlikely(X) (X) + /************** Include hash.h in the middle of sqliteInt.h ******************/ /************** Begin file hash.h ********************************************/ /* @@ -8153,6 +8183,12 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); #define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD)) #endif +/* +** Macros to compute minimum and maximum of two numbers. +*/ +#define MIN(A,B) ((A)<(B)?(A):(B)) +#define MAX(A,B) ((A)>(B)?(A):(B)) + /* ** Check to see if this machine uses EBCDIC. (Yes, believe it or ** not, there are still machines out there that use EBCDIC.) @@ -8236,6 +8272,31 @@ typedef INT8_TYPE i8; /* 1-byte signed integer */ typedef u32 tRowcnt; /* 32-bit is the default */ #endif +/* +** Estimated quantities used for query planning are stored as 16-bit +** logarithms. For quantity X, the value stored is 10*log2(X). This +** gives a possible range of values of approximately 1.0e986 to 1e-986. +** But the allowed values are "grainy". Not every value is representable. +** For example, quantities 16 and 17 are both represented by a LogEst +** of 40. However, since LogEst quantatites are suppose to be estimates, +** not exact values, this imprecision is not a problem. +** +** "LogEst" is short for "Logarithimic Estimate". +** +** Examples: +** 1 -> 0 20 -> 43 10000 -> 132 +** 2 -> 10 25 -> 46 25000 -> 146 +** 3 -> 16 100 -> 66 1000000 -> 199 +** 4 -> 20 1000 -> 99 1048576 -> 200 +** 10 -> 33 1024 -> 100 4294967296 -> 320 +** +** The LogEst can be negative to indicate fractional values. +** Examples: +** +** 0.5 -> -10 0.1 -> -33 0.0625 -> -40 +*/ +typedef INT16_TYPE LogEst; + /* ** Macros to determine whether the machine is big or little endian, ** evaluated at runtime. @@ -8334,6 +8395,20 @@ SQLITE_PRIVATE const int sqlite3one; # define SQLITE_DEFAULT_MMAP_SIZE SQLITE_MAX_MMAP_SIZE #endif +/* +** Only one of SQLITE_ENABLE_STAT3 or SQLITE_ENABLE_STAT4 can be defined. +** Priority is given to SQLITE_ENABLE_STAT4. If either are defined, also +** define SQLITE_ENABLE_STAT3_OR_STAT4 +*/ +#ifdef SQLITE_ENABLE_STAT4 +# undef SQLITE_ENABLE_STAT3 +# define SQLITE_ENABLE_STAT3_OR_STAT4 1 +#elif SQLITE_ENABLE_STAT3 +# define SQLITE_ENABLE_STAT3_OR_STAT4 1 +#elif SQLITE_ENABLE_STAT3_OR_STAT4 +# undef SQLITE_ENABLE_STAT3_OR_STAT4 +#endif + /* ** An instance of the following structure is used to store the busy-handler ** callback for a given sqlite handle. @@ -8478,9 +8553,7 @@ typedef struct UnpackedRecord UnpackedRecord; typedef struct VTable VTable; typedef struct VtabCtx VtabCtx; typedef struct Walker Walker; -typedef struct WherePlan WherePlan; typedef struct WhereInfo WhereInfo; -typedef struct WhereLevel WhereLevel; /* ** Defer sourcing vdbe.h and btree.h until after the "u8" and @@ -8555,7 +8628,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( SQLITE_PRIVATE int sqlite3BtreeClose(Btree*); SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64); -SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int); +SQLITE_PRIVATE int sqlite3BtreeSetPagerFlags(Btree*,unsigned); SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*); SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); @@ -8779,7 +8852,6 @@ typedef struct Vdbe Vdbe; ** The names of the following types declared in vdbeInt.h are required ** for the VdbeOp definition. */ -typedef struct VdbeFunc VdbeFunc; typedef struct Mem Mem; typedef struct SubProgram SubProgram; @@ -8803,7 +8875,6 @@ struct VdbeOp { i64 *pI64; /* Used when p4type is P4_INT64 */ double *pReal; /* Used when p4type is P4_REAL */ FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */ - VdbeFunc *pVdbeFunc; /* Used when p4type is P4_VDBEFUNC */ CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */ Mem *pMem; /* Used when p4type is P4_MEM */ VTable *pVtab; /* Used when p4type is P4_VTAB */ @@ -8857,7 +8928,6 @@ typedef struct VdbeOpList VdbeOpList; #define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */ #define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */ #define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */ -#define P4_VDBEFUNC (-7) /* P4 is a pointer to a VdbeFunc structure */ #define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */ #define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */ #define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */ @@ -8914,151 +8984,151 @@ typedef struct VdbeOpList VdbeOpList; /************** Begin file opcodes.h *****************************************/ /* Automatically generated. Do not edit */ /* See the mkopcodeh.awk script for details */ -#define OP_Goto 1 -#define OP_Gosub 2 -#define OP_Return 3 -#define OP_Yield 4 -#define OP_HaltIfNull 5 -#define OP_Halt 6 -#define OP_Integer 7 -#define OP_Int64 8 -#define OP_Real 130 /* same as TK_FLOAT */ -#define OP_String8 94 /* same as TK_STRING */ -#define OP_String 9 -#define OP_Null 10 -#define OP_Blob 11 -#define OP_Variable 12 -#define OP_Move 13 -#define OP_Copy 14 -#define OP_SCopy 15 -#define OP_ResultRow 16 -#define OP_Concat 91 /* same as TK_CONCAT */ +#define OP_Function 1 +#define OP_Savepoint 2 +#define OP_AutoCommit 3 +#define OP_Transaction 4 +#define OP_SorterNext 5 +#define OP_Prev 6 +#define OP_Next 7 +#define OP_AggStep 8 +#define OP_Checkpoint 9 +#define OP_JournalMode 10 +#define OP_Vacuum 11 +#define OP_VFilter 12 +#define OP_VUpdate 13 +#define OP_Goto 14 +#define OP_Gosub 15 +#define OP_Return 16 +#define OP_Yield 17 +#define OP_HaltIfNull 18 +#define OP_Not 19 /* same as TK_NOT */ +#define OP_Halt 20 +#define OP_Integer 21 +#define OP_Int64 22 +#define OP_String 23 +#define OP_Null 24 +#define OP_Blob 25 +#define OP_Variable 26 +#define OP_Move 27 +#define OP_Copy 28 +#define OP_SCopy 29 +#define OP_ResultRow 30 +#define OP_CollSeq 31 +#define OP_AddImm 32 +#define OP_MustBeInt 33 +#define OP_RealAffinity 34 +#define OP_Permutation 35 +#define OP_Compare 36 +#define OP_Jump 37 +#define OP_Once 38 +#define OP_If 39 +#define OP_IfNot 40 +#define OP_Column 41 +#define OP_Affinity 42 +#define OP_MakeRecord 43 +#define OP_Count 44 +#define OP_ReadCookie 45 +#define OP_SetCookie 46 +#define OP_VerifyCookie 47 +#define OP_OpenRead 48 +#define OP_OpenWrite 49 +#define OP_OpenAutoindex 50 +#define OP_OpenEphemeral 51 +#define OP_SorterOpen 52 +#define OP_OpenPseudo 53 +#define OP_Close 54 +#define OP_SeekLt 55 +#define OP_SeekLe 56 +#define OP_SeekGe 57 +#define OP_SeekGt 58 +#define OP_Seek 59 +#define OP_NotFound 60 +#define OP_Found 61 +#define OP_IsUnique 62 +#define OP_NotExists 63 +#define OP_Sequence 64 +#define OP_NewRowid 65 +#define OP_Insert 66 +#define OP_InsertInt 67 +#define OP_Or 68 /* same as TK_OR */ +#define OP_And 69 /* same as TK_AND */ +#define OP_Delete 70 +#define OP_ResetCount 71 +#define OP_SorterCompare 72 +#define OP_IsNull 73 /* same as TK_ISNULL */ +#define OP_NotNull 74 /* same as TK_NOTNULL */ +#define OP_Ne 75 /* same as TK_NE */ +#define OP_Eq 76 /* same as TK_EQ */ +#define OP_Gt 77 /* same as TK_GT */ +#define OP_Le 78 /* same as TK_LE */ +#define OP_Lt 79 /* same as TK_LT */ +#define OP_Ge 80 /* same as TK_GE */ +#define OP_SorterData 81 +#define OP_BitAnd 82 /* same as TK_BITAND */ +#define OP_BitOr 83 /* same as TK_BITOR */ +#define OP_ShiftLeft 84 /* same as TK_LSHIFT */ +#define OP_ShiftRight 85 /* same as TK_RSHIFT */ #define OP_Add 86 /* same as TK_PLUS */ #define OP_Subtract 87 /* same as TK_MINUS */ #define OP_Multiply 88 /* same as TK_STAR */ #define OP_Divide 89 /* same as TK_SLASH */ #define OP_Remainder 90 /* same as TK_REM */ -#define OP_CollSeq 17 -#define OP_Function 18 -#define OP_BitAnd 82 /* same as TK_BITAND */ -#define OP_BitOr 83 /* same as TK_BITOR */ -#define OP_ShiftLeft 84 /* same as TK_LSHIFT */ -#define OP_ShiftRight 85 /* same as TK_RSHIFT */ -#define OP_AddImm 20 -#define OP_MustBeInt 21 -#define OP_RealAffinity 22 +#define OP_Concat 91 /* same as TK_CONCAT */ +#define OP_RowKey 92 +#define OP_BitNot 93 /* same as TK_BITNOT */ +#define OP_String8 94 /* same as TK_STRING */ +#define OP_RowData 95 +#define OP_Rowid 96 +#define OP_NullRow 97 +#define OP_Last 98 +#define OP_SorterSort 99 +#define OP_Sort 100 +#define OP_Rewind 101 +#define OP_SorterInsert 102 +#define OP_IdxInsert 103 +#define OP_IdxDelete 104 +#define OP_IdxRowid 105 +#define OP_IdxLT 106 +#define OP_IdxGE 107 +#define OP_Destroy 108 +#define OP_Clear 109 +#define OP_CreateIndex 110 +#define OP_CreateTable 111 +#define OP_ParseSchema 112 +#define OP_LoadAnalysis 113 +#define OP_DropTable 114 +#define OP_DropIndex 115 +#define OP_DropTrigger 116 +#define OP_IntegrityCk 117 +#define OP_RowSetAdd 118 +#define OP_RowSetRead 119 +#define OP_RowSetTest 120 +#define OP_Program 121 +#define OP_Param 122 +#define OP_FkCounter 123 +#define OP_FkIfZero 124 +#define OP_MemMax 125 +#define OP_IfPos 126 +#define OP_IfNeg 127 +#define OP_IfZero 128 +#define OP_AggFinal 129 +#define OP_Real 130 /* same as TK_FLOAT */ +#define OP_IncrVacuum 131 +#define OP_Expire 132 +#define OP_TableLock 133 +#define OP_VBegin 134 +#define OP_VCreate 135 +#define OP_VDestroy 136 +#define OP_VOpen 137 +#define OP_VColumn 138 +#define OP_VNext 139 +#define OP_VRename 140 #define OP_ToText 141 /* same as TK_TO_TEXT */ #define OP_ToBlob 142 /* same as TK_TO_BLOB */ #define OP_ToNumeric 143 /* same as TK_TO_NUMERIC*/ #define OP_ToInt 144 /* same as TK_TO_INT */ #define OP_ToReal 145 /* same as TK_TO_REAL */ -#define OP_Eq 76 /* same as TK_EQ */ -#define OP_Ne 75 /* same as TK_NE */ -#define OP_Lt 79 /* same as TK_LT */ -#define OP_Le 78 /* same as TK_LE */ -#define OP_Gt 77 /* same as TK_GT */ -#define OP_Ge 80 /* same as TK_GE */ -#define OP_Permutation 23 -#define OP_Compare 24 -#define OP_Jump 25 -#define OP_And 69 /* same as TK_AND */ -#define OP_Or 68 /* same as TK_OR */ -#define OP_Not 19 /* same as TK_NOT */ -#define OP_BitNot 93 /* same as TK_BITNOT */ -#define OP_Once 26 -#define OP_If 27 -#define OP_IfNot 28 -#define OP_IsNull 73 /* same as TK_ISNULL */ -#define OP_NotNull 74 /* same as TK_NOTNULL */ -#define OP_Column 29 -#define OP_Affinity 30 -#define OP_MakeRecord 31 -#define OP_Count 32 -#define OP_Savepoint 33 -#define OP_AutoCommit 34 -#define OP_Transaction 35 -#define OP_ReadCookie 36 -#define OP_SetCookie 37 -#define OP_VerifyCookie 38 -#define OP_OpenRead 39 -#define OP_OpenWrite 40 -#define OP_OpenAutoindex 41 -#define OP_OpenEphemeral 42 -#define OP_SorterOpen 43 -#define OP_OpenPseudo 44 -#define OP_Close 45 -#define OP_SeekLt 46 -#define OP_SeekLe 47 -#define OP_SeekGe 48 -#define OP_SeekGt 49 -#define OP_Seek 50 -#define OP_NotFound 51 -#define OP_Found 52 -#define OP_IsUnique 53 -#define OP_NotExists 54 -#define OP_Sequence 55 -#define OP_NewRowid 56 -#define OP_Insert 57 -#define OP_InsertInt 58 -#define OP_Delete 59 -#define OP_ResetCount 60 -#define OP_SorterCompare 61 -#define OP_SorterData 62 -#define OP_RowKey 63 -#define OP_RowData 64 -#define OP_Rowid 65 -#define OP_NullRow 66 -#define OP_Last 67 -#define OP_SorterSort 70 -#define OP_Sort 71 -#define OP_Rewind 72 -#define OP_SorterNext 81 -#define OP_Prev 92 -#define OP_Next 95 -#define OP_SorterInsert 96 -#define OP_IdxInsert 97 -#define OP_IdxDelete 98 -#define OP_IdxRowid 99 -#define OP_IdxLT 100 -#define OP_IdxGE 101 -#define OP_Destroy 102 -#define OP_Clear 103 -#define OP_CreateIndex 104 -#define OP_CreateTable 105 -#define OP_ParseSchema 106 -#define OP_LoadAnalysis 107 -#define OP_DropTable 108 -#define OP_DropIndex 109 -#define OP_DropTrigger 110 -#define OP_IntegrityCk 111 -#define OP_RowSetAdd 112 -#define OP_RowSetRead 113 -#define OP_RowSetTest 114 -#define OP_Program 115 -#define OP_Param 116 -#define OP_FkCounter 117 -#define OP_FkIfZero 118 -#define OP_MemMax 119 -#define OP_IfPos 120 -#define OP_IfNeg 121 -#define OP_IfZero 122 -#define OP_AggStep 123 -#define OP_AggFinal 124 -#define OP_Checkpoint 125 -#define OP_JournalMode 126 -#define OP_Vacuum 127 -#define OP_IncrVacuum 128 -#define OP_Expire 129 -#define OP_TableLock 131 -#define OP_VBegin 132 -#define OP_VCreate 133 -#define OP_VDestroy 134 -#define OP_VOpen 135 -#define OP_VFilter 136 -#define OP_VColumn 137 -#define OP_VNext 138 -#define OP_VRename 139 -#define OP_VUpdate 140 #define OP_Pagecount 146 #define OP_MaxPgcnt 147 #define OP_Trace 148 @@ -9078,24 +9148,24 @@ typedef struct VdbeOpList VdbeOpList; #define OPFLG_OUT2 0x0020 /* out2: P2 is an output */ #define OPFLG_OUT3 0x0040 /* out3: P3 is an output */ #define OPFLG_INITIALIZER {\ -/* 0 */ 0x00, 0x01, 0x01, 0x04, 0x04, 0x10, 0x00, 0x02,\ -/* 8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x24,\ -/* 16 */ 0x00, 0x00, 0x00, 0x24, 0x04, 0x05, 0x04, 0x00,\ -/* 24 */ 0x00, 0x01, 0x01, 0x05, 0x05, 0x00, 0x00, 0x00,\ -/* 32 */ 0x02, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,\ -/* 40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11,\ -/* 48 */ 0x11, 0x11, 0x08, 0x11, 0x11, 0x11, 0x11, 0x02,\ -/* 56 */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 64 */ 0x00, 0x02, 0x00, 0x01, 0x4c, 0x4c, 0x01, 0x01,\ -/* 72 */ 0x01, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\ -/* 80 */ 0x15, 0x01, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\ -/* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x01,\ -/* 96 */ 0x08, 0x08, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00,\ -/* 104 */ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 112 */ 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01, 0x08,\ -/* 120 */ 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00,\ -/* 128 */ 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 136 */ 0x01, 0x00, 0x01, 0x00, 0x00, 0x04, 0x04, 0x04,\ +/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,\ +/* 8 */ 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x01,\ +/* 16 */ 0x04, 0x04, 0x10, 0x24, 0x00, 0x02, 0x02, 0x02,\ +/* 24 */ 0x02, 0x02, 0x02, 0x00, 0x00, 0x24, 0x00, 0x00,\ +/* 32 */ 0x04, 0x05, 0x04, 0x00, 0x00, 0x01, 0x01, 0x05,\ +/* 40 */ 0x05, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,\ +/* 48 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,\ +/* 56 */ 0x11, 0x11, 0x11, 0x08, 0x11, 0x11, 0x11, 0x11,\ +/* 64 */ 0x02, 0x02, 0x00, 0x00, 0x4c, 0x4c, 0x00, 0x00,\ +/* 72 */ 0x00, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\ +/* 80 */ 0x15, 0x00, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\ +/* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x00, 0x24, 0x02, 0x00,\ +/* 96 */ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x08, 0x08,\ +/* 104 */ 0x00, 0x02, 0x01, 0x01, 0x02, 0x00, 0x02, 0x02,\ +/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x45,\ +/* 120 */ 0x15, 0x01, 0x02, 0x00, 0x01, 0x08, 0x05, 0x05,\ +/* 128 */ 0x05, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,\ +/* 136 */ 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x04, 0x04,\ /* 144 */ 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00,} /************** End of opcodes.h *********************************************/ @@ -9145,7 +9215,7 @@ SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, int); SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*); SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*); -SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetValue(Vdbe*, int, u8); +SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8); SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int); #ifndef SQLITE_OMIT_TRACE SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*); @@ -9259,8 +9329,20 @@ typedef struct PgHdr DbPage; /* ** Flags that make up the mask passed to sqlite3PagerAcquire(). */ -#define PAGER_ACQUIRE_NOCONTENT 0x01 /* Do not load data from disk */ -#define PAGER_ACQUIRE_READONLY 0x02 /* Read-only page is acceptable */ +#define PAGER_GET_NOCONTENT 0x01 /* Do not load data from disk */ +#define PAGER_GET_READONLY 0x02 /* Read-only page is acceptable */ + +/* +** Flags for sqlite3PagerSetFlags() +*/ +#define PAGER_SYNCHRONOUS_OFF 0x01 /* PRAGMA synchronous=OFF */ +#define PAGER_SYNCHRONOUS_NORMAL 0x02 /* PRAGMA synchronous=NORMAL */ +#define PAGER_SYNCHRONOUS_FULL 0x03 /* PRAGMA synchronous=FULL */ +#define PAGER_SYNCHRONOUS_MASK 0x03 /* Mask for three values above */ +#define PAGER_FULLFSYNC 0x04 /* PRAGMA fullfsync=ON */ +#define PAGER_CKPT_FULLFSYNC 0x08 /* PRAGMA checkpoint_fullfsync=ON */ +#define PAGER_CACHESPILL 0x10 /* PRAGMA cache_spill=ON */ +#define PAGER_FLAGS_MASK 0x1c /* All above except SYNCHRONOUS */ /* ** The remainder of this file contains the declarations of the functions @@ -9288,7 +9370,7 @@ SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int); SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int); SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64); SQLITE_PRIVATE void sqlite3PagerShrink(Pager*); -SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int,int); +SQLITE_PRIVATE void sqlite3PagerSetFlags(Pager*,unsigned); SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int); SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *, int); SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*); @@ -9917,7 +9999,6 @@ SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *); struct Db { char *zName; /* Name of this database */ Btree *pBt; /* The B*Tree structure for this database file */ - u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */ u8 safety_level; /* How aggressive at syncing data to disk */ Schema *pSchema; /* Pointer to database schema (possibly shared) */ }; @@ -10063,9 +10144,10 @@ struct sqlite3 { u8 busy; /* TRUE if currently initializing */ u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */ } init; - int activeVdbeCnt; /* Number of VDBEs currently executing */ - int writeVdbeCnt; /* Number of active VDBEs that are writing */ - int vdbeExecCnt; /* Number of nested calls to VdbeExec() */ + int nVdbeActive; /* Number of VDBEs currently running */ + int nVdbeRead; /* Number of active VDBEs that read or write */ + int nVdbeWrite; /* Number of active VDBEs that read and write */ + int nVdbeExec; /* Number of nested calls to VdbeExec() */ int nExtension; /* Number of loaded extensions */ void **aExtension; /* Array of shared library handles */ void (*xTrace)(void*,const char*); /* Trace function */ @@ -10086,8 +10168,6 @@ struct sqlite3 { void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*); void *pCollNeededArg; sqlite3_value *pErr; /* Most recent error message */ - char *zErrMsg; /* Most recent error message (UTF-8 encoded) */ - char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */ union { volatile int isInterrupted; /* True if sqlite3_interrupt has been called */ double notUsed1; /* Spacer */ @@ -10101,7 +10181,7 @@ struct sqlite3 { #ifndef SQLITE_OMIT_PROGRESS_CALLBACK int (*xProgress)(void *); /* The progress callback */ void *pProgressArg; /* Argument to the progress callback */ - int nProgressOps; /* Number of opcodes for progress callback */ + unsigned nProgressOps; /* Number of opcodes for progress callback */ #endif #ifndef SQLITE_OMIT_VIRTUALTABLE int nVTrans; /* Allocated size of aVTrans */ @@ -10119,6 +10199,7 @@ struct sqlite3 { int nSavepoint; /* Number of non-transaction savepoints */ int nStatement; /* Number of nested statement-transactions */ i64 nDeferredCons; /* Net deferred constraints this transaction. */ + i64 nDeferredImmCons; /* Net deferred immediate constraints */ int *pnBytesFreed; /* If not NULL, increment this in DbFree() */ #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY @@ -10150,30 +10231,34 @@ struct sqlite3 { */ #define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ #define SQLITE_InternChanges 0x00000002 /* Uncommitted Hash table changes */ -#define SQLITE_FullColNames 0x00000004 /* Show full column names on SELECT */ -#define SQLITE_ShortColNames 0x00000008 /* Show short columns names */ -#define SQLITE_CountRows 0x00000010 /* Count rows changed by INSERT, */ +#define SQLITE_FullFSync 0x00000004 /* Use full fsync on the backend */ +#define SQLITE_CkptFullFSync 0x00000008 /* Use full fsync for checkpoint */ +#define SQLITE_CacheSpill 0x00000010 /* OK to spill pager cache */ +#define SQLITE_FullColNames 0x00000020 /* Show full column names on SELECT */ +#define SQLITE_ShortColNames 0x00000040 /* Show short columns names */ +#define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */ /* DELETE, or UPDATE and return */ /* the count using a callback. */ -#define SQLITE_NullCallback 0x00000020 /* Invoke the callback once if the */ +#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */ /* result set is empty */ -#define SQLITE_SqlTrace 0x00000040 /* Debug print SQL as it executes */ -#define SQLITE_VdbeListing 0x00000080 /* Debug listings of VDBE programs */ -#define SQLITE_WriteSchema 0x00000100 /* OK to update SQLITE_MASTER */ -#define SQLITE_VdbeAddopTrace 0x00000200 /* Trace sqlite3VdbeAddOp() calls */ -#define SQLITE_IgnoreChecks 0x00000400 /* Do not enforce check constraints */ -#define SQLITE_ReadUncommitted 0x0000800 /* For shared-cache mode */ -#define SQLITE_LegacyFileFmt 0x00001000 /* Create new databases in format 1 */ -#define SQLITE_FullFSync 0x00002000 /* Use full fsync on the backend */ -#define SQLITE_CkptFullFSync 0x00004000 /* Use full fsync for checkpoint */ -#define SQLITE_RecoveryMode 0x00008000 /* Ignore schema errors */ -#define SQLITE_ReverseOrder 0x00010000 /* Reverse unordered SELECTs */ -#define SQLITE_RecTriggers 0x00020000 /* Enable recursive triggers */ -#define SQLITE_ForeignKeys 0x00040000 /* Enforce foreign key constraints */ -#define SQLITE_AutoIndex 0x00080000 /* Enable automatic indexes */ -#define SQLITE_PreferBuiltin 0x00100000 /* Preference to built-in funcs */ -#define SQLITE_LoadExtension 0x00200000 /* Enable load_extension */ -#define SQLITE_EnableTrigger 0x00400000 /* True to enable triggers */ +#define SQLITE_SqlTrace 0x00000200 /* Debug print SQL as it executes */ +#define SQLITE_VdbeListing 0x00000400 /* Debug listings of VDBE programs */ +#define SQLITE_WriteSchema 0x00000800 /* OK to update SQLITE_MASTER */ +#define SQLITE_VdbeAddopTrace 0x00001000 /* Trace sqlite3VdbeAddOp() calls */ +#define SQLITE_IgnoreChecks 0x00002000 /* Do not enforce check constraints */ +#define SQLITE_ReadUncommitted 0x0004000 /* For shared-cache mode */ +#define SQLITE_LegacyFileFmt 0x00008000 /* Create new databases in format 1 */ +#define SQLITE_RecoveryMode 0x00010000 /* Ignore schema errors */ +#define SQLITE_ReverseOrder 0x00020000 /* Reverse unordered SELECTs */ +#define SQLITE_RecTriggers 0x00040000 /* Enable recursive triggers */ +#define SQLITE_ForeignKeys 0x00080000 /* Enforce foreign key constraints */ +#define SQLITE_AutoIndex 0x00100000 /* Enable automatic indexes */ +#define SQLITE_PreferBuiltin 0x00200000 /* Preference to built-in funcs */ +#define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */ +#define SQLITE_EnableTrigger 0x00800000 /* True to enable triggers */ +#define SQLITE_DeferFKs 0x01000000 /* Defer all FK constraints */ +#define SQLITE_QueryOnly 0x02000000 /* Disable database changes */ + /* ** Bits of the sqlite3.dbOptFlags field that are used by the @@ -10190,6 +10275,9 @@ struct sqlite3 { #define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */ #define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */ #define SQLITE_Transitive 0x0200 /* Transitive constraints */ +#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */ +#define SQLITE_Stat3 0x0800 /* Use the SQLITE_STAT3 table */ +#define SQLITE_AdjustOutEst 0x1000 /* Adjust output estimates using WHERE */ #define SQLITE_AllOpts 0xffff /* All optimizations */ /* @@ -10223,8 +10311,7 @@ struct sqlite3 { */ struct FuncDef { i16 nArg; /* Number of arguments. -1 means unlimited */ - u8 iPrefEnc; /* Preferred text encoding (SQLITE_UTF8, 16LE, 16BE) */ - u8 flags; /* Some combination of SQLITE_FUNC_* */ + u16 funcFlags; /* Some combination of SQLITE_FUNC_* */ void *pUserData; /* User data parameter */ FuncDef *pNext; /* Next function with same name */ void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */ @@ -10260,14 +10347,16 @@ struct FuncDestructor { ** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. There ** are assert() statements in the code to verify this. */ -#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */ -#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */ -#define SQLITE_FUNC_EPHEM 0x04 /* Ephemeral. Delete with VDBE */ -#define SQLITE_FUNC_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */ -#define SQLITE_FUNC_COUNT 0x10 /* Built-in count(*) aggregate */ -#define SQLITE_FUNC_COALESCE 0x20 /* Built-in coalesce() or ifnull() function */ -#define SQLITE_FUNC_LENGTH 0x40 /* Built-in length() function */ -#define SQLITE_FUNC_TYPEOF 0x80 /* Built-in typeof() function */ +#define SQLITE_FUNC_ENCMASK 0x003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */ +#define SQLITE_FUNC_LIKE 0x004 /* Candidate for the LIKE optimization */ +#define SQLITE_FUNC_CASE 0x008 /* Case-sensitive LIKE-type function */ +#define SQLITE_FUNC_EPHEM 0x010 /* Ephemeral. Delete with VDBE */ +#define SQLITE_FUNC_NEEDCOLL 0x020 /* sqlite3GetFuncCollSeq() might be called */ +#define SQLITE_FUNC_LENGTH 0x040 /* Built-in length() function */ +#define SQLITE_FUNC_TYPEOF 0x080 /* Built-in typeof() function */ +#define SQLITE_FUNC_COUNT 0x100 /* Built-in count(*) aggregate */ +#define SQLITE_FUNC_COALESCE 0x200 /* Built-in coalesce() or ifnull() */ +#define SQLITE_FUNC_UNLIKELY 0x400 /* Built-in unlikely() function */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are @@ -10295,18 +10384,18 @@ struct FuncDestructor { ** parameter. */ #define FUNCTION(zName, nArg, iArg, bNC, xFunc) \ - {nArg, SQLITE_UTF8, (bNC*SQLITE_FUNC_NEEDCOLL), \ + {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0} #define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \ - {nArg, SQLITE_UTF8, (bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags, \ + {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags, \ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0} #define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \ - {nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \ + {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ pArg, 0, xFunc, 0, 0, #zName, 0, 0} #define LIKEFUNC(zName, nArg, arg, flags) \ - {nArg, SQLITE_UTF8, flags, (void *)arg, 0, likeFunc, 0, 0, #zName, 0, 0} + {nArg, SQLITE_UTF8|flags, (void *)arg, 0, likeFunc, 0, 0, #zName, 0, 0} #define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \ - {nArg, SQLITE_UTF8, nc*SQLITE_FUNC_NEEDCOLL, \ + {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \ SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0,0} /* @@ -10318,6 +10407,7 @@ struct FuncDestructor { struct Savepoint { char *zName; /* Savepoint name (nul-terminated) */ i64 nDeferredCons; /* Number of deferred fk violations */ + i64 nDeferredImmCons; /* Number of deferred imm fk. */ Savepoint *pNext; /* Parent savepoint (if any) */ }; @@ -10354,7 +10444,8 @@ struct Column { char *zColl; /* Collating sequence. If NULL, use the default */ u8 notNull; /* An OE_ code for handling a NOT NULL constraint */ char affinity; /* One of the SQLITE_AFF_... values */ - u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */ + u8 szEst; /* Estimated size of this column. INT==1 */ + u8 colFlags; /* Boolean properties. See COLFLAG_ defines below */ }; /* Allowed values for Column.colFlags: @@ -10518,6 +10609,7 @@ struct Table { i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */ i16 nCol; /* Number of columns in this table */ u16 nRef; /* Number of pointers to this Table */ + LogEst szTabRow; /* Estimated size of each table row in bytes */ u8 tabFlags; /* Mask of TF_* values */ u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ #ifndef SQLITE_OMIT_ALTERTABLE @@ -10629,19 +10721,23 @@ struct FKey { #define OE_SetDflt 8 /* Set the foreign key value to its default */ #define OE_Cascade 9 /* Cascade the changes */ -#define OE_Default 99 /* Do whatever the default action is */ +#define OE_Default 10 /* Do whatever the default action is */ /* ** An instance of the following structure is passed as the first ** argument to sqlite3VdbeKeyCompare and is used to control the ** comparison of the two index keys. +** +** Note that aSortOrder[] and aColl[] have nField+1 slots. There +** are nField slots for the columns of an index then one extra slot +** for the rowid at the end. */ struct KeyInfo { sqlite3 *db; /* The database connection */ u8 enc; /* Text encoding - one of the SQLITE_UTF* values */ - u16 nField; /* Number of entries in aColl[] */ - u8 *aSortOrder; /* Sort order for each column. May be NULL */ + u16 nField; /* Maximum index for aColl[] and aSortOrder[] */ + u8 *aSortOrder; /* Sort order for each column. */ CollSeq *aColl[1]; /* Collating sequence for each term of the key */ }; @@ -10710,14 +10806,18 @@ struct Index { Schema *pSchema; /* Schema containing this index */ u8 *aSortOrder; /* for each column: True==DESC, False==ASC */ char **azColl; /* Array of collation sequence names for index */ + Expr *pPartIdxWhere; /* WHERE clause for partial indices */ int tnum; /* DB Page containing root of this index */ + LogEst szIdxRow; /* Estimated average row size in bytes */ u16 nColumn; /* Number of columns in table used by this index */ u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */ unsigned bUnordered:1; /* Use this index for == or IN queries only */ -#ifdef SQLITE_ENABLE_STAT3 + unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 int nSample; /* Number of elements in aSample[] */ - tRowcnt avgEq; /* Average nEq value for key values not in aSample */ + int nSampleCol; /* Size of IndexSample.anEq[] and so on */ + tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */ IndexSample *aSample; /* Samples of the left-most key */ #endif }; @@ -10728,16 +10828,11 @@ struct Index { ** analyze.c source file for additional information. */ struct IndexSample { - union { - char *z; /* Value if eType is SQLITE_TEXT or SQLITE_BLOB */ - double r; /* Value if eType is SQLITE_FLOAT */ - i64 i; /* Value if eType is SQLITE_INTEGER */ - } u; - u8 eType; /* SQLITE_NULL, SQLITE_INTEGER ... etc. */ - int nByte; /* Size in byte of text or blob. */ - tRowcnt nEq; /* Est. number of rows where the key equals this sample */ - tRowcnt nLt; /* Est. number of rows where key is less than this sample */ - tRowcnt nDLt; /* Est. number of distinct keys less than this sample */ + void *p; /* Pointer to sampled record */ + int n; /* Size of record in bytes */ + tRowcnt *anEq; /* Est. number of rows where the key equals this sample */ + tRowcnt *anLt; /* Est. number of rows where key is less than this sample */ + tRowcnt *anDLt; /* Est. number of distinct keys less than this sample */ }; /* @@ -10878,7 +10973,7 @@ typedef int ynVar; struct Expr { u8 op; /* Operation performed by this node */ char affinity; /* The affinity of the column or 0 if not a column */ - u16 flags; /* Various flags. EP_* See below */ + u32 flags; /* Various flags. EP_* See below */ union { char *zToken; /* Token value. Zero terminated and dequoted */ int iValue; /* Non-negative integer value if EP_IntValue */ @@ -10892,8 +10987,8 @@ struct Expr { Expr *pLeft; /* Left subnode */ Expr *pRight; /* Right subnode */ union { - ExprList *pList; /* Function arguments or in " IN ( IN (