summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/global/qlogging.cpp5
-rw-r--r--src/corelib/global/qtypeinfo.h4
-rw-r--r--src/corelib/io/qprocess_win.cpp6
-rw-r--r--src/corelib/io/qwindowspipereader.cpp154
-rw-r--r--src/corelib/io/qwindowspipereader_p.h32
-rw-r--r--src/corelib/io/qwindowspipewriter.cpp236
-rw-r--r--src/corelib/io/qwindowspipewriter_p.h70
-rw-r--r--src/network/socket/qlocalsocket_win.cpp1
-rw-r--r--src/widgets/styles/qmacstyle_mac.mm90
-rw-r--r--src/widgets/styles/qmacstyle_mac_p_p.h2
-rw-r--r--src/widgets/styles/qwindowsstyle_p.h1
-rw-r--r--src/widgets/styles/qwindowsxpstyle_p.h1
-rw-r--r--src/widgets/widgets/qtoolbarextension_p.h1
13 files changed, 367 insertions, 236 deletions
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index ca38d672c3..e341b3ecfd 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -96,6 +96,11 @@ extern char *__progname;
#if defined(Q_OS_LINUX) && (defined(__GLIBC__) || __has_include(<sys/syscall.h>))
# include <sys/syscall.h>
+
+# if defined(Q_OS_ANDROID) && !defined(SYS_gettid)
+# define SYS_gettid __NR_gettid
+# endif
+
static long qt_gettid()
{
// no error handling
diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h
index b42e5998fc..f5fc311a22 100644
--- a/src/corelib/global/qtypeinfo.h
+++ b/src/corelib/global/qtypeinfo.h
@@ -111,14 +111,14 @@ public:
*/
// apply defaults for a generic QTypeInfo<T> that didn't provide the new values
template <typename T, typename = void>
-struct QTypeInfoQuery : QTypeInfo<T>
+struct QTypeInfoQuery : public QTypeInfo<T>
{
enum { isRelocatable = !QTypeInfo<T>::isStatic };
};
// if QTypeInfo<T>::isRelocatable exists, use it
template <typename T>
-struct QTypeInfoQuery<T, typename QtPrivate::QEnableIf<QTypeInfo<T>::isRelocatable || true>::Type> : QTypeInfo<T>
+struct QTypeInfoQuery<T, typename QtPrivate::QEnableIf<QTypeInfo<T>::isRelocatable || true>::Type> : public QTypeInfo<T>
{};
/*!
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index 98ada82446..e7cd9d9a17 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -666,10 +666,7 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
QIncrementalSleepTimer timer(msecs);
forever {
- // Check if we have any data pending: the pipe writer has
- // bytes waiting to written, or it has written data since the
- // last time we called stdinChannel.writer->waitForWrite().
- bool pendingDataInPipe = stdinChannel.writer && (stdinChannel.writer->bytesToWrite() || stdinChannel.writer->hadWritten());
+ bool pendingDataInPipe = stdinChannel.writer && stdinChannel.writer->bytesToWrite();
// If we don't have pending data, and our write buffer is
// empty, we fail.
@@ -797,7 +794,6 @@ qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen)
stdinChannel.writer = new QWindowsPipeWriter(stdinChannel.pipe[1], q);
QObjectPrivate::connect(stdinChannel.writer, &QWindowsPipeWriter::canWrite,
this, &QProcessPrivate::_q_canWrite);
- stdinChannel.writer->start();
}
return stdinChannel.writer->write(data, maxlen);
diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp
index f0d6417483..735386ce16 100644
--- a/src/corelib/io/qwindowspipereader.cpp
+++ b/src/corelib/io/qwindowspipereader.cpp
@@ -32,28 +32,40 @@
****************************************************************************/
#include "qwindowspipereader_p.h"
-#include "qwinoverlappedionotifier_p.h"
-#include <qdebug.h>
+#include "qiodevice_p.h"
#include <qelapsedtimer.h>
-#include <qeventloop.h>
QT_BEGIN_NAMESPACE
+QWindowsPipeReader::Overlapped::Overlapped(QWindowsPipeReader *reader)
+ : pipeReader(reader)
+{
+}
+
+void QWindowsPipeReader::Overlapped::clear()
+{
+ ZeroMemory(this, sizeof(OVERLAPPED));
+}
+
+
QWindowsPipeReader::QWindowsPipeReader(QObject *parent)
: QObject(parent),
handle(INVALID_HANDLE_VALUE),
+ overlapped(this),
readBufferMaxSize(0),
actualReadBufferSize(0),
stopped(true),
readSequenceStarted(false),
+ notifiedCalled(false),
pipeBroken(false),
- readyReadEmitted(false)
+ readyReadPending(false),
+ inReadyRead(false)
{
- dataReadNotifier = new QWinOverlappedIoNotifier(this);
- connect(dataReadNotifier, &QWinOverlappedIoNotifier::notified, this, &QWindowsPipeReader::notified);
+ connect(this, &QWindowsPipeReader::_q_queueReadyRead,
+ this, &QWindowsPipeReader::emitPendingReadyRead, Qt::QueuedConnection);
}
-static bool qt_cancelIo(HANDLE handle, OVERLAPPED *overlapped)
+bool qt_cancelIo(HANDLE handle, OVERLAPPED *overlapped)
{
typedef BOOL (WINAPI *PtrCancelIoEx)(HANDLE, LPOVERLAPPED);
static PtrCancelIoEx ptrCancelIoEx = 0;
@@ -82,12 +94,6 @@ void QWindowsPipeReader::setHandle(HANDLE hPipeReadEnd)
actualReadBufferSize = 0;
handle = hPipeReadEnd;
pipeBroken = false;
- readyReadEmitted = false;
- stopped = false;
- if (hPipeReadEnd != INVALID_HANDLE_VALUE) {
- dataReadNotifier->setHandle(hPipeReadEnd);
- dataReadNotifier->setEnabled(true);
- }
}
/*!
@@ -98,19 +104,15 @@ void QWindowsPipeReader::stop()
{
stopped = true;
if (readSequenceStarted) {
- if (qt_cancelIo(handle, &overlapped)) {
- dataReadNotifier->waitForNotified(-1, &overlapped);
- } else {
+ if (!qt_cancelIo(handle, &overlapped)) {
const DWORD dwError = GetLastError();
if (dwError != ERROR_NOT_FOUND) {
qErrnoWarning(dwError, "QWindowsPipeReader: qt_cancelIo on handle %x failed.",
handle);
}
}
+ waitForNotification(-1);
}
- readSequenceStarted = false;
- dataReadNotifier->setEnabled(false);
- handle = INVALID_HANDLE_VALUE;
}
/*!
@@ -168,11 +170,10 @@ bool QWindowsPipeReader::canReadLine() const
\internal
Will be called whenever the read operation completes.
*/
-void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode,
- OVERLAPPED *notifiedOverlapped)
+void QWindowsPipeReader::notified(DWORD errorCode, DWORD numberOfBytesRead)
{
- if (&overlapped != notifiedOverlapped)
- return;
+ notifiedCalled = true;
+ readSequenceStarted = false;
switch (errorCode) {
case ERROR_SUCCESS:
@@ -196,8 +197,6 @@ void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode,
break;
}
- readSequenceStarted = false;
-
// After the reader was stopped, the only reason why this function can be called is the
// completion of a cancellation. No signals should be emitted, and no new read sequence should
// be started in this case.
@@ -212,13 +211,15 @@ void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode,
actualReadBufferSize += numberOfBytesRead;
readBuffer.truncate(actualReadBufferSize);
startAsyncRead();
- readyReadEmitted = true;
- emit readyRead();
+ if (!readyReadPending) {
+ readyReadPending = true;
+ emit _q_queueReadyRead(QWindowsPipeReader::QPrivateSignal());
+ }
}
/*!
\internal
- Reads data from the socket into the readbuffer
+ Reads data from the pipe into the readbuffer.
*/
void QWindowsPipeReader::startAsyncRead()
{
@@ -238,43 +239,41 @@ void QWindowsPipeReader::startAsyncRead()
char *ptr = readBuffer.reserve(bytesToRead);
+ stopped = false;
readSequenceStarted = true;
- ZeroMemory(&overlapped, sizeof(overlapped));
- if (ReadFile(handle, ptr, bytesToRead, NULL, &overlapped)) {
- // We get notified by the QWinOverlappedIoNotifier - even in the synchronous case.
- return;
- } else {
+ overlapped.clear();
+ if (!ReadFileEx(handle, ptr, bytesToRead, &overlapped, &readFileCompleted)) {
+ readSequenceStarted = false;
+
const DWORD dwError = GetLastError();
switch (dwError) {
- case ERROR_IO_PENDING:
- // This is not an error. We're getting notified, when data arrives.
- return;
- case ERROR_MORE_DATA:
- // This is not an error. The synchronous read succeeded.
- // We're connected to a message mode pipe and the message
- // didn't fit into the pipe's system buffer.
- // We're getting notified by the QWinOverlappedIoNotifier.
- break;
case ERROR_BROKEN_PIPE:
case ERROR_PIPE_NOT_CONNECTED:
- {
- // It may happen, that the other side closes the connection directly
- // after writing data. Then we must set the appropriate socket state.
- readSequenceStarted = false;
- pipeBroken = true;
- emit pipeClosed();
- return;
- }
+ // It may happen, that the other side closes the connection directly
+ // after writing data. Then we must set the appropriate socket state.
+ pipeBroken = true;
+ emit pipeClosed();
+ break;
default:
- readSequenceStarted = false;
emit winError(dwError, QLatin1String("QWindowsPipeReader::startAsyncRead"));
- return;
+ break;
}
}
}
/*!
\internal
+ Called when ReadFileEx finished the read operation.
+ */
+void QWindowsPipeReader::readFileCompleted(DWORD errorCode, DWORD numberOfBytesTransfered,
+ OVERLAPPED *overlappedBase)
+{
+ Overlapped *overlapped = static_cast<Overlapped *>(overlappedBase);
+ overlapped->pipeReader->notified(errorCode, numberOfBytesTransfered);
+}
+
+/*!
+ \internal
Returns the number of available bytes in the pipe.
Sets QWindowsPipeReader::pipeBroken to true if the connection is broken.
*/
@@ -292,17 +291,60 @@ DWORD QWindowsPipeReader::checkPipeState()
return 0;
}
+bool QWindowsPipeReader::waitForNotification(int timeout)
+{
+ QElapsedTimer t;
+ t.start();
+ notifiedCalled = false;
+ int msecs = timeout;
+ while (SleepEx(msecs == -1 ? INFINITE : msecs, TRUE) == WAIT_IO_COMPLETION) {
+ if (notifiedCalled)
+ return true;
+
+ // Some other I/O completion routine was called. Wait some more.
+ msecs = qt_subtract_from_timeout(timeout, t.elapsed());
+ if (!msecs)
+ break;
+ }
+ return notifiedCalled;
+}
+
+void QWindowsPipeReader::emitPendingReadyRead()
+{
+ if (readyReadPending) {
+ readyReadPending = false;
+ inReadyRead = true;
+ emit readyRead();
+ inReadyRead = false;
+ }
+}
+
/*!
Waits for the completion of the asynchronous read operation.
- Returns \c true, if we've emitted the readyRead signal.
+ Returns \c true, if we've emitted the readyRead signal (non-recursive case)
+ or readyRead will be emitted by the event loop (recursive case).
*/
bool QWindowsPipeReader::waitForReadyRead(int msecs)
{
if (!readSequenceStarted)
return false;
- readyReadEmitted = false;
- dataReadNotifier->waitForNotified(msecs, &overlapped);
- return readyReadEmitted;
+
+ if (readyReadPending) {
+ if (!inReadyRead)
+ emitPendingReadyRead();
+ return true;
+ }
+
+ if (!waitForNotification(msecs))
+ return false;
+
+ if (readyReadPending) {
+ if (!inReadyRead)
+ emitPendingReadyRead();
+ return true;
+ }
+
+ return false;
}
/*!
diff --git a/src/corelib/io/qwindowspipereader_p.h b/src/corelib/io/qwindowspipereader_p.h
index c8a66d9511..44009877f2 100644
--- a/src/corelib/io/qwindowspipereader_p.h
+++ b/src/corelib/io/qwindowspipereader_p.h
@@ -45,7 +45,6 @@
// We mean it.
//
-#include <qbytearray.h>
#include <qobject.h>
#include <private/qringbuffer_p.h>
@@ -53,9 +52,6 @@
QT_BEGIN_NAMESPACE
-
-class QWinOverlappedIoNotifier;
-
class Q_CORE_EXPORT QWindowsPipeReader : public QObject
{
Q_OBJECT
@@ -64,6 +60,7 @@ public:
~QWindowsPipeReader();
void setHandle(HANDLE hPipeReadEnd);
+ void startAsyncRead();
void stop();
void setMaxReadBufferSize(qint64 size) { readBufferMaxSize = size; }
@@ -76,31 +73,42 @@ public:
bool waitForReadyRead(int msecs);
bool waitForPipeClosed(int msecs);
- void startAsyncRead();
bool isReadOperationActive() const { return readSequenceStarted; }
Q_SIGNALS:
void winError(ulong, const QString &);
void readyRead();
void pipeClosed();
-
-private Q_SLOTS:
- void notified(quint32 numberOfBytesRead, quint32 errorCode, OVERLAPPED *notifiedOverlapped);
+ void _q_queueReadyRead(QPrivateSignal);
private:
+ static void CALLBACK readFileCompleted(DWORD errorCode, DWORD numberOfBytesTransfered,
+ OVERLAPPED *overlappedBase);
+ void notified(DWORD errorCode, DWORD numberOfBytesRead);
DWORD checkPipeState();
+ bool waitForNotification(int timeout);
+ void emitPendingReadyRead();
+
+ class Overlapped : public OVERLAPPED
+ {
+ Q_DISABLE_COPY(Overlapped)
+ public:
+ explicit Overlapped(QWindowsPipeReader *reader);
+ void clear();
+ QWindowsPipeReader *pipeReader;
+ };
-private:
HANDLE handle;
- OVERLAPPED overlapped;
- QWinOverlappedIoNotifier *dataReadNotifier;
+ Overlapped overlapped;
qint64 readBufferMaxSize;
QRingBuffer readBuffer;
qint64 actualReadBufferSize;
bool stopped;
bool readSequenceStarted;
+ bool notifiedCalled;
bool pipeBroken;
- bool readyReadEmitted;
+ bool readyReadPending;
+ bool inReadyRead;
};
QT_END_NAMESPACE
diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp
index 5b11ba6112..ff92ca763e 100644
--- a/src/corelib/io/qwindowspipewriter.cpp
+++ b/src/corelib/io/qwindowspipewriter.cpp
@@ -32,141 +32,177 @@
****************************************************************************/
#include "qwindowspipewriter_p.h"
+#include "qiodevice_p.h"
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_THREAD
+extern bool qt_cancelIo(HANDLE handle, OVERLAPPED *overlapped); // from qwindowspipereader.cpp
-QWindowsPipeWriter::QWindowsPipeWriter(HANDLE pipe, QObject * parent)
- : QThread(parent),
- writePipe(pipe),
- quitNow(false),
- hasWritten(false)
+
+QWindowsPipeWriter::Overlapped::Overlapped(QWindowsPipeWriter *pipeWriter)
+ : pipeWriter(pipeWriter)
+{
+}
+
+void QWindowsPipeWriter::Overlapped::clear()
{
+ ZeroMemory(this, sizeof(OVERLAPPED));
+}
+
+
+QWindowsPipeWriter::QWindowsPipeWriter(HANDLE pipeWriteEnd, QObject *parent)
+ : QObject(parent),
+ handle(pipeWriteEnd),
+ overlapped(this),
+ numberOfBytesToWrite(0),
+ pendingBytesWrittenValue(0),
+ stopped(true),
+ writeSequenceStarted(false),
+ notifiedCalled(false),
+ bytesWrittenPending(false),
+ inBytesWritten(false)
+{
+ connect(this, &QWindowsPipeWriter::_q_queueBytesWritten,
+ this, &QWindowsPipeWriter::emitPendingBytesWrittenValue, Qt::QueuedConnection);
}
QWindowsPipeWriter::~QWindowsPipeWriter()
{
- lock.lock();
- quitNow = true;
- waitCondition.wakeOne();
- lock.unlock();
- if (!wait(30000))
- terminate();
+ stop();
}
bool QWindowsPipeWriter::waitForWrite(int msecs)
{
- QMutexLocker locker(&lock);
- bool hadWritten = hasWritten;
- hasWritten = false;
- if (hadWritten)
+ if (!writeSequenceStarted)
+ return false;
+
+ if (bytesWrittenPending) {
+ if (!inBytesWritten)
+ emitPendingBytesWrittenValue();
return true;
- if (!waitCondition.wait(&lock, msecs))
+ }
+
+ if (!waitForNotification(msecs))
return false;
- hadWritten = hasWritten;
- hasWritten = false;
- return hadWritten;
+
+ if (bytesWrittenPending) {
+ if (!inBytesWritten)
+ emitPendingBytesWrittenValue();
+ return true;
+ }
+
+ return false;
}
-qint64 QWindowsPipeWriter::write(const char *ptr, qint64 maxlen)
+qint64 QWindowsPipeWriter::bytesToWrite() const
{
- if (!isRunning())
- return -1;
-
- QMutexLocker locker(&lock);
- data.append(ptr, maxlen);
- waitCondition.wakeOne();
- return maxlen;
+ return numberOfBytesToWrite;
}
-class QPipeWriterOverlapped
+void QWindowsPipeWriter::emitPendingBytesWrittenValue()
{
-public:
- QPipeWriterOverlapped()
- {
- overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (bytesWrittenPending) {
+ bytesWrittenPending = false;
+ const qint64 bytes = pendingBytesWrittenValue;
+ pendingBytesWrittenValue = 0;
+
+ inBytesWritten = true;
+ emit bytesWritten(bytes);
+ inBytesWritten = false;
+ emit canWrite();
}
+}
- ~QPipeWriterOverlapped()
- {
- CloseHandle(overlapped.hEvent);
- }
+void QWindowsPipeWriter::writeFileCompleted(DWORD errorCode, DWORD numberOfBytesTransfered,
+ OVERLAPPED *overlappedBase)
+{
+ Overlapped *overlapped = static_cast<Overlapped *>(overlappedBase);
+ overlapped->pipeWriter->notified(errorCode, numberOfBytesTransfered);
+}
- void prepare()
- {
- const HANDLE hEvent = overlapped.hEvent;
- ZeroMemory(&overlapped, sizeof overlapped);
- overlapped.hEvent = hEvent;
+/*!
+ \internal
+ Will be called whenever the write operation completes.
+ */
+void QWindowsPipeWriter::notified(DWORD errorCode, DWORD numberOfBytesWritten)
+{
+ notifiedCalled = true;
+ writeSequenceStarted = false;
+ numberOfBytesToWrite = 0;
+
+ switch (errorCode) {
+ case ERROR_SUCCESS:
+ break;
+ case ERROR_OPERATION_ABORTED:
+ if (stopped)
+ break;
+ // fall through
+ default:
+ qErrnoWarning(errorCode, "QWindowsPipeWriter: asynchronous write failed.");
+ break;
}
- OVERLAPPED *operator&()
- {
- return &overlapped;
+ // After the writer was stopped, the only reason why this function can be called is the
+ // completion of a cancellation. No signals should be emitted, and no new write sequence should
+ // be started in this case.
+ if (stopped)
+ return;
+
+ pendingBytesWrittenValue += qint64(numberOfBytesWritten);
+ if (!bytesWrittenPending) {
+ bytesWrittenPending = true;
+ emit _q_queueBytesWritten(QWindowsPipeWriter::QPrivateSignal());
}
+}
-private:
- OVERLAPPED overlapped;
-};
+bool QWindowsPipeWriter::waitForNotification(int timeout)
+{
+ QElapsedTimer t;
+ t.start();
+ notifiedCalled = false;
+ int msecs = timeout;
+ while (SleepEx(msecs == -1 ? INFINITE : msecs, TRUE) == WAIT_IO_COMPLETION) {
+ if (notifiedCalled)
+ return true;
+
+ // Some other I/O completion routine was called. Wait some more.
+ msecs = qt_subtract_from_timeout(timeout, t.elapsed());
+ if (!msecs)
+ break;
+ }
+ return notifiedCalled;
+}
-void QWindowsPipeWriter::run()
+qint64 QWindowsPipeWriter::write(const char *ptr, qint64 maxlen)
{
- QPipeWriterOverlapped overl;
- forever {
- lock.lock();
- while(data.isEmpty() && (!quitNow)) {
- waitCondition.wakeOne();
- waitCondition.wait(&lock);
- }
+ if (writeSequenceStarted)
+ return 0;
+
+ overlapped.clear();
+ numberOfBytesToWrite = maxlen;
+ stopped = false;
+ writeSequenceStarted = true;
+ if (!WriteFileEx(handle, ptr, maxlen, &overlapped, &writeFileCompleted)) {
+ writeSequenceStarted = false;
+ qErrnoWarning("QWindowsPipeWriter::write failed.");
+ }
- if (quitNow) {
- lock.unlock();
- quitNow = false;
- break;
- }
+ return maxlen;
+}
- QByteArray copy = data;
-
- lock.unlock();
-
- const char *ptrData = copy.data();
- qint64 maxlen = copy.size();
- qint64 totalWritten = 0;
- overl.prepare();
- while ((!quitNow) && totalWritten < maxlen) {
- DWORD written = 0;
- if (!WriteFile(writePipe, ptrData + totalWritten,
- maxlen - totalWritten, &written, &overl)) {
- const DWORD writeError = GetLastError();
- if (writeError == 0xE8/*NT_STATUS_INVALID_USER_BUFFER*/) {
- // give the os a rest
- msleep(100);
- continue;
- }
- if (writeError != ERROR_IO_PENDING) {
- qErrnoWarning(writeError, "QWindowsPipeWriter: async WriteFile failed.");
- return;
- }
- if (!GetOverlappedResult(writePipe, &overl, &written, TRUE)) {
- qErrnoWarning(GetLastError(), "QWindowsPipeWriter: GetOverlappedResult failed.");
- return;
- }
+void QWindowsPipeWriter::stop()
+{
+ stopped = true;
+ if (writeSequenceStarted) {
+ if (!qt_cancelIo(handle, &overlapped)) {
+ const DWORD dwError = GetLastError();
+ if (dwError != ERROR_NOT_FOUND) {
+ qErrnoWarning(dwError, "QWindowsPipeWriter: qt_cancelIo on handle %x failed.",
+ handle);
}
- totalWritten += written;
-#if defined QPIPEWRITER_DEBUG
- qDebug("QWindowsPipeWriter::run() wrote %d %d/%d bytes",
- written, int(totalWritten), int(maxlen));
-#endif
- lock.lock();
- data.remove(0, written);
- hasWritten = true;
- lock.unlock();
}
- emit bytesWritten(totalWritten);
- emit canWrite();
+ waitForNotification(-1);
}
}
-#endif //QT_NO_THREAD
-
QT_END_NAMESPACE
diff --git a/src/corelib/io/qwindowspipewriter_p.h b/src/corelib/io/qwindowspipewriter_p.h
index 78d43e6efe..808d303262 100644
--- a/src/corelib/io/qwindowspipewriter_p.h
+++ b/src/corelib/io/qwindowspipewriter_p.h
@@ -46,16 +46,11 @@
//
#include <qelapsedtimer.h>
-#include <qthread.h>
-#include <qmutex.h>
-#include <qwaitcondition.h>
+#include <qobject.h>
#include <qt_windows.h>
QT_BEGIN_NAMESPACE
-
-#ifndef QT_NO_THREAD
-
#define SLEEPMIN 10
#define SLEEPMAX 500
@@ -104,45 +99,50 @@ private:
int nextSleep;
};
-class Q_CORE_EXPORT QWindowsPipeWriter : public QThread
+class Q_CORE_EXPORT QWindowsPipeWriter : public QObject
{
Q_OBJECT
-
-Q_SIGNALS:
- void canWrite();
- void bytesWritten(qint64 bytes);
-
public:
- explicit QWindowsPipeWriter(HANDLE writePipe, QObject * parent = 0);
+ explicit QWindowsPipeWriter(HANDLE pipeWriteEnd, QObject *parent = 0);
~QWindowsPipeWriter();
- bool waitForWrite(int msecs);
qint64 write(const char *data, qint64 maxlen);
+ void stop();
+ bool waitForWrite(int msecs);
+ qint64 bytesToWrite() const;
- qint64 bytesToWrite() const
- {
- QMutexLocker locker(&lock);
- return data.size();
- }
-
- bool hadWritten() const
- {
- return hasWritten;
- }
-
-protected:
- void run();
+Q_SIGNALS:
+ void canWrite();
+ void bytesWritten(qint64 bytes);
+ void _q_queueBytesWritten(QPrivateSignal);
private:
- QByteArray data;
- QWaitCondition waitCondition;
- mutable QMutex lock;
- HANDLE writePipe;
- volatile bool quitNow;
- bool hasWritten;
-};
+ static void CALLBACK writeFileCompleted(DWORD errorCode, DWORD numberOfBytesTransfered,
+ OVERLAPPED *overlappedBase);
+ void notified(DWORD errorCode, DWORD numberOfBytesWritten);
+ bool waitForNotification(int timeout);
+ void emitPendingBytesWrittenValue();
-#endif //QT_NO_THREAD
+ class Overlapped : public OVERLAPPED
+ {
+ Q_DISABLE_COPY(Overlapped)
+ public:
+ explicit Overlapped(QWindowsPipeWriter *pipeWriter);
+ void clear();
+
+ QWindowsPipeWriter *pipeWriter;
+ };
+
+ HANDLE handle;
+ Overlapped overlapped;
+ qint64 numberOfBytesToWrite;
+ qint64 pendingBytesWrittenValue;
+ bool stopped;
+ bool writeSequenceStarted;
+ bool notifiedCalled;
+ bool bytesWrittenPending;
+ bool inBytesWritten;
+};
QT_END_NAMESPACE
diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp
index ae39f78fe8..03ad2b6654 100644
--- a/src/network/socket/qlocalsocket_win.cpp
+++ b/src/network/socket/qlocalsocket_win.cpp
@@ -214,7 +214,6 @@ qint64 QLocalSocket::writeData(const char *data, qint64 maxSize)
d->pipeWriter = new QWindowsPipeWriter(d->handle, this);
connect(d->pipeWriter, SIGNAL(canWrite()), this, SLOT(_q_canWrite()));
connect(d->pipeWriter, SIGNAL(bytesWritten(qint64)), this, SIGNAL(bytesWritten(qint64)));
- d->pipeWriter->start();
}
return d->pipeWriter->write(data, maxSize);
}
diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm
index 4f688f6f28..092cf4d543 100644
--- a/src/widgets/styles/qmacstyle_mac.mm
+++ b/src/widgets/styles/qmacstyle_mac.mm
@@ -1097,17 +1097,67 @@ static QAquaWidgetSize qt_aqua_guess_size(const QWidget *widg, QSize large, QSiz
}
#endif
-static void qt_drawFocusRingOnPath(CGContextRef cg, NSBezierPath *focusRingPath)
+void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, qreal radius) const
{
- CGContextSaveGState(cg);
- [NSGraphicsContext saveGraphicsState];
- [NSGraphicsContext setCurrentContext:[NSGraphicsContext
- graphicsContextWithGraphicsPort:(CGContextRef)cg flipped:NO]];
- NSSetFocusRingStyle(NSFocusRingOnly);
- [focusRingPath setClip]; // Clear clip path to avoid artifacts when rendering the cursor at zero pos
- [focusRingPath fill];
- [NSGraphicsContext restoreGraphicsState];
- CGContextRestoreGState(cg);
+ qreal pixelRatio = p->device()->devicePixelRatioF();
+ static const QString keyFormat = QLatin1String("$qt_focusring%1-%2-%3-%4");
+ const QString &key = keyFormat.arg(hMargin).arg(vMargin).arg(radius).arg(pixelRatio);
+ QPixmap focusRingPixmap;
+ const qreal size = radius * 2 + 5;
+
+ if (!QPixmapCache::find(key, focusRingPixmap)) {
+ focusRingPixmap = QPixmap((QSize(size, size) + 2 * QSize(hMargin, vMargin)) * pixelRatio);
+ focusRingPixmap.fill(Qt::transparent);
+ focusRingPixmap.setDevicePixelRatio(pixelRatio);
+ {
+ QMacAutoReleasePool pool;
+ NSBezierPath *focusRingPath;
+ if (radius > 0)
+ focusRingPath = [NSBezierPath bezierPathWithRoundedRect:NSMakeRect(hMargin, vMargin, size, size)
+ xRadius:radius
+ yRadius:radius];
+ else
+ focusRingPath = [NSBezierPath bezierPathWithRect:NSMakeRect(hMargin, vMargin, size, size)];
+ [NSGraphicsContext saveGraphicsState];
+ QMacCGContext gc(&focusRingPixmap);
+ [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:(CGContextRef)gc
+ flipped:NO]];
+ NSSetFocusRingStyle(NSFocusRingOnly);
+ [focusRingPath fill];
+ [NSGraphicsContext restoreGraphicsState];
+ }
+ QPixmapCache::insert(key, focusRingPixmap);
+ }
+
+ // Add 2 for the actual ring tickness going inwards
+ const qreal hCornerSize = 2 + hMargin + radius;
+ const qreal vCornerSize = 2 + vMargin + radius;
+ const qreal shCornerSize = hCornerSize * pixelRatio;
+ const qreal svCornerSize = vCornerSize * pixelRatio;
+ // top-left corner
+ p->drawPixmap(QPointF(targetRect.left(), targetRect.top()), focusRingPixmap,
+ QRectF(0, 0, shCornerSize, svCornerSize));
+ // top-right corner
+ p->drawPixmap(QPointF(targetRect.right() - hCornerSize + 1, targetRect.top()), focusRingPixmap,
+ QRectF(focusRingPixmap.width() - shCornerSize, 0, shCornerSize, svCornerSize));
+ // bottom-left corner
+ p->drawPixmap(QPointF(targetRect.left(), targetRect.bottom() - vCornerSize + 1), focusRingPixmap,
+ QRectF(0, focusRingPixmap.height() - svCornerSize, shCornerSize, svCornerSize));
+ // bottom-right corner
+ p->drawPixmap(QPointF(targetRect.right() - hCornerSize + 1, targetRect.bottom() - vCornerSize + 1), focusRingPixmap,
+ QRect(focusRingPixmap.width() - shCornerSize, focusRingPixmap.height() - svCornerSize, shCornerSize, svCornerSize));
+ // top edge
+ p->drawPixmap(QRectF(targetRect.left() + hCornerSize, targetRect.top(), targetRect.width() - 2 * hCornerSize, vCornerSize), focusRingPixmap,
+ QRect(shCornerSize, 0, focusRingPixmap.width() - 2 * shCornerSize, svCornerSize));
+ // bottom edge
+ p->drawPixmap(QRectF(targetRect.left() + hCornerSize, targetRect.bottom() - vCornerSize + 1, targetRect.width() - 2 * hCornerSize, vCornerSize), focusRingPixmap,
+ QRect(shCornerSize, focusRingPixmap.height() - svCornerSize, focusRingPixmap.width() - 2 * shCornerSize, svCornerSize));
+ // left edge
+ p->drawPixmap(QRectF(targetRect.left(), targetRect.top() + vCornerSize, hCornerSize, targetRect.height() - 2 * vCornerSize), focusRingPixmap,
+ QRect(0, svCornerSize, shCornerSize, focusRingPixmap.width() - 2 * svCornerSize));
+ // right edge
+ p->drawPixmap(QRectF(targetRect.right() - hCornerSize + 1, targetRect.top() + vCornerSize, hCornerSize, targetRect.height() - 2 * vCornerSize), focusRingPixmap,
+ QRect(focusRingPixmap.width() - shCornerSize, svCornerSize, shCornerSize, focusRingPixmap.width() - 2 * svCornerSize));
}
QAquaWidgetSize QMacStylePrivate::aquaSizeConstrain(const QStyleOption *option, const QWidget *widg,
@@ -3947,12 +3997,11 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
}
}
- NSBezierPath *pushButtonFocusRingPath;
- if (bdi.kind == kThemeBevelButton)
- pushButtonFocusRingPath = [NSBezierPath bezierPathWithRect:NSRectFromCGRect(focusRect)];
- else
- pushButtonFocusRingPath = [NSBezierPath bezierPathWithRoundedRect:NSRectFromCGRect(focusRect) xRadius:4 yRadius:4];
- qt_drawFocusRingOnPath(cg, pushButtonFocusRingPath);
+ const qreal radius = bdi.kind == kThemeBevelButton ? 0 : 4;
+ const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, btn, w);
+ const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, btn, w);
+ const QRect focusTargetRect(focusRect.origin.x, focusRect.origin.y, focusRect.size.width, focusRect.size.height);
+ d->drawFocusRing(p, focusTargetRect.adjusted(-hMargin, -vMargin, hMargin, vMargin), hMargin, vMargin, radius);
}
if (hasMenu && (!usingYosemiteOrLater || bdi.kind == kThemeBevelButton)) {
@@ -4391,12 +4440,9 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
}
break;
case CE_FocusFrame: {
- int xOff = proxy()->pixelMetric(PM_FocusFrameHMargin, opt, w);
- int yOff = proxy()->pixelMetric(PM_FocusFrameVMargin, opt, w);
- NSRect rect = NSMakeRect(xOff+opt->rect.x(), yOff+opt->rect.y(), opt->rect.width() - 2 * xOff,
- opt->rect.height() - 2 * yOff);
- NSBezierPath *focusFramePath = [NSBezierPath bezierPathWithRect:rect];
- qt_drawFocusRingOnPath(cg, focusFramePath);
+ const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, opt, w);
+ const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, opt, w);
+ d->drawFocusRing(p, opt->rect, hMargin, vMargin);
break; }
case CE_MenuItem:
case CE_MenuEmptyArea:
diff --git a/src/widgets/styles/qmacstyle_mac_p_p.h b/src/widgets/styles/qmacstyle_mac_p_p.h
index 33818568ec..b2c76c2d76 100644
--- a/src/widgets/styles/qmacstyle_mac_p_p.h
+++ b/src/widgets/styles/qmacstyle_mac_p_p.h
@@ -209,6 +209,8 @@ public:
void drawNSViewInRect(QCocoaWidget widget, NSView *view, const QRect &rect, QPainter *p, bool isQWidget = true, QCocoaDrawRectBlock drawRectBlock = nil) const;
void resolveCurrentNSView(QWindow *window);
+ void drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, qreal radius = 0) const;
+
public:
mutable QPointer<QObject> pressedButton;
mutable QPointer<QObject> defaultButton;
diff --git a/src/widgets/styles/qwindowsstyle_p.h b/src/widgets/styles/qwindowsstyle_p.h
index da36d2af1b..2724222652 100644
--- a/src/widgets/styles/qwindowsstyle_p.h
+++ b/src/widgets/styles/qwindowsstyle_p.h
@@ -97,7 +97,6 @@ protected:
private:
Q_DISABLE_COPY(QWindowsStyle)
Q_DECLARE_PRIVATE(QWindowsStyle)
- void *reserved;
};
#endif // QT_NO_STYLE_WINDOWS
diff --git a/src/widgets/styles/qwindowsxpstyle_p.h b/src/widgets/styles/qwindowsxpstyle_p.h
index 1706a1abe6..4dcb75716e 100644
--- a/src/widgets/styles/qwindowsxpstyle_p.h
+++ b/src/widgets/styles/qwindowsxpstyle_p.h
@@ -93,7 +93,6 @@ private:
Q_DISABLE_COPY(QWindowsXPStyle)
Q_DECLARE_PRIVATE(QWindowsXPStyle)
friend class QStyleFactory;
- void *reserved;
};
#endif // QT_NO_STYLE_WINDOWSXP
diff --git a/src/widgets/widgets/qtoolbarextension_p.h b/src/widgets/widgets/qtoolbarextension_p.h
index f72dfbd597..cbb4eb5c98 100644
--- a/src/widgets/widgets/qtoolbarextension_p.h
+++ b/src/widgets/widgets/qtoolbarextension_p.h
@@ -54,7 +54,6 @@ QT_BEGIN_NAMESPACE
class Q_AUTOTEST_EXPORT QToolBarExtension : public QToolButton
{
Q_OBJECT
- Qt::Orientation orientation;
public:
explicit QToolBarExtension(QWidget *parent);