summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@nokia.com>2009-07-08 14:47:41 +0200
committerVolker Hilsheimer <volker.hilsheimer@nokia.com>2009-07-08 14:47:41 +0200
commitab2b51679c64fd1befad9e8a3442bff2bb104a19 (patch)
treef4d1a4d090d12f587d3e62a8f793c6e2ff54e823 /src
parent0ed214105547980803336337096fd9429ce9f1a1 (diff)
parent1dd1cb8c70a8986c1acc911a663d99d7043d15c7 (diff)
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/phonon/ds9/mediaobject.cpp18
-rw-r--r--src/corelib/animation/qabstractanimation_p.h7
-rw-r--r--src/corelib/animation/qanimationgroup_p.h4
-rw-r--r--src/corelib/animation/qparallelanimationgroup_p.h4
-rw-r--r--src/corelib/animation/qpropertyanimation_p.h6
-rw-r--r--src/corelib/animation/qsequentialanimationgroup_p.h3
-rw-r--r--src/corelib/animation/qvariantanimation_p.h4
-rw-r--r--src/gui/itemviews/qcolumnview.cpp12
-rw-r--r--src/gui/itemviews/qcolumnview_p.h2
-rw-r--r--src/gui/kernel/qclipboard_mac.cpp14
-rw-r--r--src/gui/kernel/qt_cocoa_helpers_mac.mm12
-rw-r--r--src/gui/kernel/qt_cocoa_helpers_mac_p.h1
-rw-r--r--src/gui/widgets/qmainwindowlayout.cpp3
-rw-r--r--src/gui/widgets/qwidgetanimator.cpp22
-rw-r--r--src/gui/widgets/qwidgetanimator_p.h3
-rw-r--r--src/network/socket/qlocalsocket.h1
-rw-r--r--src/network/socket/qlocalsocket_p.h16
-rw-r--r--src/network/socket/qlocalsocket_win.cpp241
18 files changed, 239 insertions, 134 deletions
diff --git a/src/3rdparty/phonon/ds9/mediaobject.cpp b/src/3rdparty/phonon/ds9/mediaobject.cpp
index 1d0b69d8ed..f77bdc1612 100644
--- a/src/3rdparty/phonon/ds9/mediaobject.cpp
+++ b/src/3rdparty/phonon/ds9/mediaobject.cpp
@@ -207,12 +207,14 @@ namespace Phonon
HRESULT hr = S_OK;
- m_currentRender = w.graph;
- m_currentRenderId = w.id;
- if (w.task == ReplaceGraph) {
+ {
QMutexLocker locker(&m_mutex);
- HANDLE h;
+ m_currentRender = w.graph;
+ m_currentRenderId = w.id;
+ }
+ if (w.task == ReplaceGraph) {
+ QMutexLocker locker(&m_mutex);
int index = -1;
for(int i = 0; i < FILTER_COUNT; ++i) {
if (m_graphHandle[i].graph == w.oldGraph) {
@@ -228,6 +230,7 @@ namespace Phonon
Q_ASSERT(index != -1);
//add the new graph
+ HANDLE h;
if (SUCCEEDED(ComPointer<IMediaEvent>(w.graph, IID_IMediaEvent)
->GetEventHandle(reinterpret_cast<OAEVENT*>(&h)))) {
m_graphHandle[index].graph = w.graph;
@@ -324,8 +327,11 @@ namespace Phonon
}
}
- m_currentRender = Graph();
- m_currentRenderId = 0;
+ {
+ QMutexLocker locker(&m_mutex);
+ m_currentRender = Graph();
+ m_currentRenderId = 0;
+ }
}
diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h
index 00def552d5..0d8402e90c 100644
--- a/src/corelib/animation/qabstractanimation_p.h
+++ b/src/corelib/animation/qabstractanimation_p.h
@@ -58,6 +58,8 @@
#include <QtCore/qtimer.h>
#include <private/qobject_p.h>
+#ifndef QT_NO_ANIMATION
+
QT_BEGIN_NAMESPACE
class QAnimationGroup;
@@ -147,4 +149,7 @@ private:
};
QT_END_NAMESPACE
-#endif
+
+#endif //QT_NO_ANIMATION
+
+#endif //QABSTRACTANIMATION_P_H
diff --git a/src/corelib/animation/qanimationgroup_p.h b/src/corelib/animation/qanimationgroup_p.h
index 8e668f0114..01252c56a9 100644
--- a/src/corelib/animation/qanimationgroup_p.h
+++ b/src/corelib/animation/qanimationgroup_p.h
@@ -59,6 +59,8 @@
#include "private/qabstractanimation_p.h"
+#ifndef QT_NO_ANIMATION
+
QT_BEGIN_NAMESPACE
class QAnimationGroupPrivate : public QAbstractAnimationPrivate
@@ -76,4 +78,6 @@ public:
QT_END_NAMESPACE
+#endif //QT_NO_ANIMATION
+
#endif //QANIMATIONGROUP_P_H
diff --git a/src/corelib/animation/qparallelanimationgroup_p.h b/src/corelib/animation/qparallelanimationgroup_p.h
index 201eb1627a..949a9b2e38 100644
--- a/src/corelib/animation/qparallelanimationgroup_p.h
+++ b/src/corelib/animation/qparallelanimationgroup_p.h
@@ -57,6 +57,8 @@
#include "private/qanimationgroup_p.h"
#include <QtCore/QHash>
+#ifndef QT_NO_ANIMATION
+
QT_BEGIN_NAMESPACE
class QParallelAnimationGroupPrivate : public QAnimationGroupPrivate
@@ -82,4 +84,6 @@ public:
QT_END_NAMESPACE
+#endif //QT_NO_ANIMATION
+
#endif //QPARALLELANIMATIONGROUP_P_H
diff --git a/src/corelib/animation/qpropertyanimation_p.h b/src/corelib/animation/qpropertyanimation_p.h
index 68b25193bf..a2ae5ec563 100644
--- a/src/corelib/animation/qpropertyanimation_p.h
+++ b/src/corelib/animation/qpropertyanimation_p.h
@@ -58,6 +58,8 @@
#include "private/qvariantanimation_p.h"
+#ifndef QT_NO_ANIMATION
+
QT_BEGIN_NAMESPACE
class QPropertyAnimationPrivate : public QVariantAnimationPrivate
@@ -86,4 +88,6 @@ public:
QT_END_NAMESPACE
-#endif
+#endif //QT_NO_ANIMATION
+
+#endif //QPROPERTYANIMATION_P_H
diff --git a/src/corelib/animation/qsequentialanimationgroup_p.h b/src/corelib/animation/qsequentialanimationgroup_p.h
index 555b69655a..8db79a0147 100644
--- a/src/corelib/animation/qsequentialanimationgroup_p.h
+++ b/src/corelib/animation/qsequentialanimationgroup_p.h
@@ -56,6 +56,7 @@
#include "qsequentialanimationgroup.h"
#include "private/qanimationgroup_p.h"
+#ifndef QT_NO_ANIMATION
QT_BEGIN_NAMESPACE
@@ -108,4 +109,6 @@ public:
QT_END_NAMESPACE
+#endif //QT_NO_ANIMATION
+
#endif //QSEQUENTIALANIMATIONGROUP_P_H
diff --git a/src/corelib/animation/qvariantanimation_p.h b/src/corelib/animation/qvariantanimation_p.h
index b848e12e88..69e23dc472 100644
--- a/src/corelib/animation/qvariantanimation_p.h
+++ b/src/corelib/animation/qvariantanimation_p.h
@@ -60,6 +60,8 @@
#include "private/qabstractanimation_p.h"
+#ifndef QT_NO_ANIMATION
+
QT_BEGIN_NAMESPACE
class QVariantAnimationPrivate : public QAbstractAnimationPrivate
@@ -120,4 +122,6 @@ template<typename T > inline QVariant _q_interpolateVariant(const T &from, const
QT_END_NAMESPACE
+#endif //QT_NO_ANIMATION
+
#endif //QANIMATION_P_H
diff --git a/src/gui/itemviews/qcolumnview.cpp b/src/gui/itemviews/qcolumnview.cpp
index fc899674ac..c544394133 100644
--- a/src/gui/itemviews/qcolumnview.cpp
+++ b/src/gui/itemviews/qcolumnview.cpp
@@ -107,10 +107,13 @@ void QColumnViewPrivate::initialize()
{
Q_Q(QColumnView);
q->setTextElideMode(Qt::ElideMiddle);
+#ifndef QT_NO_ANIMATION
QObject::connect(&currentAnimation, SIGNAL(finished()), q, SLOT(_q_changeCurrentColumn()));
currentAnimation.setDuration(ANIMATION_DURATION_MSEC);
currentAnimation.setTargetObject(hbar);
+ currentAnimation.setPropertyName("value");
currentAnimation.setEasingCurve(QEasingCurve::InOutQuad);
+#endif //QT_NO_ANIMATION
delete itemDelegate;
q->setItemDelegate(new QColumnViewDelegate(q));
}
@@ -260,10 +263,12 @@ void QColumnView::scrollTo(const QModelIndex &index, ScrollHint hint)
if (!index.isValid() || d->columns.isEmpty())
return;
+#ifndef QT_NO_ANIMATION
if (d->currentAnimation.state() == QPropertyAnimation::Running)
return;
d->currentAnimation.stop();
+#endif //QT_NO_ANIMATION
// Fill up what is needed to get to index
d->closeColumns(index, true);
@@ -326,8 +331,12 @@ void QColumnView::scrollTo(const QModelIndex &index, ScrollHint hint)
}
}
+#ifndef QT_NO_ANIMATION
d->currentAnimation.setEndValue(newScrollbarValue);
d->currentAnimation.start();
+#else
+ horizontalScrollBar()->setValue(newScrollbarValue);
+#endif //QT_NO_ANIMATION
}
/*!
@@ -396,8 +405,10 @@ void QColumnView::resizeEvent(QResizeEvent *event)
void QColumnViewPrivate::updateScrollbars()
{
Q_Q(QColumnView);
+#ifndef QT_NO_ANIMATION
if (currentAnimation.state() == QPropertyAnimation::Running)
return;
+#endif //QT_NO_ANIMATION
// find the total horizontal length of the laid out columns
int horizontalLength = 0;
@@ -1031,7 +1042,6 @@ QColumnViewPrivate::QColumnViewPrivate()
: QAbstractItemViewPrivate()
,showResizeGrips(true)
,offset(0)
-,currentAnimation(0, "value") // will set the target later
,previewWidget(0)
,previewColumn(0)
{
diff --git a/src/gui/itemviews/qcolumnview_p.h b/src/gui/itemviews/qcolumnview_p.h
index 1a8be70af3..3f99220dcd 100644
--- a/src/gui/itemviews/qcolumnview_p.h
+++ b/src/gui/itemviews/qcolumnview_p.h
@@ -160,7 +160,9 @@ public:
QVector<int> columnSizes; // used during init and corner moving
bool showResizeGrips;
int offset;
+#ifndef QT_NO_ANIMATION
QPropertyAnimation currentAnimation;
+#endif
QWidget *previewWidget;
QAbstractItemView *previewColumn;
};
diff --git a/src/gui/kernel/qclipboard_mac.cpp b/src/gui/kernel/qclipboard_mac.cpp
index b7b57b8a60..45050b278c 100644
--- a/src/gui/kernel/qclipboard_mac.cpp
+++ b/src/gui/kernel/qclipboard_mac.cpp
@@ -50,6 +50,7 @@
#include "qurl.h"
#include <stdlib.h>
#include <string.h>
+#include "qt_cocoa_helpers_mac_p.h"
QT_BEGIN_NAMESPACE
@@ -525,8 +526,17 @@ QMacPasteboard::retrieveData(const QString &format, QVariant::Type) const
QString c_flavor = c->flavorFor(format);
if(!c_flavor.isEmpty()) {
// Handle text/plain a little differently. Try handling Unicode first.
- if((c_flavor == QLatin1String("com.apple.traditional-mac-plain-text") || c_flavor == QLatin1String("public.utf8-plain-text")) &&
- hasFlavor(QLatin1String("public.utf16-plain-text")))
+ bool checkForUtf16 = (c_flavor == QLatin1String("com.apple.traditional-mac-plain-text")
+ || c_flavor == QLatin1String("public.utf8-plain-text"));
+ if (checkForUtf16 || c_flavor == QLatin1String("public.utf16-plain-text")) {
+ // Try to get the NSStringPboardType from NSPasteboard, newlines are mapped
+ // correctly (as '\n') in this data. The 'public.utf16-plain-text' type
+ // usually maps newlines to '\r' instead.
+ QString str = qt_mac_get_pasteboardString();
+ if (!str.isEmpty())
+ return str;
+ }
+ if (checkForUtf16 && hasFlavor(QLatin1String("public.utf16-plain-text")))
c_flavor = QLatin1String("public.utf16-plain-text");
QVariant ret;
diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm
index 073a00e250..13b0e50bad 100644
--- a/src/gui/kernel/qt_cocoa_helpers_mac.mm
+++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm
@@ -1131,4 +1131,16 @@ CGFloat qt_mac_get_scalefactor()
#endif
}
+QString qt_mac_get_pasteboardString()
+{
+ QMacCocoaAutoReleasePool pool;
+ NSPasteboard *pb = [NSPasteboard generalPasteboard];
+ NSString *text = [pb stringForType:NSStringPboardType];
+ if (text) {
+ return qt_mac_NSStringToQString(text);
+ } else {
+ return QString();
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h
index 7b975f52ba..3881ccdbb9 100644
--- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h
+++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h
@@ -162,6 +162,7 @@ void *qt_mac_QStringListToNSMutableArrayVoid(const QStringList &list);
void qt_syncCocoaTitleBarButtons(OSWindowRef window, QWidget *widgetForWindow);
CGFloat qt_mac_get_scalefactor();
+QString qt_mac_get_pasteboardString();
#ifdef __OBJC__
inline NSMutableArray *qt_mac_QStringListToNSMutableArray(const QStringList &qstrlist)
diff --git a/src/gui/widgets/qmainwindowlayout.cpp b/src/gui/widgets/qmainwindowlayout.cpp
index ad608d3127..8fb7c4f07c 100644
--- a/src/gui/widgets/qmainwindowlayout.cpp
+++ b/src/gui/widgets/qmainwindowlayout.cpp
@@ -237,7 +237,7 @@ void QMainWindowLayoutState::apply(bool animated)
if (centralWidgetItem != 0) {
QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(mainWindow->layout());
Q_ASSERT(layout != 0);
- layout->widgetAnimator->animate(centralWidgetItem->widget(), centralWidgetRect, animated);
+ layout->widgetAnimator.animate(centralWidgetItem->widget(), centralWidgetRect, animated);
}
#endif
}
@@ -946,7 +946,6 @@ void QMainWindowLayout::toggleToolBarsVisible()
r = layoutState.toolBarAreaLayout.rectHint(r);
r.moveTo(topLeft);
parentWidget()->setGeometry(r);
-// widgetAnimator->animate(parentWidget(), r, true);
} else{
update();
}
diff --git a/src/gui/widgets/qwidgetanimator.cpp b/src/gui/widgets/qwidgetanimator.cpp
index d820b59516..7a3a464e96 100644
--- a/src/gui/widgets/qwidgetanimator.cpp
+++ b/src/gui/widgets/qwidgetanimator.cpp
@@ -53,6 +53,7 @@ QWidgetAnimator::QWidgetAnimator(QMainWindowLayout *layout) : m_mainWindowLayout
void QWidgetAnimator::abort(QWidget *w)
{
+#ifndef QT_NO_ANIMATION
AnimationMap::iterator it = m_animation_map.find(w);
if (it == m_animation_map.end())
return;
@@ -60,13 +61,18 @@ void QWidgetAnimator::abort(QWidget *w)
m_animation_map.erase(it);
anim->stop();
m_mainWindowLayout->animationFinished(w);
+#else
+ Q_UNUSED(w); //there is no animation to abort
+#endif //QT_NO_ANIMATION
}
+#ifndef QT_NO_ANIMATION
void QWidgetAnimator::animationFinished()
{
QPropertyAnimation *anim = qobject_cast<QPropertyAnimation*>(sender());
abort(static_cast<QWidget*>(anim->targetObject()));
}
+#endif //QT_NO_ANIMATION
void QWidgetAnimator::animate(QWidget *widget, const QRect &_final_geometry, bool animate)
{
@@ -76,6 +82,9 @@ void QWidgetAnimator::animate(QWidget *widget, const QRect &_final_geometry, boo
if (r.right() < 0 || r.bottom() < 0)
r = QRect();
+#ifdef QT_NO_ANIMATION
+ Q_UNUSED(animate);
+#else
if (r.isNull() || final_geometry.isNull() || r == final_geometry)
animate = false;
@@ -91,7 +100,9 @@ void QWidgetAnimator::animate(QWidget *widget, const QRect &_final_geometry, boo
m_animation_map[widget] = anim;
connect(anim, SIGNAL(finished()), SLOT(animationFinished()));
anim->start(QPropertyAnimation::DeleteWhenStopped);
- } else {
+ } else
+#endif //QT_NO_ANIMATION
+ {
if (!final_geometry.isValid() && !widget->isWindow()) {
// Make the wigdet go away by sending it to negative space
QSize s = widget->size();
@@ -103,12 +114,21 @@ void QWidgetAnimator::animate(QWidget *widget, const QRect &_final_geometry, boo
bool QWidgetAnimator::animating() const
{
+#ifdef QT_NO_ANIMATION
+ return false;
+#else
return !m_animation_map.isEmpty();
+#endif //QT_NO_ANIMATION
}
bool QWidgetAnimator::animating(QWidget *widget) const
{
+#ifdef QT_NO_ANIMATION
+ Q_UNUSED(widget);
+ return false;
+#else
return m_animation_map.contains(widget);
+#endif //QT_NO_ANIMATION
}
QT_END_NAMESPACE
diff --git a/src/gui/widgets/qwidgetanimator_p.h b/src/gui/widgets/qwidgetanimator_p.h
index edd8e7c6a5..4047395168 100644
--- a/src/gui/widgets/qwidgetanimator_p.h
+++ b/src/gui/widgets/qwidgetanimator_p.h
@@ -74,12 +74,15 @@ public:
void abort(QWidget *widget);
+#ifndef QT_NO_ANIMATION
private Q_SLOTS:
void animationFinished();
private:
typedef QMap<QWidget*, QPropertyAnimation*> AnimationMap;
AnimationMap m_animation_map;
+#endif
+private:
QMainWindowLayout *m_mainWindowLayout;
};
diff --git a/src/network/socket/qlocalsocket.h b/src/network/socket/qlocalsocket.h
index 417671ac28..4bff62eb7e 100644
--- a/src/network/socket/qlocalsocket.h
+++ b/src/network/socket/qlocalsocket.h
@@ -134,6 +134,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_notified())
Q_PRIVATE_SLOT(d_func(), void _q_canWrite())
Q_PRIVATE_SLOT(d_func(), void _q_pipeClosed())
+ Q_PRIVATE_SLOT(d_func(), void _q_emitReadyRead())
#else
Q_PRIVATE_SLOT(d_func(), void _q_stateChanged(QAbstractSocket::SocketState))
Q_PRIVATE_SLOT(d_func(), void _q_error(QAbstractSocket::SocketError))
diff --git a/src/network/socket/qlocalsocket_p.h b/src/network/socket/qlocalsocket_p.h
index bdbba42eb2..2dae7d9476 100644
--- a/src/network/socket/qlocalsocket_p.h
+++ b/src/network/socket/qlocalsocket_p.h
@@ -65,6 +65,7 @@
#elif defined(Q_OS_WIN)
# include "private/qwindowspipewriter_p.h"
# include "private/qringbuffer_p.h"
+# include <private/qwineventnotifier_p.h>
#else
# include "private/qnativesocketengine_p.h"
# include <qtcpsocket.h>
@@ -135,18 +136,23 @@ public:
void _q_notified();
void _q_canWrite();
void _q_pipeClosed();
- qint64 readData(char *data, qint64 maxSize);
- qint64 bytesAvailable();
- bool readFromSocket();
+ void _q_emitReadyRead();
+ DWORD bytesAvailable();
+ void startAsyncRead();
+ void completeAsyncRead();
+ void checkReadyRead();
HANDLE handle;
OVERLAPPED overlapped;
QWindowsPipeWriter *pipeWriter;
qint64 readBufferMaxSize;
QRingBuffer readBuffer;
- QTimer dataNotifier;
+ int actualReadBufferSize;
+ QWinEventNotifier *dataReadNotifier;
QLocalSocket::LocalSocketError error;
- bool readyReadEmitted;
+ bool readSequenceStarted;
+ bool pendingReadyRead;
bool pipeClosed;
+ static const qint64 initialReadBufferSize = 4096;
#else
QLocalUnixSocket unixSocket;
QString generateErrorString(QLocalSocket::LocalSocketError, const QString &function) const;
diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp
index b1b69fc293..1a971f0ba9 100644
--- a/src/network/socket/qlocalsocket_win.cpp
+++ b/src/network/socket/qlocalsocket_win.cpp
@@ -48,13 +48,13 @@
QT_BEGIN_NAMESPACE
-#define NOTIFYTIMEOUT 100
-
void QLocalSocketPrivate::init()
{
Q_Q(QLocalSocket);
- QObject::connect(&dataNotifier, SIGNAL(timeout()), q, SLOT(_q_notified()));
+ memset(&overlapped, 0, sizeof(overlapped));
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ dataReadNotifier = new QWinEventNotifier(overlapped.hEvent, q);
+ q->connect(dataReadNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_notified()));
}
void QLocalSocketPrivate::setErrorString(const QString &function)
@@ -101,8 +101,10 @@ QLocalSocketPrivate::QLocalSocketPrivate() : QIODevicePrivate(),
handle(INVALID_HANDLE_VALUE),
pipeWriter(0),
readBufferMaxSize(0),
+ actualReadBufferSize(0),
error(QLocalSocket::UnknownSocketError),
- readyReadEmitted(false),
+ readSequenceStarted(false),
+ pendingReadyRead(false),
pipeClosed(false),
state(QLocalSocket::UnconnectedState)
{
@@ -176,82 +178,103 @@ void QLocalSocket::connectToServer(const QString &name, OpenMode openMode)
qint64 QLocalSocket::readData(char *data, qint64 maxSize)
{
Q_D(QLocalSocket);
- if (d->readBuffer.isEmpty()) {
- if (!d->readFromSocket()) {
- if (d->pipeClosed)
- return -1;
- return 0;
- }
- }
-
- if (!d->dataNotifier.isActive() && d->threadData->eventDispatcher)
- d->dataNotifier.start(NOTIFYTIMEOUT);
-
- if (d->readBuffer.isEmpty())
- return qint64(0);
- // If readFromSocket() read data, copy it to its destination.
- if (maxSize == 1) {
+ qint64 readSoFar;
+ // If startAsyncRead() read data, copy it to its destination.
+ if (maxSize == 1 && d->actualReadBufferSize > 0) {
*data = d->readBuffer.getChar();
- return 1;
+ d->actualReadBufferSize--;
+ readSoFar = 1;
+ } else {
+ qint64 bytesToRead = qMin(qint64(d->actualReadBufferSize), maxSize);
+ readSoFar = 0;
+ while (readSoFar < bytesToRead) {
+ const char *ptr = d->readBuffer.readPointer();
+ int bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar,
+ qint64(d->readBuffer.nextDataBlockSize()));
+ memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock);
+ readSoFar += bytesToReadFromThisBlock;
+ d->readBuffer.free(bytesToReadFromThisBlock);
+ d->actualReadBufferSize -= bytesToReadFromThisBlock;
+ }
}
- qint64 bytesToRead = qMin(qint64(d->readBuffer.size()), maxSize);
- qint64 readSoFar = 0;
- while (readSoFar < bytesToRead) {
- const char *ptr = d->readBuffer.readPointer();
- int bytesToReadFromThisBlock = qMin(int(bytesToRead - readSoFar),
- d->readBuffer.nextDataBlockSize());
- memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock);
- readSoFar += bytesToReadFromThisBlock;
- d->readBuffer.free(bytesToReadFromThisBlock);
- }
+ if (!d->readSequenceStarted)
+ d->startAsyncRead();
+ d->checkReadyRead();
+
return readSoFar;
}
/*!
\internal
- read from the socket
+ Schedules or cancels a readyRead() emission depending on actual data availability
*/
-qint64 QLocalSocketPrivate::readData(char *data, qint64 maxSize)
+void QLocalSocketPrivate::checkReadyRead()
{
- DWORD bytesRead = 0;
- overlapped.Offset = 0;
- overlapped.OffsetHigh = 0;
- bool success = ReadFile(handle, data, maxSize, &bytesRead, &overlapped);
- if (!success && GetLastError() == ERROR_IO_PENDING)
- if (GetOverlappedResult(handle, &overlapped, &bytesRead, TRUE))
- success = true;
- if (!success) {
- setErrorString(QLatin1String("QLocalSocket::readData"));
- return 0;
+ if (actualReadBufferSize > 0) {
+ if (!pendingReadyRead) {
+ Q_Q(QLocalSocket);
+ QTimer::singleShot(0, q, SLOT(_q_emitReadyRead()));
+ pendingReadyRead = true;
+ }
+ } else {
+ pendingReadyRead = false;
}
- return bytesRead;
}
/*!
\internal
Reads data from the socket into the readbuffer
*/
-bool QLocalSocketPrivate::readFromSocket()
+void QLocalSocketPrivate::startAsyncRead()
{
- qint64 bytesToRead = bytesAvailable();
- if (bytesToRead == 0)
- return false;
+ do {
+ DWORD bytesToRead = bytesAvailable();
+ if (bytesToRead == 0) {
+ // There are no bytes in the pipe but we need to
+ // start the overlapped read with some buffer size.
+ bytesToRead = initialReadBufferSize;
+ }
- if (readBufferMaxSize && bytesToRead
- > (readBufferMaxSize - readBuffer.size()))
- bytesToRead = readBufferMaxSize - readBuffer.size();
+ if (readBufferMaxSize && bytesToRead > (readBufferMaxSize - readBuffer.size())) {
+ bytesToRead = readBufferMaxSize - readBuffer.size();
+ if (bytesToRead == 0) {
+ // Buffer is full. User must read data from the buffer
+ // before we can read more from the pipe.
+ return;
+ }
+ }
- char *ptr = readBuffer.reserve(bytesToRead);
- qint64 readBytes = readData(ptr, bytesToRead);
- if (readBytes == 0) {
- readBuffer.chop(bytesToRead);
- return false;
+ char *ptr = readBuffer.reserve(bytesToRead);
+
+ readSequenceStarted = true;
+ if (ReadFile(handle, ptr, bytesToRead, NULL, &overlapped)) {
+ completeAsyncRead();
+ } else if (GetLastError() != ERROR_IO_PENDING) {
+ setErrorString(QLatin1String("QLocalSocketPrivate::startAsyncRead"));
+ return;
+ }
+ } while (!readSequenceStarted);
+}
+
+/*!
+ \internal
+ Sets the correct size of the read buffer after a read operation.
+ */
+void QLocalSocketPrivate::completeAsyncRead()
+{
+ ResetEvent(overlapped.hEvent);
+ readSequenceStarted = false;
+
+ DWORD bytesRead;
+ if (!GetOverlappedResult(handle, &overlapped, &bytesRead, TRUE)) {
+ setErrorString(QLatin1String("QLocalSocketPrivate::completeAsyncRead"));
+ return;
}
- readyReadEmitted = false;
- readBuffer.chop(int(bytesToRead - (readBytes < 0 ? qint64(0) : readBytes)));
- return true;
+
+ actualReadBufferSize += bytesRead;
+ readBuffer.truncate(actualReadBufferSize);
}
qint64 QLocalSocket::writeData(const char *data, qint64 maxSize)
@@ -273,7 +296,7 @@ void QLocalSocket::abort()
/*!
The number of bytes available from the pipe
*/
-qint64 QLocalSocketPrivate::bytesAvailable()
+DWORD QLocalSocketPrivate::bytesAvailable()
{
Q_Q(QLocalSocket);
if (q->state() != QLocalSocket::ConnectedState)
@@ -300,7 +323,7 @@ qint64 QLocalSocket::bytesAvailable() const
{
Q_D(const QLocalSocket);
qint64 available = QIODevice::bytesAvailable();
- available += (qint64) d->readBuffer.size();
+ available += (qint64) d->actualReadBufferSize;
return available;
}
@@ -327,7 +350,6 @@ void QLocalSocket::close()
QIODevice::close();
d->state = ClosingState;
emit stateChanged(d->state);
- d->readyReadEmitted = false;
emit readChannelFinished();
d->serverName = QString();
d->fullServerName = QString();
@@ -336,10 +358,13 @@ void QLocalSocket::close()
disconnectFromServer();
return;
}
+ d->readSequenceStarted = false;
+ d->pendingReadyRead = false;
d->pipeClosed = false;
DisconnectNamedPipe(d->handle);
CloseHandle(d->handle);
d->handle = INVALID_HANDLE_VALUE;
+ ResetEvent(d->overlapped.hEvent);
d->state = UnconnectedState;
emit stateChanged(d->state);
emit disconnected();
@@ -347,7 +372,6 @@ void QLocalSocket::close()
delete d->pipeWriter;
d->pipeWriter = 0;
}
- d->dataNotifier.stop();
}
bool QLocalSocket::flush()
@@ -381,12 +405,15 @@ bool QLocalSocket::setSocketDescriptor(quintptr socketDescriptor,
{
Q_D(QLocalSocket);
d->readBuffer.clear();
+ d->actualReadBufferSize = 0;
QIODevice::open(openMode);
d->handle = (int*)socketDescriptor;
d->state = socketState;
emit stateChanged(d->state);
- if (d->threadData->eventDispatcher)
- d->dataNotifier.start(NOTIFYTIMEOUT);
+ if (d->state == ConnectedState) {
+ d->startAsyncRead();
+ d->checkReadyRead();
+ }
return true;
}
@@ -400,20 +427,18 @@ void QLocalSocketPrivate::_q_canWrite()
void QLocalSocketPrivate::_q_notified()
{
Q_Q(QLocalSocket);
- if (0 != bytesAvailable()) {
- if (readBufferMaxSize == 0 || readBuffer.size() < readBufferMaxSize) {
- if (!readFromSocket()) {
- return;
- }
- // wait until buffer is cleared before starting again
- if (readBufferMaxSize && readBuffer.size() == readBufferMaxSize) {
- dataNotifier.stop();
- }
- }
- if (!readyReadEmitted) {
- readyReadEmitted = true;
- q->emit readyRead();
- }
+ completeAsyncRead();
+ startAsyncRead();
+ pendingReadyRead = false;
+ emit q->readyRead();
+}
+
+void QLocalSocketPrivate::_q_emitReadyRead()
+{
+ if (pendingReadyRead) {
+ Q_Q(QLocalSocket);
+ pendingReadyRead = false;
+ emit q->readyRead();
}
}
@@ -448,9 +473,9 @@ bool QLocalSocket::waitForDisconnected(int msecs)
return false;
QIncrementalSleepTimer timer(msecs);
forever {
- d->_q_notified();
- if (d->pipeClosed)
- close();
+ d->bytesAvailable(); // to check if PeekNamedPipe fails
+ if (d->pipeClosed)
+ close();
if (state() == UnconnectedState)
return true;
Sleep(timer.nextSleepTime());
@@ -470,22 +495,24 @@ bool QLocalSocket::isValid() const
bool QLocalSocket::waitForReadyRead(int msecs)
{
Q_D(QLocalSocket);
- QIncrementalSleepTimer timer(msecs);
- forever {
- d->_q_notified();
- if (bytesAvailable() > 0) {
- if (!d->readyReadEmitted) {
- d->readyReadEmitted = true;
- emit readyRead();
- }
- return true;
- }
- Sleep(timer.nextSleepTime());
- if (timer.hasTimedOut())
- break;
+ if (bytesAvailable() > 0)
+ return true;
+
+ if (d->state != QLocalSocket::ConnectedState)
+ return false;
+
+ Q_ASSERT(d->readSequenceStarted);
+ DWORD result = WaitForSingleObject(d->overlapped.hEvent, msecs == -1 ? INFINITE : msecs);
+ switch (result) {
+ case WAIT_OBJECT_0:
+ d->_q_notified();
+ return true;
+ case WAIT_TIMEOUT:
+ return false;
}
+ qWarning("QLocalSocket::waitForReadyRead WaitForSingleObject failed with error code %d.", GetLastError());
return false;
}
@@ -495,27 +522,11 @@ bool QLocalSocket::waitForBytesWritten(int msecs)
if (!d->pipeWriter)
return false;
- QIncrementalSleepTimer timer(msecs);
- forever {
- if (d->pipeWriter->hadWritten())
- return true;
-
- if (d->pipeWriter->bytesToWrite() == 0)
- return false;
-
- // Wait for the pipe writer to acknowledge that it has
- // written. This will succeed if either the pipe writer has
- // already written the data, or if it manages to write data
- // within the given timeout.
- if (d->pipeWriter->waitForWrite(0))
- return true;
-
- Sleep(timer.nextSleepTime());
- if (timer.hasTimedOut())
- break;
- }
-
- return false;
+ // Wait for the pipe writer to acknowledge that it has
+ // written. This will succeed if either the pipe writer has
+ // already written the data, or if it manages to write data
+ // within the given timeout.
+ return d->pipeWriter->waitForWrite(msecs);
}
QT_END_NAMESPACE