From 9ff84982005a1a0fd5cbc1b014f4eac3c03b52be Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Wed, 16 Jun 2010 12:18:40 +0200 Subject: Fix autoScroll implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The scrolling should not be calculated inside the paint event, this leads to some incorrect behaviour. It is now calculated separately when needed. Patch actually written by Alexis, and I reviewed it. Task-number: QTBUG-11127 Reviewed-by: Alexis Ménard (cherry picked from commit bc4c5a2d9c5d3841948bc4443f2229d8d6ec0e95) --- .../graphicsitems/qdeclarativetextinput.cpp | 88 +++++++++++++--------- .../graphicsitems/qdeclarativetextinput_p_p.h | 1 + .../tst_qdeclarativetextinput.cpp | 1 - 3 files changed, 54 insertions(+), 36 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index 633c01e..624a5aa 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -100,6 +100,7 @@ void QDeclarativeTextInput::setText(const QString &s) if(s == text()) return; d->control->setText(s); + d->updateHorizontalScroll(); //emit textChanged(); } @@ -337,6 +338,7 @@ void QDeclarativeTextInput::setHAlign(HAlignment align) return; d->hAlign = align; updateRect(); + d->updateHorizontalScroll(); emit horizontalAlignmentChanged(d->hAlign); } @@ -554,7 +556,9 @@ void QDeclarativeTextInput::setAutoScroll(bool b) return; d->autoScroll = b; - + d->updateHorizontalScroll(); + //We need to repaint so that the scrolling is taking into account. + updateSize(true); emit autoScrollChanged(d->autoScroll); } @@ -836,6 +840,7 @@ void QDeclarativeTextInput::moveCursor() Q_D(QDeclarativeTextInput); if(!d->cursorItem) return; + d->updateHorizontalScroll(); d->cursorItem->setX(d->control->cursorToX() - d->hscroll); } @@ -845,7 +850,6 @@ void QDeclarativeTextInput::moveCursor() QRectF QDeclarativeTextInput::positionToRectangle(int x) const { Q_D(const QDeclarativeTextInput); - QFontMetrics fm = QFontMetrics(d->font); return QRectF(d->control->cursorToX(x)-d->hscroll, 0.0, d->control->cursorWidth(), @@ -1012,61 +1016,73 @@ void QDeclarativeTextInput::geometryChanged(const QRectF &newGeometry, QDeclarativePaintedItem::geometryChanged(newGeometry, oldGeometry); } -void QDeclarativeTextInput::drawContents(QPainter *p, const QRect &r) +void QDeclarativeTextInputPrivate::updateHorizontalScroll() { - Q_D(QDeclarativeTextInput); - p->setRenderHint(QPainter::TextAntialiasing, true); - p->save(); - p->setPen(QPen(d->color)); - int flags = QLineControl::DrawText; - if(!isReadOnly() && d->cursorVisible && !d->cursorItem) - flags |= QLineControl::DrawCursor; - if (d->control->hasSelectedText()) - flags |= QLineControl::DrawSelections; - QPoint offset = QPoint(0,0); - QFontMetrics fm = QFontMetrics(d->font); - int cix = qRound(d->control->cursorToX()); - QRect br(boundingRect().toRect()); + Q_Q(QDeclarativeTextInput); + QFontMetrics fm = QFontMetrics(font); + int cix = qRound(control->cursorToX()); + QRect br(q->boundingRect().toRect()); //###Is this using bearing appropriately? int minLB = qMax(0, -fm.minLeftBearing()); int minRB = qMax(0, -fm.minRightBearing()); - int widthUsed = qRound(d->control->naturalTextWidth()) + 1 + minRB; - if (d->autoScroll) { + int widthUsed = qRound(control->naturalTextWidth()) + 1 + minRB; + if (autoScroll) { if ((minLB + widthUsed) <= br.width()) { // text fits in br; use hscroll for alignment - switch (d->hAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) { + switch (hAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) { case Qt::AlignRight: - d->hscroll = widthUsed - br.width() + 1; + hscroll = widthUsed - br.width() + 1; break; case Qt::AlignHCenter: - d->hscroll = (widthUsed - br.width()) / 2; + hscroll = (widthUsed - br.width()) / 2; break; default: // Left - d->hscroll = 0; + hscroll = 0; break; } - d->hscroll -= minLB; - } else if (cix - d->hscroll >= br.width()) { + hscroll -= minLB; + } else if (cix - hscroll >= br.width()) { // text doesn't fit, cursor is to the right of br (scroll right) - d->hscroll = cix - br.width() + 1; - } else if (cix - d->hscroll < 0 && d->hscroll < widthUsed) { + hscroll = cix - br.width() + 1; + } else if (cix - hscroll < 0 && hscroll < widthUsed) { // text doesn't fit, cursor is to the left of br (scroll left) - d->hscroll = cix; - } else if (widthUsed - d->hscroll < br.width()) { + hscroll = cix; + } else if (widthUsed - hscroll < br.width()) { // text doesn't fit, text document is to the left of br; align // right - d->hscroll = widthUsed - br.width() + 1; + hscroll = widthUsed - br.width() + 1; + } + } else { + if(hAlign == QDeclarativeTextInput::AlignRight){ + hscroll = q->width() - widthUsed; + }else if(hAlign == QDeclarativeTextInput::AlignHCenter){ + hscroll = (q->width() - widthUsed) / 2; + } else { + hscroll = 0; } + hscroll -= minLB; + } +} + +void QDeclarativeTextInput::drawContents(QPainter *p, const QRect &r) +{ + Q_D(QDeclarativeTextInput); + p->setRenderHint(QPainter::TextAntialiasing, true); + p->save(); + p->setPen(QPen(d->color)); + int flags = QLineControl::DrawText; + if(!isReadOnly() && d->cursorVisible && !d->cursorItem) + flags |= QLineControl::DrawCursor; + if (d->control->hasSelectedText()) + flags |= QLineControl::DrawSelections; + QPoint offset = QPoint(0,0); + QFontMetrics fm = QFontMetrics(d->font); + QRect br(boundingRect().toRect()); + if (d->autoScroll) { // the y offset is there to keep the baseline constant in case we have script changes in the text. offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent()); } else { - if(d->hAlign == AlignRight){ - d->hscroll = width() - widthUsed; - }else if(d->hAlign == AlignHCenter){ - d->hscroll = (width() - widthUsed) / 2; - } - d->hscroll -= minLB; offset = QPoint(d->hscroll, 0); } d->control->draw(p, offset, r, flags); @@ -1236,6 +1252,7 @@ void QDeclarativeTextInput::moveCursorSelection(int position) { Q_D(QDeclarativeTextInput); d->control->moveCursor(position, true); + d->updateHorizontalScroll(); } /*! @@ -1426,6 +1443,7 @@ void QDeclarativeTextInput::selectionChanged() void QDeclarativeTextInput::q_textChanged() { Q_D(QDeclarativeTextInput); + d->updateHorizontalScroll(); updateSize(); emit textChanged(); if(hasAcceptableInput() != d->oldValidity){ diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h index 6865147..8b74bcc 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h @@ -99,6 +99,7 @@ public: void init(); void startCreatingCursor(); void focusChanged(bool hasFocus); + void updateHorizontalScroll(); QLineControl* control; diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index 3143580..a55b42e 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -396,7 +396,6 @@ void tst_qdeclarativetextinput::positionAt() #endif // Check without autoscroll... - QEXPECT_FAIL("", "QTBUG-11127", Abort); textinputObject->setAutoScroll(false); pos = textinputObject->positionAt(textinputObject->width()/2); diff = abs(fm.width(textinputObject->text().left(pos))-textinputObject->width()/2); -- cgit v0.12 From 46e8e2afc6b351b1024f94f5146814bfe866607e Mon Sep 17 00:00:00 2001 From: Kim Motoyoshi Kalland Date: Wed, 16 Jun 2010 12:10:03 +0200 Subject: Fixed infinite recursion when drawing very large painter paths. Task-number: QTBUG-11291 Reviewed-by: Gunnar (cherry picked from commit 7619c210217c85ef6e8d3571cce5d1272b1cb437) --- src/gui/painting/qoutlinemapper.cpp | 8 ++++++-- src/gui/painting/qoutlinemapper_p.h | 4 +++- src/gui/painting/qpaintengine_raster.cpp | 11 +++++------ 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/gui/painting/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp index 1b01960..6038a2a 100644 --- a/src/gui/painting/qoutlinemapper.cpp +++ b/src/gui/painting/qoutlinemapper.cpp @@ -234,12 +234,12 @@ void QOutlineMapper::endOutline() // Check for out of dev bounds... - const bool do_clip = (controlPointRect.left() < -QT_RASTER_COORD_LIMIT + const bool do_clip = !m_in_clip_elements && ((controlPointRect.left() < -QT_RASTER_COORD_LIMIT || controlPointRect.right() > QT_RASTER_COORD_LIMIT || controlPointRect.top() < -QT_RASTER_COORD_LIMIT || controlPointRect.bottom() > QT_RASTER_COORD_LIMIT || controlPointRect.width() > QT_RASTER_COORD_LIMIT - || controlPointRect.height() > QT_RASTER_COORD_LIMIT); + || controlPointRect.height() > QT_RASTER_COORD_LIMIT)); if (do_clip) { clipElements(elements, elementTypes(), element_count); @@ -353,6 +353,8 @@ void QOutlineMapper::clipElements(const QPointF *elements, // instead of going through convenience functionallity, but since // this part of code hardly every used, it shouldn't matter. + m_in_clip_elements = true; + QPainterPath path; if (types) { for (int i=0; ioutlineMapper->m_clip_rect = d->deviceRect.adjusted(-10, -10, 10, 10); - - // This is the upp - QRect bounds(-QT_RASTER_COORD_LIMIT, -QT_RASTER_COORD_LIMIT, - QT_RASTER_COORD_LIMIT*2 - 1, QT_RASTER_COORD_LIMIT * 2 - 1); - d->outlineMapper->m_clip_rect = bounds.intersected(d->outlineMapper->m_clip_rect); + d->outlineMapper->m_clip_rect = d->deviceRect; + if (d->outlineMapper->m_clip_rect.width() > QT_RASTER_COORD_LIMIT) + d->outlineMapper->m_clip_rect.setWidth(QT_RASTER_COORD_LIMIT); + if (d->outlineMapper->m_clip_rect.height() > QT_RASTER_COORD_LIMIT) + d->outlineMapper->m_clip_rect.setHeight(QT_RASTER_COORD_LIMIT); d->rasterizer->setClipRect(d->deviceRect); -- cgit v0.12 From 7b1822dad8091e69a5c0eafb489444d2b7552a5e Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 17 Jun 2010 10:26:13 +1000 Subject: clearFocus() shouldn't mess with focus if it doesn't have focus removing an item from the view caused the focus to change even if the removed item didn't have focus. Task-number: QTBUG-11341 Reviewed-by: Yoann Lopes (cherry picked from commit 7a577ff67388413a882435c5cbd1ad6d1fa8393d) --- src/gui/graphicsview/qgraphicsitem.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 8042c46..c9176d1 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -3277,7 +3277,8 @@ void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool clim */ void QGraphicsItem::clearFocus() { - d_ptr->clearFocusHelper(/* giveFocusToParent = */ true); + if (hasFocus()) + d_ptr->clearFocusHelper(/* giveFocusToParent = */ true); } /*! -- cgit v0.12 From ef6d2ab56754eac8d65bc7a1c851a840f129fa87 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Wed, 16 Jun 2010 16:33:19 +1000 Subject: Stopping a flick resulted in the next click being consumed. Task-number: QTBUG-11390 (cherry picked from commit cfbca0bd925b76fff533dc093c67ad72dbd73de5) --- src/declarative/graphicsitems/qdeclarativeflickable.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index fdc1444..6dfd4d9 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -1214,6 +1214,7 @@ bool QDeclarativeFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event) default: break; } + stealThisEvent = d->stealMouse; // Update stealThisEvent and grabber in case changed by function calls above grabber = qobject_cast(s->mouseGrabberItem()); if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this) { d->clearDelayedPress(); -- cgit v0.12 From 5a549780710cfb2e5110b068dd93f5a8393b0a86 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Fri, 18 Jun 2010 16:01:54 +0200 Subject: Fix a possible crash with the EVR video renderer in windows This can happn when the component can be instanciated but not all the services are available on it. The code is now more robust. Reviewed-By: gabi (cherry picked from commit cf5971503ee1f7a5ce96758e33796dfdf48375bf) --- src/3rdparty/phonon/ds9/videorenderer_evr.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/3rdparty/phonon/ds9/videorenderer_evr.cpp b/src/3rdparty/phonon/ds9/videorenderer_evr.cpp index d23d9ce..de3f46f 100644 --- a/src/3rdparty/phonon/ds9/videorenderer_evr.cpp +++ b/src/3rdparty/phonon/ds9/videorenderer_evr.cpp @@ -43,14 +43,12 @@ namespace Phonon { //normally we should use IID_IMFGetService but this introduces another dependency //so here we simply define our own IId with the same value + ComPointer ret; ComPointer getService(filter, IID_IMFGetService); - Q_ASSERT(getService); - T *ptr = 0; - HRESULT hr = getService->GetService(guidService, riid, reinterpret_cast(&ptr)); - if (!SUCCEEDED(hr) || ptr == 0) - Q_ASSERT(!SUCCEEDED(hr) && ptr != 0); - ComPointer service(ptr); - return service; + if (getService) { + getService->GetService(guidService, riid, reinterpret_cast(ret.pparam())); + } + return ret; } VideoRendererEVR::~VideoRendererEVR() @@ -70,6 +68,10 @@ namespace Phonon } ComPointer filterControl = getService(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl); + if (!filterControl) { + m_filter = Filter(); //will release the interface + return; + } filterControl->SetVideoWindow(reinterpret_cast(target->winId())); filterControl->SetAspectRatioMode(MFVideoARMode_None); // We're in control of the size -- cgit v0.12 From 9c2bf58de3c014345a47013386a84e8a41cf609b Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 21 Jun 2010 14:22:38 +0100 Subject: Update 4.7-beta2 def files Task-number: QTBUG-11585 Reviewed-by: Trust Me (cherry picked from commit 09b770aee2a39e7445d5154e7b8ba3ccc249d55f) --- src/s60installs/bwins/QtCoreu.def | 1 + src/s60installs/bwins/QtDeclarativeu.def | 13 +++++++++++-- src/s60installs/bwins/QtGuiu.def | 7 +++++++ src/s60installs/eabi/QtCoreu.def | 2 ++ src/s60installs/eabi/QtDeclarativeu.def | 17 +++++++++++++---- src/s60installs/eabi/QtGuiu.def | 5 +++++ 6 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/s60installs/bwins/QtCoreu.def b/src/s60installs/bwins/QtCoreu.def index c6d7a2c..45caeb0 100644 --- a/src/s60installs/bwins/QtCoreu.def +++ b/src/s60installs/bwins/QtCoreu.def @@ -4479,4 +4479,5 @@ EXPORTS ?trUtf8@QEventDispatcherSymbian@@SA?AVQString@@PBD0@Z @ 4478 NONAME ; class QString QEventDispatcherSymbian::trUtf8(char const *, char const *) ?trUtf8@QEventDispatcherSymbian@@SA?AVQString@@PBD0H@Z @ 4479 NONAME ; class QString QEventDispatcherSymbian::trUtf8(char const *, char const *, int) ?staticMetaObject@QEventDispatcherSymbian@@2UQMetaObject@@B @ 4480 NONAME ; struct QMetaObject const QEventDispatcherSymbian::staticMetaObject + ?textDirection@QLocale@@QBE?AW4LayoutDirection@Qt@@XZ @ 4481 NONAME ; enum Qt::LayoutDirection QLocale::textDirection(void) const diff --git a/src/s60installs/bwins/QtDeclarativeu.def b/src/s60installs/bwins/QtDeclarativeu.def index 2992cf6..0aac72b 100644 --- a/src/s60installs/bwins/QtDeclarativeu.def +++ b/src/s60installs/bwins/QtDeclarativeu.def @@ -4025,7 +4025,7 @@ EXPORTS ?get@QDeclarativeXmlListModel@@QBE?AVQScriptValue@@H@Z @ 4024 NONAME ; class QScriptValue QDeclarativeXmlListModel::get(int) const ?setScale@QDeclarativeParentChange@@QAEXVQDeclarativeScriptString@@@Z @ 4025 NONAME ; void QDeclarativeParentChange::setScale(class QDeclarativeScriptString) ?showInputPanelOnFocusChanged@QDeclarativeTextEdit@@IAEX_N@Z @ 4026 NONAME ABSENT ; void QDeclarativeTextEdit::showInputPanelOnFocusChanged(bool) - ?focusOutEvent@QDeclarativeTextInput@@MAEXPAVQFocusEvent@@@Z @ 4027 NONAME ; void QDeclarativeTextInput::focusOutEvent(class QFocusEvent *) + ?focusOutEvent@QDeclarativeTextInput@@MAEXPAVQFocusEvent@@@Z @ 4027 NONAME ABSENT ; void QDeclarativeTextInput::focusOutEvent(class QFocusEvent *) ?height@QDeclarativeParentChange@@QBE?AVQDeclarativeScriptString@@XZ @ 4028 NONAME ; class QDeclarativeScriptString QDeclarativeParentChange::height(void) const ?showInputPanelOnFocus@QDeclarativeTextEdit@@QBE_NXZ @ 4029 NONAME ABSENT ; bool QDeclarativeTextEdit::showInputPanelOnFocus(void) const ?errorString@QDeclarativeComponent@@QBE?AVQString@@XZ @ 4030 NONAME ; class QString QDeclarativeComponent::errorString(void) const @@ -4035,7 +4035,7 @@ EXPORTS ?rotation@QDeclarativeParentChange@@QBE?AVQDeclarativeScriptString@@XZ @ 4034 NONAME ; class QDeclarativeScriptString QDeclarativeParentChange::rotation(void) const ?paintedHeight@QDeclarativeTextEdit@@QBEMXZ @ 4035 NONAME ; float QDeclarativeTextEdit::paintedHeight(void) const ?paintedWidth@QDeclarativeTextEdit@@QBEMXZ @ 4036 NONAME ; float QDeclarativeTextEdit::paintedWidth(void) const - ?focusOutEvent@QDeclarativeTextEdit@@MAEXPAVQFocusEvent@@@Z @ 4037 NONAME ; void QDeclarativeTextEdit::focusOutEvent(class QFocusEvent *) + ?focusOutEvent@QDeclarativeTextEdit@@MAEXPAVQFocusEvent@@@Z @ 4037 NONAME ABSENT ; void QDeclarativeTextEdit::focusOutEvent(class QFocusEvent *) ??0QDeclarativeExpression@@IAE@PAVQDeclarativeContextData@@PAVQObject@@ABVQString@@AAVQDeclarativeExpressionPrivate@@@Z @ 4038 NONAME ; QDeclarativeExpression::QDeclarativeExpression(class QDeclarativeContextData *, class QObject *, class QString const &, class QDeclarativeExpressionPrivate &) ??0QDeclarativeExpression@@QAE@PAVQDeclarativeContext@@PAVQObject@@ABVQString@@1@Z @ 4039 NONAME ; QDeclarativeExpression::QDeclarativeExpression(class QDeclarativeContext *, class QObject *, class QString const &, class QObject *) ?queryError@QDeclarativeXmlListModel@@AAEXPAXABVQString@@@Z @ 4040 NONAME ; void QDeclarativeXmlListModel::queryError(void *, class QString const &) @@ -4088,4 +4088,13 @@ EXPORTS ?positionToRectangle@QDeclarativeTextInput@@QBE?AVQRectF@@H@Z @ 4087 NONAME ; class QRectF QDeclarativeTextInput::positionToRectangle(int) const ?positionAt@QDeclarativeTextInput@@QBEHH@Z @ 4088 NONAME ; int QDeclarativeTextInput::positionAt(int) const ?selectWord@QDeclarativeTextEdit@@QAEXXZ @ 4089 NONAME ; void QDeclarativeTextEdit::selectWord(void) + ?setFooter@QDeclarativeGridView@@QAEXPAVQDeclarativeComponent@@@Z @ 4090 NONAME ; void QDeclarativeGridView::setFooter(class QDeclarativeComponent *) + ?isNamed@QDeclarativeState@@QBE_NXZ @ 4091 NONAME ; bool QDeclarativeState::isNamed(void) const + ?initialSize@QDeclarativeView@@QBE?AVQSize@@XZ @ 4092 NONAME ; class QSize QDeclarativeView::initialSize(void) const + ?childAt@QDeclarativeItem@@QBEPAV1@MM@Z @ 4093 NONAME ; class QDeclarativeItem * QDeclarativeItem::childAt(float, float) const + ?footer@QDeclarativeGridView@@QBEPAVQDeclarativeComponent@@XZ @ 4094 NONAME ; class QDeclarativeComponent * QDeclarativeGridView::footer(void) const + ?headerChanged@QDeclarativeGridView@@IAEXXZ @ 4095 NONAME ; void QDeclarativeGridView::headerChanged(void) + ?setHeader@QDeclarativeGridView@@QAEXPAVQDeclarativeComponent@@@Z @ 4096 NONAME ; void QDeclarativeGridView::setHeader(class QDeclarativeComponent *) + ?header@QDeclarativeGridView@@QBEPAVQDeclarativeComponent@@XZ @ 4097 NONAME ; class QDeclarativeComponent * QDeclarativeGridView::header(void) const + ?footerChanged@QDeclarativeGridView@@IAEXXZ @ 4098 NONAME ; void QDeclarativeGridView::footerChanged(void) diff --git a/src/s60installs/bwins/QtGuiu.def b/src/s60installs/bwins/QtGuiu.def index 9b4ecc2..d439927 100644 --- a/src/s60installs/bwins/QtGuiu.def +++ b/src/s60installs/bwins/QtGuiu.def @@ -12813,4 +12813,11 @@ EXPORTS ?setVerticalMovementX@QTextCursor@@QAEXH@Z @ 12812 NONAME ; void QTextCursor::setVerticalMovementX(int) ?invertedAppearance@QProgressBar@@QBE_NXZ @ 12813 NONAME ; bool QProgressBar::invertedAppearance(void) const ?width@QFontMetrics@@QBEHABVQString@@HH@Z @ 12814 NONAME ; int QFontMetrics::width(class QString const &, int, int) const + ?aboutToDestroy@QWidgetPrivate@@UAEXXZ @ 12815 NONAME ; void QWidgetPrivate::aboutToDestroy(void) + ?setTextOption@QStaticText@@QAEXABVQTextOption@@@Z @ 12816 NONAME ; void QStaticText::setTextOption(class QTextOption const &) + ?pointInsideRectAndMask@QWidgetPrivate@@QBE_NABVQPoint@@@Z @ 12817 NONAME ; bool QWidgetPrivate::pointInsideRectAndMask(class QPoint const &) const + ?childAtRecursiveHelper@QWidgetPrivate@@QBEPAVQWidget@@ABVQPoint@@_N1@Z @ 12818 NONAME ; class QWidget * QWidgetPrivate::childAtRecursiveHelper(class QPoint const &, bool, bool) const + ?textOption@QStaticText@@QBE?AVQTextOption@@XZ @ 12819 NONAME ; class QTextOption QStaticText::textOption(void) const + ?isRightToLeft@QTextEngine@@QBE_NXZ @ 12820 NONAME ; bool QTextEngine::isRightToLeft(void) const + ?textDirection@QTextBlock@@QBE?AW4LayoutDirection@Qt@@XZ @ 12821 NONAME ; enum Qt::LayoutDirection QTextBlock::textDirection(void) const diff --git a/src/s60installs/eabi/QtCoreu.def b/src/s60installs/eabi/QtCoreu.def index 0590d39..48cad39 100644 --- a/src/s60installs/eabi/QtCoreu.def +++ b/src/s60installs/eabi/QtCoreu.def @@ -3705,4 +3705,6 @@ EXPORTS _ZlsR11QDataStreamRK12QEasingCurve @ 3704 NONAME _ZltRK13QElapsedTimerS1_ @ 3705 NONAME _ZrsR11QDataStreamR12QEasingCurve @ 3706 NONAME + _ZNK7QLocale13textDirectionEv @ 3707 NONAME + _ZNK7QString13isRightToLeftEv @ 3708 NONAME diff --git a/src/s60installs/eabi/QtDeclarativeu.def b/src/s60installs/eabi/QtDeclarativeu.def index 1c4cd5d..f997454 100644 --- a/src/s60installs/eabi/QtDeclarativeu.def +++ b/src/s60installs/eabi/QtDeclarativeu.def @@ -3605,7 +3605,7 @@ EXPORTS _ZN16QDeclarativeText18paintedSizeChangedEv @ 3604 NONAME _ZN20QDeclarativePathView5eventEP6QEvent @ 3605 NONAME _ZN20QDeclarativeTextEdit12focusInEventEP11QFocusEvent @ 3606 NONAME - _ZN20QDeclarativeTextEdit13focusOutEventEP11QFocusEvent @ 3607 NONAME + _ZN20QDeclarativeTextEdit13focusOutEventEP11QFocusEvent @ 3607 NONAME ABSENT _ZN20QDeclarativeTextEdit16setSelectByMouseEb @ 3608 NONAME _ZN20QDeclarativeTextEdit18paintedSizeChangedEv @ 3609 NONAME _ZN20QDeclarativeTextEdit20selectByMouseChangedEb @ 3610 NONAME @@ -3615,7 +3615,7 @@ EXPORTS _ZN20QDeclarativeTextEdit24setShowInputPanelOnFocusEb @ 3614 NONAME ABSENT _ZN20QDeclarativeTextEdit28showInputPanelOnFocusChangedEb @ 3615 NONAME ABSENT _ZN21QDeclarativeTextInput12focusInEventEP11QFocusEvent @ 3616 NONAME - _ZN21QDeclarativeTextInput13focusOutEventEP11QFocusEvent @ 3617 NONAME + _ZN21QDeclarativeTextInput13focusOutEventEP11QFocusEvent @ 3617 NONAME ABSENT _ZN21QDeclarativeTextInput16setSelectByMouseEb @ 3618 NONAME _ZN21QDeclarativeTextInput20selectByMouseChangedEb @ 3619 NONAME _ZN21QDeclarativeTextInput22openSoftwareInputPanelEv @ 3620 NONAME @@ -3653,9 +3653,9 @@ EXPORTS _ZNK24QDeclarativeXmlListModel11errorStringEv @ 3652 NONAME _ZNK24QDeclarativeXmlListModel3getEi @ 3653 NONAME _ZThn8_N20QDeclarativeTextEdit12focusInEventEP11QFocusEvent @ 3654 NONAME - _ZThn8_N20QDeclarativeTextEdit13focusOutEventEP11QFocusEvent @ 3655 NONAME + _ZThn8_N20QDeclarativeTextEdit13focusOutEventEP11QFocusEvent @ 3655 NONAME ABSENT _ZThn8_N21QDeclarativeTextInput12focusInEventEP11QFocusEvent @ 3656 NONAME - _ZThn8_N21QDeclarativeTextInput13focusOutEventEP11QFocusEvent @ 3657 NONAME + _ZThn8_N21QDeclarativeTextInput13focusOutEventEP11QFocusEvent @ 3657 NONAME ABSENT _ZThn8_NK23QDeclarativePaintedItem12boundingRectEv @ 3658 NONAME _ZN20QDeclarativeTextEdit10selectWordEv @ 3659 NONAME _ZN20QDeclarativeTextEdit19moveCursorSelectionEi @ 3660 NONAME @@ -3672,4 +3672,13 @@ EXPORTS _ZNK21QDeclarativeTextInput15cursorRectangleEv @ 3671 NONAME _ZNK21QDeclarativeTextInput19positionToRectangleEi @ 3672 NONAME _ZThn8_N21QDeclarativeTextInput21mouseDoubleClickEventEP24QGraphicsSceneMouseEvent @ 3673 NONAME + _ZN20QDeclarativeGridView13footerChangedEv @ 3674 NONAME + _ZN20QDeclarativeGridView13headerChangedEv @ 3675 NONAME + _ZN20QDeclarativeGridView9setFooterEP21QDeclarativeComponent @ 3676 NONAME + _ZN20QDeclarativeGridView9setHeaderEP21QDeclarativeComponent @ 3677 NONAME + _ZNK16QDeclarativeItem7childAtEff @ 3678 NONAME + _ZNK16QDeclarativeView11initialSizeEv @ 3679 NONAME + _ZNK17QDeclarativeState7isNamedEv @ 3680 NONAME + _ZNK20QDeclarativeGridView6footerEv @ 3681 NONAME + _ZNK20QDeclarativeGridView6headerEv @ 3682 NONAME diff --git a/src/s60installs/eabi/QtGuiu.def b/src/s60installs/eabi/QtGuiu.def index 9c1002d..b59ddee 100644 --- a/src/s60installs/eabi/QtGuiu.def +++ b/src/s60installs/eabi/QtGuiu.def @@ -12012,4 +12012,9 @@ EXPORTS _ZNK11QTextCursor17verticalMovementXEv @ 12011 NONAME _ZNK11QTextCursor20keepPositionOnInsertEv @ 12012 NONAME _ZNK12QFontMetrics5widthERK7QStringii @ 12013 NONAME + _ZN11QStaticText13setTextOptionERK11QTextOption @ 12014 NONAME + _ZNK10QTextBlock13textDirectionEv @ 12015 NONAME + _ZNK11QStaticText10textOptionEv @ 12016 NONAME + _ZNK11QTextEngine13isRightToLeftEv @ 12017 NONAME + _ZNK14QWidgetPrivate22childAtRecursiveHelperERK6QPointbb @ 12018 NONAME -- cgit v0.12 From 4effb0832834659ebb5bb7cf7d64e272647efeed Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Thu, 17 Jun 2010 14:11:18 -0700 Subject: Assigning 0xA UID3s to the new standalone qml demos Task-number: QTBUG-10148 Reviewed-by: Aleksandar Sasha Babic (cherry picked from commit 3ab8e763a4ddf076dec48d71f0bae098325e1e50) --- demos/embedded/qmlcalculator/deployment.pri | 2 +- demos/embedded/qmlclocks/deployment.pri | 2 +- demos/embedded/qmldialcontrol/deployment.pri | 2 +- demos/embedded/qmleasing/deployment.pri | 2 +- demos/embedded/qmlflickr/deployment.pri | 2 +- demos/embedded/qmlphotoviewer/deployment.pri | 2 +- demos/embedded/qmltwitter/deployment.pri | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/demos/embedded/qmlcalculator/deployment.pri b/demos/embedded/qmlcalculator/deployment.pri index d5078f6..a0bfbb6 100644 --- a/demos/embedded/qmlcalculator/deployment.pri +++ b/demos/embedded/qmlcalculator/deployment.pri @@ -1,6 +1,6 @@ qmlcalculator_src = $$PWD/../../declarative/calculator symbian { - qmlcalculator_uid3 = EA8EBD98 + qmlcalculator_uid3 = A000E3FB qmlcalculator_files.path = ../$$qmlcalculator_uid3 } qmlcalculator_files.sources = $$qmlcalculator_src/calculator.qml $$qmlcalculator_src/Core diff --git a/demos/embedded/qmlclocks/deployment.pri b/demos/embedded/qmlclocks/deployment.pri index 84803ec..a30e403 100644 --- a/demos/embedded/qmlclocks/deployment.pri +++ b/demos/embedded/qmlclocks/deployment.pri @@ -1,6 +1,6 @@ qmlclocks_src = $$PWD/../../../examples/declarative/toys/clocks symbian { - qmlclocks_uid3 = E19225B9 + qmlclocks_uid3 = A000E3FC qmlclocks_files.path = ../$$qmlclocks_uid3 } qmlclocks_files.sources = $$qmlclocks_src/clocks.qml $$qmlclocks_src/content diff --git a/demos/embedded/qmldialcontrol/deployment.pri b/demos/embedded/qmldialcontrol/deployment.pri index 8eb39b2..c04ed05 100644 --- a/demos/embedded/qmldialcontrol/deployment.pri +++ b/demos/embedded/qmldialcontrol/deployment.pri @@ -1,6 +1,6 @@ qmldialcontrol_src = $$PWD/../../../examples/declarative/ui-components/dialcontrol symbian { - qmldialcontrol_uid3 = E59A9283 + qmldialcontrol_uid3 = A000E3FD qmldialcontrol_files.path = ../$$qmldialcontrol_uid3 } qmldialcontrol_files.sources = $$qmldialcontrol_src/dialcontrol.qml $$qmldialcontrol_src/content diff --git a/demos/embedded/qmleasing/deployment.pri b/demos/embedded/qmleasing/deployment.pri index ddab1ba..bc37348 100644 --- a/demos/embedded/qmleasing/deployment.pri +++ b/demos/embedded/qmleasing/deployment.pri @@ -1,6 +1,6 @@ qmleasing_src = $$PWD/../../../examples/declarative/animation/easing symbian { - qmleasing_uid3 = E8E8E725 + qmleasing_uid3 = A000E3FE qmleasing_files.path = ../$$qmleasing_uid3 } qmleasing_files.sources = $$qmleasing_src/easing.qml diff --git a/demos/embedded/qmlflickr/deployment.pri b/demos/embedded/qmlflickr/deployment.pri index aef3198..c1f82df 100644 --- a/demos/embedded/qmlflickr/deployment.pri +++ b/demos/embedded/qmlflickr/deployment.pri @@ -1,6 +1,6 @@ qmlflickr_src = $$PWD/../../declarative/flickr symbian { - qmlflickr_uid3 = E56D5A92 + qmlflickr_uid3 = A000E3FF qmlflickr_files.path = ../$$qmlflickr_uid3 } qmlflickr_files.sources = $$qmlflickr_src/flickr.qml $$qmlflickr_src/common $$qmlflickr_src/mobile diff --git a/demos/embedded/qmlphotoviewer/deployment.pri b/demos/embedded/qmlphotoviewer/deployment.pri index 99475cc..0a457de 100644 --- a/demos/embedded/qmlphotoviewer/deployment.pri +++ b/demos/embedded/qmlphotoviewer/deployment.pri @@ -1,6 +1,6 @@ qmlphotoviewer_src = $$PWD/../../declarative/photoviewer symbian { - qmlphotoviewer_uid3 = E8567E72 + qmlphotoviewer_uid3 = A000E400 qmlphotoviewer_files.path = ../$$qmlphotoviewer_uid3 } qmlphotoviewer_files.sources = $$qmlphotoviewer_src/photoviewer.qml $$qmlphotoviewer_src/PhotoViewerCore diff --git a/demos/embedded/qmltwitter/deployment.pri b/demos/embedded/qmltwitter/deployment.pri index e5bd884..34c8cd1 100644 --- a/demos/embedded/qmltwitter/deployment.pri +++ b/demos/embedded/qmltwitter/deployment.pri @@ -1,6 +1,6 @@ qmltwitter_src = $$PWD/../../declarative/twitter symbian { - qmltwitter_uid3 = EEF6D468 + qmltwitter_uid3 = A000E401 qmltwitter_files.path = ../$$qmltwitter_uid3 } qmltwitter_files.sources = $$qmltwitter_src/twitter.qml $$qmltwitter_src/TwitterCore -- cgit v0.12 From 869623866464f3ac3a3f03c3e135f1101ad31c94 Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Wed, 23 Jun 2010 09:20:54 +0100 Subject: Updated UIDs for spectrum demo Resolving UID clash with other example apps Reviewed-by: Miikka Heikkinen (cherry picked from commit 19ee05c994af7d0c55ec9e4a44e7e485eafc8c66) --- demos/spectrum/3rdparty/fftreal/fftreal.pro | 2 +- demos/spectrum/app/app.pro | 2 +- demos/spectrum/spectrum.pro | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/demos/spectrum/3rdparty/fftreal/fftreal.pro b/demos/spectrum/3rdparty/fftreal/fftreal.pro index 8d9f46e..6801b42 100644 --- a/demos/spectrum/3rdparty/fftreal/fftreal.pro +++ b/demos/spectrum/3rdparty/fftreal/fftreal.pro @@ -29,7 +29,7 @@ DEFINES += FFTREAL_LIBRARY symbian { # Provide unique ID for the generated binary, required by Symbian OS - TARGET.UID3 = 0xA000E3FB + TARGET.UID3 = 0xA000E403 TARGET.CAPABILITY = UserEnvironment } else { macx { diff --git a/demos/spectrum/app/app.pro b/demos/spectrum/app/app.pro index c4b0943..c15edf9 100644 --- a/demos/spectrum/app/app.pro +++ b/demos/spectrum/app/app.pro @@ -48,7 +48,7 @@ symbian { TARGET.CAPABILITY = UserEnvironment # Provide unique ID for the generated binary, required by Symbian OS - TARGET.UID3 = 0xA000E3FA + TARGET.UID3 = 0xA000E402 } diff --git a/demos/spectrum/spectrum.pro b/demos/spectrum/spectrum.pro index a8f09de..12bdec1 100644 --- a/demos/spectrum/spectrum.pro +++ b/demos/spectrum/spectrum.pro @@ -21,7 +21,7 @@ symbian { include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) # UID for the SIS file - TARGET.UID3 = 0xA000E3FA + TARGET.UID3 = 0xA000E402 } sources.files = README.txt spectrum.pri spectrum.pro TODO.txt -- cgit v0.12 From 898b7599a71ab14b54af80defe8c701c34c85907 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Wed, 23 Jun 2010 12:00:59 +0300 Subject: Fix "missing store_build" errors Create a dummy store_build target in projects that do not deploy anything when building for symbian-abld. Task-number: QTBUG-11656 Reviewed-by: Janne Koskinen (cherry picked from commit 4f6a7f7e480dc0c7fada475c1ab04cc3d082e490) --- mkspecs/features/sis_targets.prf | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mkspecs/features/sis_targets.prf b/mkspecs/features/sis_targets.prf index b149a22..349a027 100644 --- a/mkspecs/features/sis_targets.prf +++ b/mkspecs/features/sis_targets.prf @@ -145,6 +145,12 @@ equals(GENERATE_SIS_TARGETS, true) { sis_target.commands = sis_target.target = sis QMAKE_EXTRA_TARGETS += sis_target + + symbian-abld { + # Create dummy store_build target to avoid errors from .mk callbacks during build + store_build_target.target = store_build + QMAKE_EXTRA_TARGETS += store_build_target + } } QMAKE_DISTCLEAN += $${sis_destdir}$${TARGET}.sis -- cgit v0.12 From f14b9b1bbb023ba8f28839bab456e09040449851 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Wed, 23 Jun 2010 14:41:26 +0200 Subject: Provide Qml plugins with UID3s on Symbian ...otherwise we cannot Symbian sign them. (cherry picked from commit 808c045dd351dab32b8add07d45fd77f5a061f61) --- src/imports/folderlistmodel/folderlistmodel.pro | 1 + src/imports/gestures/gestures.pro | 1 + src/imports/particles/particles.pro | 1 + src/imports/webkit/webkit.pro | 1 + 4 files changed, 4 insertions(+) diff --git a/src/imports/folderlistmodel/folderlistmodel.pro b/src/imports/folderlistmodel/folderlistmodel.pro index 781dfc2..9a1be61 100644 --- a/src/imports/folderlistmodel/folderlistmodel.pro +++ b/src/imports/folderlistmodel/folderlistmodel.pro @@ -14,6 +14,7 @@ qmldir.files += $$PWD/qmldir qmldir.path += $$[QT_INSTALL_IMPORTS]/$$TARGETPATH symbian:{ + TARGET.UID3 = 0x20021320 load(data_caging_paths) include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) diff --git a/src/imports/gestures/gestures.pro b/src/imports/gestures/gestures.pro index 4ef7931..ac49b76 100644 --- a/src/imports/gestures/gestures.pro +++ b/src/imports/gestures/gestures.pro @@ -14,6 +14,7 @@ qmldir.files += $$PWD/qmldir qmldir.path += $$[QT_INSTALL_IMPORTS]/$$TARGETPATH symbian:{ + TARGET.UID3 = 0x2002131F load(data_caging_paths) include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) diff --git a/src/imports/particles/particles.pro b/src/imports/particles/particles.pro index 9fd4db5..400c526 100644 --- a/src/imports/particles/particles.pro +++ b/src/imports/particles/particles.pro @@ -18,6 +18,7 @@ qmldir.files += $$PWD/qmldir qmldir.path += $$[QT_INSTALL_IMPORTS]/$$TARGETPATH symbian:{ + TARGET.UID3 = 0x2002131E load(data_caging_paths) include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) diff --git a/src/imports/webkit/webkit.pro b/src/imports/webkit/webkit.pro index 7b2ac66..3661690 100644 --- a/src/imports/webkit/webkit.pro +++ b/src/imports/webkit/webkit.pro @@ -15,6 +15,7 @@ qmldir.files += $$PWD/qmldir qmldir.path += $$[QT_INSTALL_IMPORTS]/$$TARGETPATH symbian:{ + TARGET.UID3 = 0x20021321 load(data_caging_paths) include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) -- cgit v0.12 From 0fef3b8463a3d3b9bb0e4e08b964794eb40bd55d Mon Sep 17 00:00:00 2001 From: Kim Motoyoshi Kalland Date: Fri, 18 Jun 2010 15:09:12 +0200 Subject: Fixed device context leak in QGLWidget on Windows. Commit 392123ef5432643d1047d1e1dd71512ec39d382d introduced the leak. Task-number: QTBUG-11432 Reviewed-by: Trond (cherry picked from commit 38adb59a9e80a23d37ff0820ef62ebd45ab1e4ae) --- src/gui/kernel/qapplication_win.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 09535fa..cf28893 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -957,6 +957,9 @@ const QString qt_reg_winclass(QWidget *w) // register window class if (qt_widget_private(w)->isGLWidget) { cname = QLatin1String("QGLWidget"); style = CS_DBLCLKS; +#ifndef Q_WS_WINCE + style |= CS_OWNDC; +#endif icon = true; } else if (flags & Qt::MSWindowsOwnDC) { cname = QLatin1String("QWidgetOwnDC"); -- cgit v0.12 From 7bf890a45139c06a66eb362dec9fa6e17205291d Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 29 Jun 2010 16:36:04 +0200 Subject: don't complain multiple times about same abuse of //% meta strings Reviewed-by: Kent Hansen Task-number: QTBUG-11818 (cherry picked from commit f08b60f4ca52d525c1dc9890cb0c6661ee34b069) --- .../lupdate/testdata/good/parsecpp2/expectedoutput.txt | 2 ++ .../auto/linguist/lupdate/testdata/good/parsecpp2/main.cpp | 13 +++++++++++++ .../lupdate/testdata/good/parsecpp2/project.ts.result | 12 ++++++++++++ tools/linguist/lupdate/cpp.cpp | 3 +++ 4 files changed, 30 insertions(+) diff --git a/tests/auto/linguist/lupdate/testdata/good/parsecpp2/expectedoutput.txt b/tests/auto/linguist/lupdate/testdata/good/parsecpp2/expectedoutput.txt index 195c0e6..959938c 100644 --- a/tests/auto/linguist/lupdate/testdata/good/parsecpp2/expectedoutput.txt +++ b/tests/auto/linguist/lupdate/testdata/good/parsecpp2/expectedoutput.txt @@ -2,3 +2,5 @@ .*/lupdate/testdata/good/parsecpp2/main.cpp:55: Excess closing brace .* .*/lupdate/testdata/good/parsecpp2/main.cpp:61: Excess closing brace .* .*/lupdate/testdata/good/parsecpp2/main.cpp:65: Excess closing brace .* +.*/lupdate/testdata/good/parsecpp2/main.cpp:120: //% cannot be used with tr\(\) / QT_TR_NOOP\(\)\. Ignoring +.*/lupdate/testdata/good/parsecpp2/main.cpp:123: //% cannot be used with translate\(\) / QT_TRANSLATE_NOOP\(\)\. Ignoring diff --git a/tests/auto/linguist/lupdate/testdata/good/parsecpp2/main.cpp b/tests/auto/linguist/lupdate/testdata/good/parsecpp2/main.cpp index feb885c..06e6fe0 100644 --- a/tests/auto/linguist/lupdate/testdata/good/parsecpp2/main.cpp +++ b/tests/auto/linguist/lupdate/testdata/good/parsecpp2/main.cpp @@ -112,3 +112,16 @@ void ToBeUsed::caller() { tr("NameSpace::ToBeUsed"); } + + + +// QTBUG-11818 +//% "Foo" +QObject::tr("Hello World"); +QObject::tr("Hello World"); +//% "Bar" +QApplication::translate("QObject", "Hello World"); +QApplication::translate("QObject", "Hello World"); +//% "Baz" +clear = me; +QObject::tr("Hello World"); diff --git a/tests/auto/linguist/lupdate/testdata/good/parsecpp2/project.ts.result b/tests/auto/linguist/lupdate/testdata/good/parsecpp2/project.ts.result index 6f48e27..806f56f 100644 --- a/tests/auto/linguist/lupdate/testdata/good/parsecpp2/project.ts.result +++ b/tests/auto/linguist/lupdate/testdata/good/parsecpp2/project.ts.result @@ -10,6 +10,18 @@ + QObject + + + + + + + Hello World + + + + TopLevel diff --git a/tools/linguist/lupdate/cpp.cpp b/tools/linguist/lupdate/cpp.cpp index b3e7e84..97fa04c 100644 --- a/tools/linguist/lupdate/cpp.cpp +++ b/tools/linguist/lupdate/cpp.cpp @@ -1858,6 +1858,7 @@ void CppParser::parseInternal(ConversionData &cd, QSet &inclusions) gotctx: recordMessage(line, context, text, comment, extracomment, msgid, extra, utf8, plural); } + sourcetext.clear(); // Will have warned about that already extracomment.clear(); msgid.clear(); extra.clear(); @@ -1913,6 +1914,7 @@ void CppParser::parseInternal(ConversionData &cd, QSet &inclusions) } recordMessage(line, context, text, comment, extracomment, msgid, extra, utf8, plural); } + sourcetext.clear(); // Will have warned about that already extracomment.clear(); msgid.clear(); extra.clear(); @@ -2079,6 +2081,7 @@ void CppParser::parseInternal(ConversionData &cd, QSet &inclusions) case Tok_Semicolon: prospectiveContext.clear(); prefix.clear(); + sourcetext.clear(); extracomment.clear(); msgid.clear(); extra.clear(); -- cgit v0.12 From fd75bec667e011c0700e0e6bcd45ff2fc29beb8d Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Tue, 29 Jun 2010 14:38:42 +0300 Subject: Fix s60main linking issue with gcce applications MMP_RULES_DONT_EXPORT_ALL_CLASS_IMPEDIMENTA must not be included in s60main build, otherwise some symbols will not be relocatable when linked against from gcce build. Task-number: QTBUG-11804 Reviewed-by: Alessandro Portale (cherry picked from commit ce57d92ef5723f54c1e3a1b50d66eb74273b995b) --- src/s60main/s60main.pro | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/s60main/s60main.pro b/src/s60main/s60main.pro index 1ba105d..9ea3080 100644 --- a/src/s60main/s60main.pro +++ b/src/s60main/s60main.pro @@ -25,6 +25,10 @@ symbian { # Workaround for abld toolchain problem to make ARMV6 qtmain.lib link with GCCE apps symbian-abld: QMAKE_CXXFLAGS.ARMCC += --dllimport_runtime + + # Having MMP_RULES_DONT_EXPORT_ALL_CLASS_IMPEDIMENTA will cause s60main.lib be unlinkable + # against GCCE apps, so remove it + MMP_RULES -= $$MMP_RULES_DONT_EXPORT_ALL_CLASS_IMPEDIMENTA } else { error("$$_FILE_ is intended only for Symbian!") } -- cgit v0.12 From d7513a5994c734ed48e95ec55d1abd9147c75405 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Fri, 11 Jun 2010 12:36:34 +0200 Subject: Changed the way we detect touch screen on Windows. Instead of using the IInkTablets interface (which sometimes freezes in the get_Count() call for 10 seconds), we just check if there is digitizer support. Task-number: QTBUG-6007 Reviewed-by: Prasanth (cherry picked from commit 7f338180e88b71e793069e2fbe9a70f3c434e126) --- src/gui/kernel/qapplication_win.cpp | 36 +++------------------- .../kernel/qwinnativepangesturerecognizer_win_p.h | 32 +++++++++++++++++++ 2 files changed, 36 insertions(+), 32 deletions(-) diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index cf28893..610dec5 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -118,8 +118,6 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c # include #endif -#include "private/qwinnativepangesturerecognizer_win_p.h" - #ifndef WM_TOUCH # define WM_TOUCH 0x0240 @@ -4069,36 +4067,10 @@ PtrCloseTouchInputHandle QApplicationPrivate::CloseTouchInputHandle = 0; void QApplicationPrivate::initializeMultitouch_sys() { - static const IID QT_IID_IInkTablets = {0x112086D9, 0x7779, 0x4535, {0xA6, 0x99, 0x86, 0x2B, 0x43, 0xAC, 0x18, 0x63} }; - static const IID QT_IID_IInkTablet2 = {0x90c91ad2, 0xfa36, 0x49d6, {0x95, 0x16, 0xce, 0x8d, 0x57, 0x0f, 0x6f, 0x85} }; - static const CLSID QT_CLSID_InkTablets = {0x6E4FCB12, 0x510A, 0x4d40, {0x93, 0x04, 0x1D, 0xA1, 0x0A, 0xE9, 0x14, 0x7C} }; - - IInkTablets *iInkTablets = 0; - HRESULT hr = CoCreateInstance(QT_CLSID_InkTablets, NULL, CLSCTX_ALL, QT_IID_IInkTablets, (void**)&iInkTablets); - if (SUCCEEDED(hr)) { - long count = 0; - iInkTablets->get_Count(&count); - for (long i = 0; i < count; ++i) { - IInkTablet *iInkTablet = 0; - hr = iInkTablets->Item(i, &iInkTablet); - if (FAILED(hr)) - continue; - IInkTablet2 *iInkTablet2 = 0; - hr = iInkTablet->QueryInterface(QT_IID_IInkTablet2, (void**)&iInkTablet2); - iInkTablet->Release(); - if (FAILED(hr)) - continue; - TabletDeviceKind kind; - hr = iInkTablet2->get_DeviceKind(&kind); - iInkTablet2->Release(); - if (FAILED(hr)) - continue; - if (kind == TDK_Touch) { - QApplicationPrivate::HasTouchSupport = true; - break; - } - } - iInkTablets->Release(); + if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) { + static const int QT_SM_DIGITIZER = 94; + QApplicationPrivate::HasTouchSupport = GetSystemMetrics(QT_SM_DIGITIZER); + qDebug() << "QApplicationPrivate::HasTouchSupport " << QApplicationPrivate::HasTouchSupport; } QLibrary library(QLatin1String("user32")); diff --git a/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h b/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h index 64addeb..eb99b74 100644 --- a/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h +++ b/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h @@ -54,6 +54,38 @@ // #include +#include + +class IInkRectangle; +class TabletHardwareCapabilities; +class TabletPropertyMetricUnit; +DECLARE_INTERFACE_(IInkTablet, IDispatch) +{ + STDMETHOD(get_Name)(THIS_ BSTR *Name) PURE; + STDMETHOD(get_PlugAndPlayId)(THIS_ BSTR *Id) PURE; + STDMETHOD(get_MaximumInputRectangle)(THIS_ IInkRectangle **Rectangle) PURE; + STDMETHOD(get_HardwareCapabilities)(THIS_ TabletHardwareCapabilities *Capabilities) PURE; + STDMETHOD(IsPacketPropertySupported)(THIS_ BSTR packetPropertyName) PURE; + STDMETHOD(GetPropertyMetrics)(THIS_ BSTR propertyName, long *Minimum, long *Maximum, TabletPropertyMetricUnit *Units, float *Resolution) PURE; +}; +enum TabletDeviceKind +{ + TDK_Mouse = 0, + TDK_Pen = 1, + TDK_Touch = 2 +}; +DECLARE_INTERFACE_(IInkTablet2, IDispatch) +{ + STDMETHOD(get_DeviceKind)(THIS_ TabletDeviceKind *Kind) PURE; +}; +DECLARE_INTERFACE_(IInkTablets, IDispatch) +{ + STDMETHOD(get_Count)(THIS_ long *Count) PURE; + STDMETHOD(get__NewEnum)(THIS_ IUnknown **_NewEnum) PURE; + STDMETHOD(get_DefaultTablet)(THIS_ IInkTablet **DefaultTablet) PURE; + STDMETHOD(Item)(THIS_ long Index, IInkTablet **Tablet) PURE; + STDMETHOD(IsPacketPropertySupported)(THIS_ BSTR packetPropertyName, VARIANT_BOOL *Supported) PURE; +}; #include -- cgit v0.12 From 53c58703223bdc8cef84b0d26f80573be3de91fb Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Fri, 11 Jun 2010 13:26:05 +0200 Subject: Fixed a broken merge. Reviewed-by: trustme (cherry picked from commit 24bcac9de46c89f4d8b533946e7b0feeacca1b0d) --- src/gui/kernel/qapplication_win.cpp | 1 - .../kernel/qwinnativepangesturerecognizer_win_p.h | 65 ---------------------- 2 files changed, 66 deletions(-) diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 610dec5..2a85fdc 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -4070,7 +4070,6 @@ void QApplicationPrivate::initializeMultitouch_sys() if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) { static const int QT_SM_DIGITIZER = 94; QApplicationPrivate::HasTouchSupport = GetSystemMetrics(QT_SM_DIGITIZER); - qDebug() << "QApplicationPrivate::HasTouchSupport " << QApplicationPrivate::HasTouchSupport; } QLibrary library(QLatin1String("user32")); diff --git a/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h b/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h index eb99b74..9d0e6f7 100644 --- a/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h +++ b/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h @@ -54,71 +54,6 @@ // #include -#include - -class IInkRectangle; -class TabletHardwareCapabilities; -class TabletPropertyMetricUnit; -DECLARE_INTERFACE_(IInkTablet, IDispatch) -{ - STDMETHOD(get_Name)(THIS_ BSTR *Name) PURE; - STDMETHOD(get_PlugAndPlayId)(THIS_ BSTR *Id) PURE; - STDMETHOD(get_MaximumInputRectangle)(THIS_ IInkRectangle **Rectangle) PURE; - STDMETHOD(get_HardwareCapabilities)(THIS_ TabletHardwareCapabilities *Capabilities) PURE; - STDMETHOD(IsPacketPropertySupported)(THIS_ BSTR packetPropertyName) PURE; - STDMETHOD(GetPropertyMetrics)(THIS_ BSTR propertyName, long *Minimum, long *Maximum, TabletPropertyMetricUnit *Units, float *Resolution) PURE; -}; -enum TabletDeviceKind -{ - TDK_Mouse = 0, - TDK_Pen = 1, - TDK_Touch = 2 -}; -DECLARE_INTERFACE_(IInkTablet2, IDispatch) -{ - STDMETHOD(get_DeviceKind)(THIS_ TabletDeviceKind *Kind) PURE; -}; -DECLARE_INTERFACE_(IInkTablets, IDispatch) -{ - STDMETHOD(get_Count)(THIS_ long *Count) PURE; - STDMETHOD(get__NewEnum)(THIS_ IUnknown **_NewEnum) PURE; - STDMETHOD(get_DefaultTablet)(THIS_ IInkTablet **DefaultTablet) PURE; - STDMETHOD(Item)(THIS_ long Index, IInkTablet **Tablet) PURE; - STDMETHOD(IsPacketPropertySupported)(THIS_ BSTR packetPropertyName, VARIANT_BOOL *Supported) PURE; -}; - -#include - -class IInkRectangle; -class TabletHardwareCapabilities; -class TabletPropertyMetricUnit; -DECLARE_INTERFACE_(IInkTablet, IDispatch) -{ - STDMETHOD(get_Name)(THIS_ BSTR *Name) PURE; - STDMETHOD(get_PlugAndPlayId)(THIS_ BSTR *Id) PURE; - STDMETHOD(get_MaximumInputRectangle)(THIS_ IInkRectangle **Rectangle) PURE; - STDMETHOD(get_HardwareCapabilities)(THIS_ TabletHardwareCapabilities *Capabilities) PURE; - STDMETHOD(IsPacketPropertySupported)(THIS_ BSTR packetPropertyName) PURE; - STDMETHOD(GetPropertyMetrics)(THIS_ BSTR propertyName, long *Minimum, long *Maximum, TabletPropertyMetricUnit *Units, float *Resolution) PURE; -}; -enum TabletDeviceKind -{ - TDK_Mouse = 0, - TDK_Pen = 1, - TDK_Touch = 2 -}; -DECLARE_INTERFACE_(IInkTablet2, IDispatch) -{ - STDMETHOD(get_DeviceKind)(THIS_ TabletDeviceKind *Kind) PURE; -}; -DECLARE_INTERFACE_(IInkTablets, IDispatch) -{ - STDMETHOD(get_Count)(THIS_ long *Count) PURE; - STDMETHOD(get__NewEnum)(THIS_ IUnknown **_NewEnum) PURE; - STDMETHOD(get_DefaultTablet)(THIS_ IInkTablet **DefaultTablet) PURE; - STDMETHOD(Item)(THIS_ long Index, IInkTablet **Tablet) PURE; - STDMETHOD(IsPacketPropertySupported)(THIS_ BSTR packetPropertyName, VARIANT_BOOL *Supported) PURE; -}; #ifndef QT_NO_GESTURES -- cgit v0.12 From a37ae8590026de2ef150e3da1b4b986022d6294a Mon Sep 17 00:00:00 2001 From: Morten Engvoldsen Date: Tue, 6 Jul 2010 10:07:54 +0200 Subject: Doc: fixing img style --- doc/src/template/style/style.css | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/doc/src/template/style/style.css b/doc/src/template/style/style.css index 299806b..184a832 100755 --- a/doc/src/template/style/style.css +++ b/doc/src/template/style/style.css @@ -18,6 +18,8 @@ fieldset, img { border: 0; + height:100%; + width:100% } address, caption, cite, code, dfn, em, strong, th, var, optgroup { @@ -756,6 +758,7 @@ pre { border: 1px solid #DDDDDD; + -moz-border-radius: 7px 7px 7px 7px; margin: 0 20px 10px 10px; padding: 20px 15px 20px 20px; overflow-x: auto; @@ -1023,6 +1026,7 @@ } h3.fn, span.fn { + -moz-border-radius:7px 7px 7px 7px; background-color: #F6F6F6; border-width: 1px; border-style: solid; @@ -1040,6 +1044,7 @@ border-width: 1px; border-style: solid; border-color: #E6E6E6; + -moz-border-radius: 7px 7px 7px 7px; width:100%; } @@ -1199,6 +1204,7 @@ vertical-align:top; width:100%; background-color:#F6F6F6; border:1px solid #E6E6E6; +-moz-border-radius: 7px 7px 7px 7px; font-size:12pt; padding-left:10px; margin-top:10px; @@ -1250,8 +1256,9 @@ pre.highlightedCode { } .navTop{ float:right; - padding-right:5px; - margin-top:15px; + display:block; + padding-right:15px; + /*margin-top:10px;*/ } .wrap .content .toc h3{ -- cgit v0.12 From f36d829ef02c54b18734dd027a1c0d9b55a6171f Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Mon, 5 Jul 2010 07:22:42 -0700 Subject: Spectrum build: fixed DLL rpath Rather than explicitly modifying LD_LIBRARY_PATH using a shell script when the application is launched, the relative path from the application binary to the FFT library is encoded in the application using an --rpath flag. Task-number: QTBUG-11756 Reviewed-by: Andy Shaw --- demos/spectrum/app/app.pro | 13 +++-------- demos/spectrum/app/spectrum.sh | 50 ------------------------------------------ 2 files changed, 3 insertions(+), 60 deletions(-) delete mode 100644 demos/spectrum/app/spectrum.sh diff --git a/demos/spectrum/app/app.pro b/demos/spectrum/app/app.pro index ebeef87..28fdab0 100644 --- a/demos/spectrum/app/app.pro +++ b/demos/spectrum/app/app.pro @@ -3,7 +3,6 @@ include(../spectrum.pri) TEMPLATE = app TARGET = spectrum -unix: !macx: !symbian: TARGET = spectrum.bin QT += multimedia @@ -113,15 +112,9 @@ symbian { # Specify directory in which to create spectrum application DESTDIR = ../bin - unix: !symbian { - # On unices other than Mac OSX, we copy a shell script into the bin directory. - # This script takes care of correctly setting the LD_LIBRARY_PATH so that - # the dynamic library can be located. - copy_launch_script.target = copy_launch_script - copy_launch_script.commands = \ - install -m 0555 $$QT_SOURCE_TREE/demos/spectrum/app/spectrum.sh ../bin/spectrum - QMAKE_EXTRA_TARGETS += copy_launch_script - POST_TARGETDEPS += copy_launch_script + unix: { + # Provide relative path from application to fftreal library + QMAKE_LFLAGS += -Wl,--rpath=\\\$\$ORIGIN } } } diff --git a/demos/spectrum/app/spectrum.sh b/demos/spectrum/app/spectrum.sh deleted file mode 100644 index 2a230ed..0000000 --- a/demos/spectrum/app/spectrum.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/sh -############################################################################# -## -## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -## All rights reserved. -## Contact: Nokia Corporation (qt-info@nokia.com) -## -## This file is part of the examples of the Qt Toolkit. -## -## $QT_BEGIN_LICENSE:LGPL$ -## No Commercial Usage -## This file contains pre-release code and may not be distributed. -## You may use this file in accordance with the terms and conditions -## contained in the Technology Preview License Agreement accompanying -## this package. -## -## 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, Nokia gives you certain additional -## rights. These rights are described in the Nokia Qt LGPL Exception -## version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -## -## If you have questions regarding the use of this file, please contact -## Nokia at qt-info@nokia.com. -## -## -## -## -## -## -## -## -## $QT_END_LICENSE$ -## -############################################################################# - - -# Shell script for launching spectrum application on Unix systems other than Mac OSX - -bindir=`dirname "$0"` -LD_LIBRARY_PATH="${bindir}:${LD_LIBRARY_PATH}" -export LD_LIBRARY_PATH -exec "${bindir}/spectrum.bin" ${1+"$@"} - -- cgit v0.12 From 78f48dc47dd7ea52f2ad979a7fd5289da9f22e66 Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Mon, 5 Jul 2010 11:39:37 +0100 Subject: Spectrum demo: fixed installation All binaries must be written into $$QT_BUILD_DIR/demos/spectrum in order for them to be correctly installed. Task-number: QTBUG-11572 Task-number: QTBUG-11756 Reviewed-by: Andy Shaw --- demos/spectrum/3rdparty/fftreal/fftreal.pro | 14 ++++++++------ demos/spectrum/app/app.pro | 7 +++---- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/demos/spectrum/3rdparty/fftreal/fftreal.pro b/demos/spectrum/3rdparty/fftreal/fftreal.pro index 6801b42..c9da205 100644 --- a/demos/spectrum/3rdparty/fftreal/fftreal.pro +++ b/demos/spectrum/3rdparty/fftreal/fftreal.pro @@ -1,3 +1,5 @@ +include(../../spectrum.pri) + TEMPLATE = lib TARGET = fftreal @@ -31,13 +33,13 @@ symbian { # Provide unique ID for the generated binary, required by Symbian OS TARGET.UID3 = 0xA000E403 TARGET.CAPABILITY = UserEnvironment +} + +macx { + CONFIG += lib_bundle } else { - macx { - CONFIG += lib_bundle - } else { - DESTDIR = ../../bin - } -} + !symbian: DESTDIR = ../.. +} # Install diff --git a/demos/spectrum/app/app.pro b/demos/spectrum/app/app.pro index 28fdab0..1b419db 100644 --- a/demos/spectrum/app/app.pro +++ b/demos/spectrum/app/app.pro @@ -63,8 +63,7 @@ symbian { LIBS += -F$${fftreal_dir} LIBS += -framework fftreal } else { - # Link to dynamic library which is written to ../bin - LIBS += -L../bin + LIBS += -L.. LIBS += -lfftreal } } @@ -85,7 +84,7 @@ symbian { !contains(DEFINES, DISABLE_FFT) { # Include FFTReal DLL in the SIS file - fftreal.sources = ../3rdparty/fftreal/fftreal.dll + fftreal.sources = ../fftreal.dll fftreal.path = !:/sys/bin DEPLOYMENT += fftreal } @@ -110,7 +109,7 @@ symbian { } } else { # Specify directory in which to create spectrum application - DESTDIR = ../bin + DESTDIR = .. unix: { # Provide relative path from application to fftreal library -- cgit v0.12 From 3b6c44f773d293f807784b775f352873c793e75a Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Tue, 6 Jul 2010 12:24:20 +0200 Subject: qdoc: Simplified code to enable fixing of QTBUG-6340. Also reworded some of the text for QTBUG-11575. Task-number: QTBUG-6340, QTBUG-11575 --- doc/src/declarative/extending.qdoc | 24 +- tools/qdoc3/htmlgenerator.cpp | 457 ++++++------------------------------- tools/qdoc3/htmlgenerator.h | 25 +- tools/qdoc3/tree.cpp | 17 +- 4 files changed, 97 insertions(+), 426 deletions(-) diff --git a/doc/src/declarative/extending.qdoc b/doc/src/declarative/extending.qdoc index 28d4ed4..2fd6fa8 100644 --- a/doc/src/declarative/extending.qdoc +++ b/doc/src/declarative/extending.qdoc @@ -423,22 +423,14 @@ signals with the \l {Connections} element. Additionally, if a property is added to a C++ class, all QML elements based on that C++ class will have a \e{value-changed} signal handler -for that property. The name of the signal handler is \e{onChanged}, with the first letter of the property name being upper -cased. - -\note If the NOTIFY signal for the added property is not simply -\c{Changed()}, then you will get two equivalent signal -handlers, one because of the signal, one because of the property. For -example, if the property \c{test_property} with NOTIFY signal -\c{testPropChanged()} is added to a C++ class, then QML elements based -on that C++ class will have two signal handlers: -\c{onTest_propertyChanged} because of the property, and -\c{onTestPropChanged} because of the NOTIFY signal. For clarity, we -suggest that for properties exposed to QML in this way, the name of -the NOTIFY signal should be just \c{Changed()}, so that -there will be just one signal handler in QML and one naming -convention used. +for that property. The name of the signal handler is +\e{onChanged}, with the first letter of the property +name being upper case. + +\note The QML signal handler will always be named +onChanged, regardless of the name used for the NOTIFY +signal in C++. We recommend using Changed() for the +NOTIFY signal in C++. See also \l {Extending types from QML}. diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp index 49ba5f6..89b1e98 100644 --- a/tools/qdoc3/htmlgenerator.cpp +++ b/tools/qdoc3/htmlgenerator.cpp @@ -1359,7 +1359,7 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, if (!s->inherited.isEmpty()) { out() << "
    \n"; - generateSectionInheritedList(*s, inner, marker, true); + generateSectionInheritedList(*s, inner, marker); out() << "
\n"; } } @@ -2636,44 +2636,6 @@ void HtmlGenerator::generateLegaleseList(const Node *relative, } } -/*void HtmlGenerator::generateSynopsis(const Node *node, - const Node *relative, - CodeMarker *marker, - CodeMarker::SynopsisStyle style) -{ - QString marked = marker->markedUpSynopsis(node, relative, style); - QRegExp templateTag("(<[^@>]*>)"); - if (marked.indexOf(templateTag) != -1) { - QString contents = protectEnc(marked.mid(templateTag.pos(1), - templateTag.cap(1).length())); - marked.replace(templateTag.pos(1), templateTag.cap(1).length(), - contents); - } - marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])"), - "\\1\\2"); - marked.replace("<@param>", ""); - marked.replace("", ""); - - if (style == CodeMarker::Summary) - marked.replace("@name>", "b>"); - - if (style == CodeMarker::SeparateList) { - QRegExp extraRegExp("<@extra>.*"); - extraRegExp.setMinimal(true); - marked.replace(extraRegExp, ""); - } - else { - marked.replace("<@extra>", "  "); - marked.replace("", ""); - } - - if (style != CodeMarker::Detailed) { - marked.replace("<@type>", ""); - marked.replace("", ""); - } - out() << highlightedCode(marked, marker, relative); -}*/ - #ifdef QDOC_QML void HtmlGenerator::generateQmlItem(const Node *node, const Node *relative, @@ -2703,6 +2665,17 @@ void HtmlGenerator::generateQmlItem(const Node *node, marked.replace("<@type>", ""); marked.replace("", ""); } + if (node->type() == Node::QmlProperty) { + const QmlPropertyNode* qpn = static_cast(node); + if (!summary && qpn->name() == "color" && qpn->dataType() == "color") { + if (relative && relative->name() == "GradientStop") { + qDebug() << "color : color"; + debugging_on = true; + qDebug() << " " << relative->name() << relative->type() << relative->subType(); + qDebug() << marked; + } + } + } out() << highlightedCode(marked, marker, relative); debugging_on = false; } @@ -2822,24 +2795,23 @@ void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* m } } -#ifdef QDOC_NAME_ALIGNMENT void HtmlGenerator::generateSection(const NodeList& nl, const Node *relative, CodeMarker *marker, CodeMarker::SynopsisStyle style) { - bool name_alignment = true; + bool alignNames = true; if (!nl.isEmpty()) { bool twoColumn = false; if (style == CodeMarker::SeparateList) { - name_alignment = false; + alignNames = false; twoColumn = (nl.count() >= 16); } else if (nl.first()->type() == Node::Property) { twoColumn = (nl.count() >= 5); - name_alignment = false; + alignNames = false; } - if (name_alignment) { + if (alignNames) { out() << "\n"; } else { @@ -2857,7 +2829,7 @@ void HtmlGenerator::generateSection(const NodeList& nl, continue; } - if (name_alignment) { + if (alignNames) { out() << "\n"; else out() << "\n"; i++; ++m; } - if (name_alignment) + if (alignNames) out() << "
"; } else { @@ -2866,15 +2838,15 @@ void HtmlGenerator::generateSection(const NodeList& nl, out() << "
  • "; } - generateSynopsis(*m, relative, marker, style, name_alignment); - if (name_alignment) + generateSynopsis(*m, relative, marker, style, alignNames); + if (alignNames) out() << "
  • \n"; else { out() << "\n"; @@ -2889,18 +2861,18 @@ void HtmlGenerator::generateSectionList(const Section& section, CodeMarker *marker, CodeMarker::SynopsisStyle style) { - bool name_alignment = true; + bool alignNames = true; if (!section.members.isEmpty()) { bool twoColumn = false; if (style == CodeMarker::SeparateList) { - name_alignment = false; + alignNames = false; twoColumn = (section.members.count() >= 16); } else if (section.members.first()->type() == Node::Property) { twoColumn = (section.members.count() >= 5); - name_alignment = false; + alignNames = false; } - if (name_alignment) { + if (alignNames) { out() << "\n"; } else { @@ -2918,7 +2890,7 @@ void HtmlGenerator::generateSectionList(const Section& section, continue; } - if (name_alignment) { + if (alignNames) { out() << "\n"; else out() << "\n"; i++; ++m; } - if (name_alignment) + if (alignNames) out() << "
    "; } else { @@ -2927,15 +2899,15 @@ void HtmlGenerator::generateSectionList(const Section& section, out() << "
  • "; } - generateSynopsis(*m, relative, marker, style, name_alignment); - if (name_alignment) + generateSynopsis(*m, relative, marker, style, alignNames); + if (alignNames) out() << "
  • \n"; else { out() << "\n"; @@ -2946,22 +2918,18 @@ void HtmlGenerator::generateSectionList(const Section& section, if (style == CodeMarker::Summary && !section.inherited.isEmpty()) { out() << "
      \n"; - generateSectionInheritedList(section, relative, marker, name_alignment); + generateSectionInheritedList(section, relative, marker); out() << "
    \n"; } } void HtmlGenerator::generateSectionInheritedList(const Section& section, const Node *relative, - CodeMarker *marker, - bool nameAlignment) + CodeMarker *marker) { QList >::ConstIterator p = section.inherited.begin(); while (p != section.inherited.end()) { - if (nameAlignment) - out() << "
  • "; - else - out() << "
  • "; + out() << "
  • "; out() << (*p).second << " "; if ((*p).second == 1) { out() << section.singularMember; @@ -2981,7 +2949,7 @@ void HtmlGenerator::generateSynopsis(const Node *node, const Node *relative, CodeMarker *marker, CodeMarker::SynopsisStyle style, - bool nameAlignment) + bool alignNames) { QString marked = marker->markedUpSynopsis(node, relative, style); QRegExp templateTag("(<[^@>]*>)"); @@ -3014,14 +2982,13 @@ void HtmlGenerator::generateSynopsis(const Node *node, marked.replace("<@type>", ""); marked.replace("", ""); } - out() << highlightedCode(marked, marker, relative, style, nameAlignment); + out() << highlightedCode(marked, marker, relative, alignNames); } QString HtmlGenerator::highlightedCode(const QString& markedCode, - CodeMarker *marker, - const Node *relative, - CodeMarker::SynopsisStyle , - bool nameAlignment) + CodeMarker* marker, + const Node* relative, + bool alignNames) { QString src = markedCode; QString html; @@ -3031,20 +2998,24 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, const QChar charLangle = '<'; const QChar charAt = '@'; - // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*()" + static const QString typeTag("type"); + static const QString headerTag("headerfile"); + static const QString funcTag("func"); static const QString linkTag("link"); + + // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*()" bool done = false; - for (int i = 0, n = src.size(); i < n;) { + for (int i = 0, srcSize = src.size(); i < srcSize;) { if (src.at(i) == charLangle && src.at(i + 1).unicode() == '@') { - if (nameAlignment && !done) {// && (i != 0)) Why was this here? + if (alignNames && !done) {// && (i != 0)) Why was this here? html += ""; done = true; } i += 2; - if (parseArg(src, linkTag, &i, n, &arg, &par1)) { + if (parseArg(src, linkTag, &i, srcSize, &arg, &par1)) { html += ""; - QString link = linkForNode( - CodeMarker::nodeForString(par1.toString()), relative); + const Node* n = CodeMarker::nodeForString(par1.toString()); + QString link = linkForNode(n, relative); addLink(link, arg, &html); html += ""; } @@ -3064,16 +3035,14 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, // replace all <@func> tags: "(<@func target=\"([^\"]*)\">)(.*)()" src = html; html = QString(); - static const QString funcTag("func"); - for (int i = 0, n = src.size(); i < n;) { + for (int i = 0, srcSize = src.size(); i < srcSize;) { if (src.at(i) == charLangle && src.at(i + 1) == charAt) { i += 2; - if (parseArg(src, funcTag, &i, n, &arg, &par1)) { - QString link = linkForNode( - marker->resolveTarget(par1.toString(), - myTree, - relative), - relative); + if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) { + const Node* n = marker->resolveTarget(par1.toString(), + myTree, + relative); + QString link = linkForNode(n, relative); addLink(link, arg, &html); par1 = QStringRef(); } @@ -3091,295 +3060,36 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, // replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)()" tags src = html; html = QString(); - static const QString typeTags[] = { "type", "headerfile", "func" }; - for (int i = 0, n = src.size(); i < n;) { - if (src.at(i) == charLangle && src.at(i + 1) == charAt) { + + for (int i=0, srcSize=src.size(); iresolveTarget(arg.toString(), myTree, relative); - QString link = linkForNode(n,relative); - addLink(link, arg, &html); - handled = true; - break; + if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) { + par1 = QStringRef(); + const Node* n = marker->resolveTarget(arg.toString(), myTree, relative); + if (HtmlGenerator::debugging_on) { + if (n) { + qDebug() << " " << n->name() << n->type() << n->subType(); + qDebug() << " " << relative->name() << relative->type() << relative->subType(); + } } + addLink(linkForNode(n,relative), arg, &html); + handled = true; } - if (!handled) { - html += charLangle; - html += charAt; - } - } - else { - html += src.at(i++); - } - } - - // replace all - // "<@comment>" -> ""; - // "<@preprocessor>" -> ""; - // "<@string>" -> ""; - // "<@char>" -> ""; - // "" -> "" - src = html; - html = QString(); - static const QString spanTags[] = { - "<@comment>", "", - "<@preprocessor>", "", - "<@string>", "", - "<@char>", "", - "", "", - "","", - "", "", - "", "" - // "<@char>", "", - // "", "", - // "<@func>", "", - // "", "", - // "<@id>", "", - // "", "", - // "<@keyword>", "", - // "", "", - // "<@number>", "", - // "", "", - // "<@op>", "", - // "", "", - // "<@param>", "", - // "", "", - // "<@string>", "", - // "", "", - }; - for (int i = 0, n = src.size(); i < n;) { - if (src.at(i) == charLangle) { - bool handled = false; - for (int k = 0; k != 8; ++k) { - const QString & tag = spanTags[2 * k]; - if (tag == QStringRef(&src, i, tag.length())) { - html += spanTags[2 * k + 1]; - i += tag.length(); - handled = true; - break; - } + else if (parseArg(src, headerTag, &i, srcSize, &arg, &par1)) { + par1 = QStringRef(); + const Node* n = marker->resolveTarget(arg.toString(), myTree, relative); + addLink(linkForNode(n,relative), arg, &html); + handled = true; } - if (!handled) { - ++i; - if (src.at(i) == charAt || - (src.at(i) == QLatin1Char('/') && src.at(i + 1) == charAt)) { - // drop 'our' unknown tags (the ones still containing '@') - while (i < n && src.at(i) != QLatin1Char('>')) - ++i; - ++i; - } - else { - // retain all others - html += charLangle; - } + else if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) { + par1 = QStringRef(); + const Node* n = marker->resolveTarget(arg.toString(), myTree, relative); + addLink(linkForNode(n,relative), arg, &html); + handled = true; } - } - else { - html += src.at(i); - ++i; - } - } - - return html; -} -#else -void HtmlGenerator::generateSectionList(const Section& section, - const Node *relative, - CodeMarker *marker, - CodeMarker::SynopsisStyle style) -{ - if (!section.members.isEmpty()) { - bool twoColumn = false; - if (style == CodeMarker::SeparateList) { - twoColumn = (section.members.count() >= 16); - } - else if (section.members.first()->type() == Node::Property) { - twoColumn = (section.members.count() >= 5); - } - if (twoColumn) - out() << "\n"; - if (++numTableRows % 2 == 1) - out() << ""; - else - out() << ""; - -// << "\n
    "; - out() << "
      \n"; - - int i = 0; - NodeList::ConstIterator m = section.members.begin(); - while (m != section.members.end()) { - if ((*m)->access() == Node::Private) { - ++m; - continue; - } - - if (twoColumn && i == (int) (section.members.count() + 1) / 2) - out() << "
      \n"; - - out() << "
    • "; - if (style == CodeMarker::Accessors) - out() << ""; - generateSynopsis(*m, relative, marker, style); - if (style == CodeMarker::Accessors) - out() << ""; - out() << "
    • \n"; - i++; - ++m; - } - out() << "
    \n"; - if (twoColumn) - out() << "
    \n"; - } - - if (style == CodeMarker::Summary && !section.inherited.isEmpty()) { - out() << "
      \n"; - generateSectionInheritedList(section, relative, marker); - out() << "
    \n"; - } -} - -void HtmlGenerator::generateSectionInheritedList(const Section& section, - const Node *relative, - CodeMarker *marker) -{ - QList >::ConstIterator p = section.inherited.begin(); - while (p != section.inherited.end()) { - out() << "
  • "; - out() << (*p).second << " "; - if ((*p).second == 1) { - out() << section.singularMember; - } else { - out() << section.pluralMember; - } - out() << " inherited from " - << protectEnc(marker->plainFullName((*p).first, relative)) - << "
  • \n"; - ++p; - } -} - -void HtmlGenerator::generateSynopsis(const Node *node, - const Node *relative, - CodeMarker *marker, - CodeMarker::SynopsisStyle style) -{ - QString marked = marker->markedUpSynopsis(node, relative, style); - QRegExp templateTag("(<[^@>]*>)"); - if (marked.indexOf(templateTag) != -1) { - QString contents = protectEnc(marked.mid(templateTag.pos(1), - templateTag.cap(1).length())); - marked.replace(templateTag.pos(1), templateTag.cap(1).length(), - contents); - } - marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])"), "\\1\\2"); - marked.replace("<@param>", ""); - marked.replace("", ""); - - if (style == CodeMarker::Summary) - marked.replace("@name>", "b>"); - - if (style == CodeMarker::SeparateList) { - QRegExp extraRegExp("<@extra>.*"); - extraRegExp.setMinimal(true); - marked.replace(extraRegExp, ""); - } else { - marked.replace("<@extra>", ""); - marked.replace("", ""); - } - - if (style != CodeMarker::Detailed) { - marked.replace("<@type>", ""); - marked.replace("", ""); - } - out() << highlightedCode(marked, marker, relative); -} - -QString HtmlGenerator::highlightedCode(const QString& markedCode, - CodeMarker *marker, - const Node *relative) -{ - QString src = markedCode; - QString html; - QStringRef arg; - QStringRef par1; - - const QChar charLangle = '<'; - const QChar charAt = '@'; - - // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*()" - static const QString linkTag("link"); - for (int i = 0, n = src.size(); i < n;) { - if (src.at(i) == charLangle && src.at(i + 1) == charAt) { - i += 2; - if (parseArg(src, linkTag, &i, n, &arg, &par1)) { - const Node* node = CodeMarker::nodeForString(par1.toString()); - QString link = linkForNode(node, relative); - addLink(link, arg, &html); - } - else { - html += charLangle; - html += charAt; - } - } - else { - html += src.at(i++); - } - } - - if (slow) { - // is this block ever used at all? - // replace all <@func> tags: "(<@func target=\"([^\"]*)\">)(.*)()" - src = html; - html = QString(); - static const QString funcTag("func"); - for (int i = 0, n = src.size(); i < n;) { - if (src.at(i) == charLangle && src.at(i + 1) == charAt) { - i += 2; - if (parseArg(src, funcTag, &i, n, &arg, &par1)) { - QString link = linkForNode( - marker->resolveTarget(par1.toString(), - myTree, - relative), - relative); - addLink(link, arg, &html); - par1 = QStringRef(); - } - else { - html += charLangle; - html += charAt; - } - } - else { - html += src.at(i++); - } - } - } - - // replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)()" tags - src = html; - html = QString(); - static const QString typeTags[] = { "type", "headerfile", "func" }; - for (int i = 0, n = src.size(); i < n;) { - if (src.at(i) == charLangle && src.at(i + 1) == charAt) { - i += 2; - bool handled = false; - for (int k = 0; k != 3; ++k) { - if (parseArg(src, typeTags[k], &i, n, &arg, &par1)) { - par1 = QStringRef(); - QString link = linkForNode( - marker->resolveTarget(arg.toString(), myTree, relative), - relative); - addLink(link, arg, &html); - handled = true; - break; - } - } if (!handled) { html += charLangle; html += charAt; @@ -3407,22 +3117,6 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, "","", "", "", "", "" - // "<@char>", "", - // "", "", - // "<@func>", "", - // "", "", - // "<@id>", "", - // "", "", - // "<@keyword>", "", - // "", "", - // "<@number>", "", - // "", "", - // "<@op>", "", - // "", "", - // "<@param>", "", - // "", "", - // "<@string>", "", - // "", "", }; for (int i = 0, n = src.size(); i < n;) { if (src.at(i) == charLangle) { @@ -3459,7 +3153,6 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, return html; } -#endif void HtmlGenerator::generateLink(const Atom* atom, const Node* /* relative */, diff --git a/tools/qdoc3/htmlgenerator.h b/tools/qdoc3/htmlgenerator.h index aad5021..80341de 100644 --- a/tools/qdoc3/htmlgenerator.h +++ b/tools/qdoc3/htmlgenerator.h @@ -46,8 +46,6 @@ #ifndef HTMLGENERATOR_H #define HTMLGENERATOR_H -#define QDOC_NAME_ALIGNMENT - #include #include #include @@ -198,7 +196,7 @@ class HtmlGenerator : public PageGenerator void generateQmlInstantiates(const QmlClassNode* qcn, CodeMarker* marker); void generateInstantiatedBy(const ClassNode* cn, CodeMarker* marker); #endif -#ifdef QDOC_NAME_ALIGNMENT + void generateSection(const NodeList& nl, const Node *relative, CodeMarker *marker, @@ -207,28 +205,15 @@ class HtmlGenerator : public PageGenerator const Node *relative, CodeMarker *marker, CodeMarker::SynopsisStyle style, - bool nameAlignment = false); - void generateSectionInheritedList(const Section& section, - const Node *relative, - CodeMarker *marker, - bool nameAlignment = false); - QString highlightedCode(const QString& markedCode, - CodeMarker *marker, - const Node *relative, - CodeMarker::SynopsisStyle style = CodeMarker::Accessors, - bool nameAlignment = false); -#else - void generateSynopsis(const Node *node, - const Node *relative, - CodeMarker *marker, - CodeMarker::SynopsisStyle style); + bool alignNames = false); void generateSectionInheritedList(const Section& section, const Node *relative, CodeMarker *marker); QString highlightedCode(const QString& markedCode, CodeMarker *marker, - const Node *relative); -#endif + const Node *relative, + bool alignNames = false); + void generateFullName(const Node *apparentNode, const Node *relative, CodeMarker *marker, diff --git a/tools/qdoc3/tree.cpp b/tools/qdoc3/tree.cpp index d3de46c..70b998f 100644 --- a/tools/qdoc3/tree.cpp +++ b/tools/qdoc3/tree.cpp @@ -134,15 +134,16 @@ Node *Tree::findNode(const QStringList &path, Node *relative, int findFlags) /*! */ -const Node *Tree::findNode(const QStringList &path, - const Node *relative, +const Node* Tree::findNode(const QStringList &path, + const Node* start, int findFlags) const { - if (!relative) - relative = root(); + const Node* current = start; + if (!current) + current = root(); do { - const Node *node = relative; + const Node *node = current; int i; for (i = 0; i < path.size(); ++i) { @@ -171,10 +172,10 @@ const Node *Tree::findNode(const QStringList &path, if (node && i == path.size() && (!(findFlags & NonFunction) || node->type() != Node::Function || ((FunctionNode *)node)->metaness() == FunctionNode::MacroWithoutParams)) - if (node->subType() != Node::QmlPropertyGroup) + if ((node != start) && (node->subType() != Node::QmlPropertyGroup)) return node; - relative = relative->parent(); - } while (relative); + current = current->parent(); + } while (current); return 0; } -- cgit v0.12 From 4a1d231cd5e0b756a919642b9faf35146a190b95 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 6 Jul 2010 13:33:47 +0200 Subject: Support QSslSocket::systemCaCertificates() on Symbian Implemented access to the unified certificate store on Symbian with Shane and Peter's help. Task-number: QTBUG-11399 Reviewed-by: Shane Kearns Reviewed-by: Peter Hartmann --- src/network/network.pro | 2 +- src/network/ssl/qsslsocket_openssl.cpp | 134 +++++++++++++++++++++++++++++++++ src/network/ssl/qsslsocket_openssl_p.h | 64 ++++++++++++++++ 3 files changed, 199 insertions(+), 1 deletion(-) diff --git a/src/network/network.pro b/src/network/network.pro index 8582d8a..7ed7d3a 100644 --- a/src/network/network.pro +++ b/src/network/network.pro @@ -27,5 +27,5 @@ QMAKE_LIBS += $$QMAKE_LIBS_NETWORK symbian { TARGET.UID3=0x2001B2DE - LIBS += -lesock -linsock + LIBS += -lesock -linsock -lcertstore -lefsrv -lctframework } diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index cad8ca7..d7088ee 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -68,6 +68,8 @@ PtrCertOpenSystemStoreW QSslSocketPrivate::ptrCertOpenSystemStoreW = 0; PtrCertFindCertificateInStore QSslSocketPrivate::ptrCertFindCertificateInStore = 0; PtrCertCloseStore QSslSocketPrivate::ptrCertCloseStore = 0; +#elif defined(Q_OS_SYMBIAN) +#include #endif QT_BEGIN_NAMESPACE @@ -565,6 +567,119 @@ void QSslSocketPrivate::resetDefaultCiphers() setDefaultCiphers(ciphers); } +#if defined(Q_OS_SYMBIAN) + +QCertificateRetriever::QCertificateRetriever(QCertificateConsumer* parent) + : CActive(EPriorityStandard) + , certStore(0) + , certFilter(0) + , consumer(parent) + , currentCertificateIndex(0) + , certDescriptor(0, 0) +{ + CActiveScheduler::Add(this); + QT_TRAP_THROWING(certStore = CUnifiedCertStore::NewL(qt_s60GetRFs(), EFalse)); + QT_TRAP_THROWING(certFilter = CCertAttributeFilter::NewL()); + certFilter->SetFormat(EX509Certificate); +} + +QCertificateRetriever::~QCertificateRetriever() +{ + delete certFilter; + delete certStore; + Cancel(); +} + +void QCertificateRetriever::fetch() +{ + certStore->Initialize(iStatus); + state = Initializing; + SetActive(); +} + +void QCertificateRetriever::list() +{ + certStore->List(certs, *certFilter, iStatus); + state = Listing; + SetActive(); +} + +void QCertificateRetriever::retrieveNextCertificate() +{ + CCTCertInfo* cert = certs[currentCertificateIndex]; + currentCertificate.resize(cert->Size()); + certDescriptor.Set((TUint8*)currentCertificate.data(), 0, currentCertificate.size()); + certStore->Retrieve(*cert, certDescriptor, iStatus); + state = RetrievingCertificates; + SetActive(); +} + +void QCertificateRetriever::RunL() +{ + switch (state) { + case Initializing: + list(); + break; + case Listing: + currentCertificateIndex = 0; + retrieveNextCertificate(); + break; + case RetrievingCertificates: + consumer->addEncodedCertificate(currentCertificate); + currentCertificate = QByteArray(); + + currentCertificateIndex++; + + if (currentCertificateIndex < certs.Count()) + retrieveNextCertificate(); + else + consumer->finish(); + break; + } +} + +void QCertificateRetriever::DoCancel() +{ + switch (state) { + case Initializing: + certStore->CancelInitialize(); + break; + case Listing: + certStore->CancelList(); + break; + case RetrievingCertificates: + certStore->CancelRetrieve(); + break; + } +} + +QCertificateConsumer::QCertificateConsumer(QObject* parent) + : QObject(parent) + , retriever(0) +{ +} + +QCertificateConsumer::~QCertificateConsumer() +{ + delete retriever; +} + +void QCertificateConsumer::finish() +{ + delete retriever; + retriever = 0; + emit finished(); +} + +void QCertificateConsumer::start() +{ + retriever = new QCertificateRetriever(this); + Q_CHECK_PTR(retriever); + retriever->fetch(); +} + +#endif // defined(Q_OS_SYMBIAN) + QList QSslSocketPrivate::systemCaCertificates() { ensureInitialized(); @@ -638,7 +753,26 @@ QList QSslSocketPrivate::systemCaCertificates() systemCerts.append(QSslCertificate::fromPath(QLatin1String("/usr/lib/ssl/certs/*.pem"), QSsl::Pem, QRegExp::Wildcard)); // Gentoo, Mandrake systemCerts.append(QSslCertificate::fromPath(QLatin1String("/usr/share/ssl/*.pem"), QSsl::Pem, QRegExp::Wildcard)); // Centos, Redhat, SuSE systemCerts.append(QSslCertificate::fromPath(QLatin1String("/usr/local/ssl/*.pem"), QSsl::Pem, QRegExp::Wildcard)); // Normal OpenSSL Tarball +#elif defined(Q_OS_SYMBIAN) + QThread* certThread = new QThread; + + QCertificateConsumer *consumer = new QCertificateConsumer(); + consumer->moveToThread(certThread); + QObject::connect(certThread, SIGNAL(started()), consumer, SLOT(start())); + QObject::connect(consumer, SIGNAL(finished()), certThread, SLOT(quit()), Qt::DirectConnection); + + certThread->start(); + certThread->wait(); + foreach (const QByteArray &encodedCert, consumer->encodedCertificates()) { + QSslCertificate cert(encodedCert, QSsl::Der); + if (!cert.isNull()) + systemCerts.append(cert); + } + + delete consumer; + delete certThread; #endif + return systemCerts; } diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h index 3c08757..e41320d 100644 --- a/src/network/ssl/qsslsocket_openssl_p.h +++ b/src/network/ssl/qsslsocket_openssl_p.h @@ -118,6 +118,70 @@ public: static QList STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509); }; +#if defined(Q_OS_SYMBIAN) +#include // link against certstore.lib +#include // link against ctframework.lib + +class QCertificateRetriever; + +class QCertificateConsumer : public QObject +{ + Q_OBJECT +public: + QCertificateConsumer(QObject* parent = 0); + ~QCertificateConsumer(); + + void finish(); + + void addEncodedCertificate(const QByteArray& certificate) + { certificates.append(certificate); } + QList encodedCertificates() const { return certificates; } + +public slots: + void start(); + +signals: + void finished(); + +private: + QList certificates; + QCertificateRetriever *retriever; +}; + + +class QCertificateRetriever : public CActive +{ +public: + QCertificateRetriever(QCertificateConsumer* consumer); + ~QCertificateRetriever(); + + void fetch(); + +private: + virtual void RunL(); + virtual void DoCancel(); + + void list(); + void retrieveNextCertificate(); + + enum { + Initializing, + Listing, + RetrievingCertificates + } state; + + CUnifiedCertStore* certStore; + RMPointerArray certs; + CCertAttributeFilter* certFilter; + QCertificateConsumer* consumer; + int currentCertificateIndex; + QByteArray currentCertificate; + TPtr8 certDescriptor; +}; + +#endif + + QT_END_NAMESPACE #endif -- cgit v0.12 From 92b6ca830f279cfa9d37946f1fd72843b24e704b Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 2 Jul 2010 17:38:10 +0200 Subject: fix bogus return value from qprocess::execute() Task-number: QTBUG-230, QTBUG-5866 Reviewed-by: joerg --- src/corelib/io/qprocess.cpp | 14 ++++++++++---- tests/auto/qprocess/tst_qprocess.cpp | 9 +++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 8eba2b0..4c21a40 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -2082,14 +2082,19 @@ QProcess::ExitStatus QProcess::exitStatus() const process. On Windows, arguments that contain spaces are wrapped in quotes. + + If the process cannot be started, -2 is returned. If the process + crashes, -1 is returned. Otherwise, the process' exit code is + returned. */ int QProcess::execute(const QString &program, const QStringList &arguments) { QProcess process; process.setReadChannelMode(ForwardedChannels); process.start(program, arguments); - process.waitForFinished(-1); - return process.exitCode(); + if (!process.waitForFinished(-1)) + return -2; + return process.exitStatus() == QProcess::NormalExit ? process.exitCode() : -1; } /*! @@ -2104,8 +2109,9 @@ int QProcess::execute(const QString &program) QProcess process; process.setReadChannelMode(ForwardedChannels); process.start(program); - process.waitForFinished(-1); - return process.exitCode(); + if (!process.waitForFinished(-1)) + return -2; + return process.exitStatus() == QProcess::NormalExit ? process.exitCode() : -1; } /*! diff --git a/tests/auto/qprocess/tst_qprocess.cpp b/tests/auto/qprocess/tst_qprocess.cpp index 8dae9a0..8242d30 100644 --- a/tests/auto/qprocess/tst_qprocess.cpp +++ b/tests/auto/qprocess/tst_qprocess.cpp @@ -93,6 +93,7 @@ private slots: void getSetCheck(); void constructing(); void simpleStart(); + void execute(); void startDetached(); void crashTest(); void crashTest2(); @@ -284,6 +285,14 @@ void tst_QProcess::simpleStart() QCOMPARE(qVariantValue(spy.at(2).at(0)), QProcess::NotRunning); } //----------------------------------------------------------------------------- +void tst_QProcess::execute() +{ + QCOMPARE(QProcess::execute("testProcessNormal/testProcessNormal", + QStringList() << "arg1" << "arg2"), 0); + QCOMPARE(QProcess::execute("nonexistingexe"), -2); +} + +//----------------------------------------------------------------------------- void tst_QProcess::startDetached() { QProcess proc; -- cgit v0.12 From 4fe7291edcac2688f042a11ff5c23374c6c0375d Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 6 Jul 2010 13:56:38 +0200 Subject: add setNativeArguments() and nativeArguments() this function enables starting subprocesses which need command lines which cannot be constructed via the portable list-based api. such cases would be programs which need quoting rules which diverge from the msvc runtime. Reviewed-by: joerg Task-number: QTBUG-7620 (and various others which boil down to that) --- src/corelib/io/qprocess.cpp | 44 ++++++++++++++++++ src/corelib/io/qprocess.h | 5 +++ src/corelib/io/qprocess_p.h | 3 ++ src/corelib/io/qprocess_symbian.cpp | 17 ++++--- src/corelib/io/qprocess_win.cpp | 5 +++ src/s60installs/bwins/QtCoreu.def | 2 + src/s60installs/eabi/QtCoreu.def | 2 + tests/auto/qprocess/testProcessSpacesArgs/main.cpp | 7 ++- tests/auto/qprocess/tst_qprocess.cpp | 52 ++++++++++++++++++++++ 9 files changed, 129 insertions(+), 8 deletions(-) diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 4c21a40..9bc4063 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -1377,6 +1377,50 @@ void QProcess::setStandardOutputProcess(QProcess *destination) dto->stdinChannel.pipeFrom(dfrom); } +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + +/*! + \since 4.7 + + Returns the additional native command line arguments for the program. + + \note This function is available only on the Windows and Symbian + platforms. + + \sa setNativeArguments() +*/ +QString QProcess::nativeArguments() const +{ + Q_D(const QProcess); + return d->nativeArguments; +} + +/*! + \since 4.7 + \overload + + Sets additional native command line arguments for the program. + + On operating systems where the system API for passing command line + arguments to a subprocess natively uses a single string, one can + conceive command lines which cannot be passed via QProcess's portable + list-based API. In such cases this function must be used to set a + string which is \e appended to the string composed from the usual + argument list, with a delimiting space. + + \note This function is available only on the Windows and Symbian + platforms. + + \sa nativeArguments() +*/ +void QProcess::setNativeArguments(const QString &arguments) +{ + Q_D(QProcess); + d->nativeArguments = arguments; +} + +#endif + /*! If QProcess has been assigned a working directory, this function returns the working directory that the QProcess will enter before the program has diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h index f84b855..b07d742 100644 --- a/src/corelib/io/qprocess.h +++ b/src/corelib/io/qprocess.h @@ -148,6 +148,11 @@ public: void setStandardErrorFile(const QString &fileName, OpenMode mode = Truncate); void setStandardOutputProcess(QProcess *destination); +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + QString nativeArguments() const; + void setNativeArguments(const QString &arguments); +#endif + QString workingDirectory() const; void setWorkingDirectory(const QString &dir); diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index 60b7b5a..8b7e3ff 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -181,6 +181,9 @@ public: QString program; QStringList arguments; +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + QString nativeArguments; +#endif QProcessEnvironment environment; QRingBuffer outputReadBuffer; diff --git a/src/corelib/io/qprocess_symbian.cpp b/src/corelib/io/qprocess_symbian.cpp index 92212fe..af657b2 100644 --- a/src/corelib/io/qprocess_symbian.cpp +++ b/src/corelib/io/qprocess_symbian.cpp @@ -219,7 +219,8 @@ static bool qt_rprocess_running(RProcess *proc) return false; } -static void qt_create_symbian_commandline(const QStringList &arguments, QString &commandLine) +static void qt_create_symbian_commandline( + const QStringList &arguments, const QString &nativeArguments, QString &commandLine) { for (int i = 0; i < arguments.size(); ++i) { QString tmp = arguments.at(i); @@ -243,12 +244,14 @@ static void qt_create_symbian_commandline(const QStringList &arguments, QString } } - // Chop the extra trailing space if any arguments were appended - if (arguments.size()) + if (!nativeArguments.isEmpty()) + commandLine += nativeArguments; + else if (!commandLine.isEmpty()) // Chop the extra trailing space if any arguments were appended commandLine.chop(1); } -static TInt qt_create_symbian_process(RProcess **proc, const QString &programName, const QStringList &arguments) +static TInt qt_create_symbian_process(RProcess **proc, + const QString &programName, const QStringList &arguments, const QString &nativeArguments) { RProcess *newProc = NULL; newProc = new RProcess(); @@ -257,7 +260,7 @@ static TInt qt_create_symbian_process(RProcess **proc, const QString &programNam return KErrNoMemory; QString commandLine; - qt_create_symbian_commandline(arguments, commandLine); + qt_create_symbian_commandline(arguments, nativeArguments, commandLine); TPtrC program_ptr(reinterpret_cast(programName.constData())); TPtrC cmdline_ptr(reinterpret_cast(commandLine.constData())); @@ -794,7 +797,7 @@ void QProcessPrivate::startProcess() q, SLOT(_q_processDied())); } - TInt err = qt_create_symbian_process(&symbianProcess, program, arguments); + TInt err = qt_create_symbian_process(&symbianProcess, program, arguments, nativeArguments); if (err == KErrNone) { pid = symbianProcess->Id().Id(); @@ -1030,7 +1033,7 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a RProcess *newProc = NULL; - TInt err = qt_create_symbian_process(&newProc, program, arguments); + TInt err = qt_create_symbian_process(&newProc, program, arguments, QString()); if (err == KErrNone) { if (pid) diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index cb25a58..702349f 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -366,6 +366,11 @@ void QProcessPrivate::startProcess() if (environment.d.constData()) envlist = qt_create_environment(environment.d.constData()->hash); #endif + if (!nativeArguments.isEmpty()) { + if (!args.isEmpty()) + args += QLatin1Char(' '); + args += nativeArguments; + } #if defined QPROCESS_DEBUG qDebug("Creating process"); diff --git a/src/s60installs/bwins/QtCoreu.def b/src/s60installs/bwins/QtCoreu.def index 101c6a8..94be1bb 100644 --- a/src/s60installs/bwins/QtCoreu.def +++ b/src/s60installs/bwins/QtCoreu.def @@ -4482,4 +4482,6 @@ EXPORTS ?textDirection@QLocale@@QBE?AW4LayoutDirection@Qt@@XZ @ 4481 NONAME ; enum Qt::LayoutDirection QLocale::textDirection(void) const ?peek@QIODevicePrivate@@UAE_JPAD_J@Z @ 4482 NONAME ; long long QIODevicePrivate::peek(char *, long long) ?peek@QIODevicePrivate@@UAE?AVQByteArray@@_J@Z @ 4483 NONAME ; class QByteArray QIODevicePrivate::peek(long long) + ?nativeArguments@QProcess@@QBE?AVQString@@XZ @ 4484 NONAME ; class QString QProcess::nativeArguments(void) const + ?setNativeArguments@QProcess@@QAEXABVQString@@@Z @ 4485 NONAME ; void QProcess::setNativeArguments(class QString const &) diff --git a/src/s60installs/eabi/QtCoreu.def b/src/s60installs/eabi/QtCoreu.def index 7b9e777..46c4885 100644 --- a/src/s60installs/eabi/QtCoreu.def +++ b/src/s60installs/eabi/QtCoreu.def @@ -3709,4 +3709,6 @@ EXPORTS _ZNK7QString13isRightToLeftEv @ 3708 NONAME _ZN16QIODevicePrivate4peekEPcx @ 3709 NONAME _ZN16QIODevicePrivate4peekEx @ 3710 NONAME + _ZN8QProcess18setNativeArgumentsERK7QString @ 3711 NONAME + _ZNK8QProcess15nativeArgumentsEv @ 3712 NONAME diff --git a/tests/auto/qprocess/testProcessSpacesArgs/main.cpp b/tests/auto/qprocess/testProcessSpacesArgs/main.cpp index d842934..ae5d3ae 100644 --- a/tests/auto/qprocess/testProcessSpacesArgs/main.cpp +++ b/tests/auto/qprocess/testProcessSpacesArgs/main.cpp @@ -44,9 +44,14 @@ int main(int argc, char ** argv) { -#if defined(__SYMBIAN32__) +#if defined(__SYMBIAN32__) || defined(WINCE) || defined(_WIN32_WCE) +# if defined(__SYMBIAN32__) // Printing to stdout messes up the out.txt, so open a file and print there. FILE* file = fopen("c:\\logs\\qprocess_args_test.txt","w+"); +# else + // No pipes on this "OS" + FILE* file = fopen("\\temp\\qprocess_args_test.txt","w+"); +# endif for (int i = 0; i < argc; ++i) { if (i) fprintf(file, "|"); diff --git a/tests/auto/qprocess/tst_qprocess.cpp b/tests/auto/qprocess/tst_qprocess.cpp index 8242d30..fd310f4 100644 --- a/tests/auto/qprocess/tst_qprocess.cpp +++ b/tests/auto/qprocess/tst_qprocess.cpp @@ -132,6 +132,9 @@ private slots: void waitForBytesWrittenInABytesWrittenSlot(); void spaceArgsTest_data(); void spaceArgsTest(); +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + void nativeArguments(); +#endif void exitCodeTest(); void setEnvironment_data(); void setEnvironment(); @@ -1630,6 +1633,55 @@ void tst_QProcess::spaceArgsTest() process = 0; } +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + +//----------------------------------------------------------------------------- +void tst_QProcess::nativeArguments() +{ + QProcess proc; + + // This doesn't actually need special quoting, so it is pointless to use + // native arguments here, but that's not the point of this test. + proc.setNativeArguments("hello kitty, \"*\"!"); + + proc.start(QString::fromLatin1("testProcessSpacesArgs/nospace"), QStringList()); + +#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN) + QVERIFY(proc.waitForStarted(5000)); + QVERIFY(proc.waitForFinished(5000)); +#else + QVERIFY(proc.waitForStarted(10000)); + QVERIFY(proc.waitForFinished(10000)); +#endif + +#if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE) + // Symbian test outputs to a file, so check that +# ifdef Q_OS_SYMBIAN + FILE* file = fopen("c:\\logs\\qprocess_args_test.txt","r"); +# else + FILE* file = fopen("\\temp\\qprocess_args_test.txt","r"); +# endif + char buf[256]; + fgets(buf, 256, file); + fclose(file); + QStringList actual = QString::fromLatin1(buf).split("|"); +#else + QStringList actual = QString::fromLatin1(proc.readAll()).split("|"); +#endif + QVERIFY(!actual.isEmpty()); + // not interested in the program name, it might be different. + actual.removeFirst(); + QStringList expected; +#if defined(Q_OS_WINCE) + expected << "hello" << "kitty," << "\"*\"!"; // Weird, weird ... +#else + expected << "hello" << "kitty," << "*!"; +#endif + QCOMPARE(actual, expected); +} + +#endif + //----------------------------------------------------------------------------- void tst_QProcess::exitCodeTest() { -- cgit v0.12 From fa9c62460791c9b9add365fc9543ec0392f50cee Mon Sep 17 00:00:00 2001 From: Thomas Zander Date: Mon, 5 Jul 2010 17:05:04 +0200 Subject: Adapt the TapAndHold recognizer to non-touch too The QTapAndHoldGestureRecognizer now can trigger also on mouse and GraphicsSceneMouse events and all of them will cause the gesture start event to be sent after the touch interval timed out. Reviewed-by: Denis --- src/gui/kernel/qstandardgestures.cpp | 63 +++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp index 8a3e89e..62d8a53 100644 --- a/src/gui/kernel/qstandardgestures.cpp +++ b/src/gui/kernel/qstandardgestures.cpp @@ -45,6 +45,7 @@ #include "qevent.h" #include "qwidget.h" #include "qabstractscrollarea.h" +#include #include "qdebug.h" #ifndef QT_NO_GESTURES @@ -509,49 +510,65 @@ QTapAndHoldGestureRecognizer::recognize(QGesture *state, QObject *object, if (object == state && event->type() == QEvent::Timer) { q->killTimer(d->timerId); d->timerId = 0; - return QGestureRecognizer::Ignore | QGestureRecognizer::ConsumeEventHint; + return QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint; } const QTouchEvent *ev = static_cast(event); - - QGestureRecognizer::Result result = QGestureRecognizer::CancelGesture; + const QMouseEvent *me = static_cast(event); + const QGraphicsSceneMouseEvent *gsme = static_cast(event); enum { TimerInterval = 2000 }; enum { TapRadius = 40 }; switch (event->type()) { + case QEvent::GraphicsSceneMousePress: + d->position = gsme->screenPos(); + q->setHotSpot(d->position); + if (d->timerId) + q->killTimer(d->timerId); + d->timerId = q->startTimer(TimerInterval); + return QGestureRecognizer::MayBeGesture; // we don't show a sign of life until the timeout + case QEvent::MouseButtonPress: + d->position = me->globalPos(); + q->setHotSpot(d->position); + if (d->timerId) + q->killTimer(d->timerId); + d->timerId = q->startTimer(TimerInterval); + return QGestureRecognizer::MayBeGesture; // we don't show a sign of life until the timeout case QEvent::TouchBegin: - d->position = ev->touchPoints().at(0).pos(); + d->position = ev->touchPoints().at(0).startScreenPos(); + q->setHotSpot(d->position); if (d->timerId) q->killTimer(d->timerId); d->timerId = q->startTimer(TimerInterval); - q->setHotSpot(ev->touchPoints().at(0).startScreenPos()); - result = QGestureRecognizer::TriggerGesture; - break; + return QGestureRecognizer::MayBeGesture; // we don't show a sign of life until the timeout + case QEvent::GraphicsSceneMouseRelease: + case QEvent::MouseButtonRelease: case QEvent::TouchEnd: - if (d->timerId) - result = QGestureRecognizer::CancelGesture; - else - result = QGestureRecognizer::FinishGesture; - break; + return QGestureRecognizer::CancelGesture; // get out of the MayBeGesture state case QEvent::TouchUpdate: - if (q->state() != Qt::NoGesture && ev->touchPoints().size() == 1) { + if (d->timerId && ev->touchPoints().size() == 1) { QTouchEvent::TouchPoint p = ev->touchPoints().at(0); QPoint delta = p.pos().toPoint() - p.startPos().toPoint(); if (delta.manhattanLength() <= TapRadius) - result = QGestureRecognizer::TriggerGesture; + return QGestureRecognizer::MayBeGesture; } - break; - case QEvent::MouseButtonPress: - case QEvent::MouseMove: - case QEvent::MouseButtonRelease: - result = QGestureRecognizer::Ignore; - break; + return QGestureRecognizer::CancelGesture; + case QEvent::MouseMove: { + QPoint delta = me->globalPos() - d->position.toPoint(); + if (d->timerId && delta.manhattanLength() <= TapRadius) + return QGestureRecognizer::MayBeGesture; + return QGestureRecognizer::CancelGesture; + } + case QEvent::GraphicsSceneMouseMove: { + QPoint delta = gsme->screenPos() - d->position.toPoint(); + if (d->timerId && delta.manhattanLength() <= TapRadius) + return QGestureRecognizer::MayBeGesture; + return QGestureRecognizer::CancelGesture; + } default: - result = QGestureRecognizer::Ignore; - break; + return QGestureRecognizer::Ignore; } - return result; } void QTapAndHoldGestureRecognizer::reset(QGesture *state) -- cgit v0.12 From 2fa8b39c8a687550934e9668384f0bbe9f56f550 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 6 Jul 2010 19:08:45 +0200 Subject: fix autotest fixing QProcess::execute() revealed that this test has always been broken on windows. --- tests/auto/linguist/lrelease/tst_lrelease.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/auto/linguist/lrelease/tst_lrelease.cpp b/tests/auto/linguist/lrelease/tst_lrelease.cpp index fdb384e..3b2c2d2 100644 --- a/tests/auto/linguist/lrelease/tst_lrelease.cpp +++ b/tests/auto/linguist/lrelease/tst_lrelease.cpp @@ -171,7 +171,12 @@ void tst_lrelease::mixedcodecs() { QVERIFY(!QProcess::execute(binDir + "/lrelease testdata/mixedcodecs-ts11.ts")); QVERIFY(!QProcess::execute(binDir + "/lrelease testdata/mixedcodecs-ts20.ts")); +#ifdef Q_OS_WIN + QVERIFY(!QProcess::execute("fc /b testdata\\mixedcodecs-ts11.qm testdata\\mixedcodecs-ts20.qm")); +#else QVERIFY(!QProcess::execute("cmp testdata/mixedcodecs-ts11.qm testdata/mixedcodecs-ts20.qm")); +#endif + QTranslator translator; QVERIFY(translator.load("testdata/mixedcodecs-ts11.qm")); qApp->installTranslator(&translator); -- cgit v0.12 From 28651cfc0ce2954c0b6c0e5d3587e4d8b001c1de Mon Sep 17 00:00:00 2001 From: Jason Barron Date: Fri, 2 Jul 2010 16:16:59 +0200 Subject: Fix crash when handleCommand() called before softkeys are updated Softkeys are updated via a compressable event that is posted via the event loop. Since these events are not delivered immediately, there is a chance that a call to handleCommand() could happen before the softkeys have been updated which can lead to a crash if the previous QAction's have been deleted already since the data structure used by QSoftKeyManager is outdated. The likeliness of this is increased by the fact that S60 commands are normally sent from the WSERV active object which has a higher priority than the active object used by Qt's event loop which means commands will preempt the event loop. The fix is to introduce a flag that keeps track of pending update requests and if a command is received while there are outstanding requests, force the softkeys to be updated before handling the command. Task-number: QT-3571 Reviewed-by: axis --- src/gui/kernel/qsoftkeymanager.cpp | 5 +++++ src/gui/kernel/qsoftkeymanager_common_p.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qsoftkeymanager.cpp b/src/gui/kernel/qsoftkeymanager.cpp index 04e4685..54e6317 100644 --- a/src/gui/kernel/qsoftkeymanager.cpp +++ b/src/gui/kernel/qsoftkeymanager.cpp @@ -162,6 +162,7 @@ void QSoftKeyManager::sendKeyEvent() void QSoftKeyManager::updateSoftKeys() { + QSoftKeyManager::instance()->d_func()->pendingUpdate = true; QEvent *event = new QEvent(QEvent::UpdateSoftKeys); QApplication::postEvent(QSoftKeyManager::instance(), event); } @@ -250,6 +251,7 @@ bool QSoftKeyManager::handleUpdateSoftKeys() } d->updateSoftKeys_sys(); + d->pendingUpdate = false; return true; } @@ -275,6 +277,9 @@ bool QSoftKeyManager::event(QEvent *e) #ifdef Q_WS_S60 bool QSoftKeyManager::handleCommand(int command) { + if (QSoftKeyManager::instance()->d_func()->pendingUpdate) + (void)QSoftKeyManager::instance()->handleUpdateSoftKeys(); + return static_cast(QSoftKeyManager::instance()->d_func())->handleCommand(command); } #endif diff --git a/src/gui/kernel/qsoftkeymanager_common_p.h b/src/gui/kernel/qsoftkeymanager_common_p.h index 04ddf7d..1b364d4 100644 --- a/src/gui/kernel/qsoftkeymanager_common_p.h +++ b/src/gui/kernel/qsoftkeymanager_common_p.h @@ -71,7 +71,7 @@ protected: QHash keyedActions; QMultiHash requestedSoftKeyActions; QWidget *initialSoftKeySource; - + bool pendingUpdate; }; QT_END_NAMESPACE -- cgit v0.12 From 4e915e3942c1523ffdda01e36c019f842062b794 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 7 Jul 2010 11:04:33 +0200 Subject: Fix text drawing into alpha pixmap with opengl engine The merge 03dc74984749adf5b11482bf871a47086217845c mistakenly merged the glyphMargin() (which had been removed in 4.7 because QGLTextureGlyphCache now inherits from the image glyph cache) with the glyphPadding() which had been introduced in separate commits in both branches (probably backported.) This broke text drawing into a pixmap with an alpha with the GL engine, because we'd assume a margin of 1, but the alphaMapForGlyph() function doesn't support margins. Task-number: QTBUG-11987 Reviewed-by: Gunnar --- src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp | 5 ----- src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h | 1 - 2 files changed, 6 deletions(-) diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp index 5371c5e..410cf21 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp @@ -276,11 +276,6 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph) } } -int QGLTextureGlyphCache::glyphMargin() const -{ - return 1; -} - int QGLTextureGlyphCache::glyphPadding() const { return 1; diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h index 84e9021..6bcd655 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h @@ -72,7 +72,6 @@ public: virtual void createTextureData(int width, int height); virtual void resizeTextureData(int width, int height); virtual void fillTexture(const Coord &c, glyph_t glyph); - virtual int glyphMargin() const; virtual int glyphPadding() const; inline GLuint texture() const { return m_texture; } -- cgit v0.12 From 2769d4b72675e62c441fa181609adca25922715a Mon Sep 17 00:00:00 2001 From: John Brooks Date: Mon, 5 Jul 2010 21:17:48 +0200 Subject: Move logic for building SIMD extensions to gui.pro Enables SIMD files to be built outside of painting.pri by appending files to SSE_SOURCES etc. Merge-request: 725 Reviewed-by: Benjamin Poulain --- src/gui/gui.pro | 126 ++++++++++++++++++++++++++++++++++ src/gui/painting/painting.pri | 152 ++---------------------------------------- 2 files changed, 133 insertions(+), 145 deletions(-) diff --git a/src/gui/gui.pro b/src/gui/gui.pro index dede9d0..41f1904 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -77,3 +77,129 @@ symbian { DEPLOYMENT = partial_upgrade $$DEPLOYMENT } +contains(QMAKE_MAC_XARCH, no) { + DEFINES += QT_NO_MAC_XARCH +} else { + mmx:DEFINES += QT_HAVE_MMX + 3dnow:DEFINES += QT_HAVE_3DNOW + sse:DEFINES += QT_HAVE_SSE QT_HAVE_MMXEXT + sse2:DEFINES += QT_HAVE_SSE2 + iwmmxt:DEFINES += QT_HAVE_IWMMXT + + win32-g++*|!win32:!*-icc* { + mmx { + mmx_compiler.commands = $$QMAKE_CXX -c -Winline + + mac { + mmx_compiler.commands += -Xarch_i386 -mmmx + mmx_compiler.commands += -Xarch_x86_64 -mmmx + } else { + mmx_compiler.commands += -mmmx + } + + mmx_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} + mmx_compiler.dependency_type = TYPE_C + mmx_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} + mmx_compiler.input = MMX_SOURCES + mmx_compiler.variable_out = OBJECTS + mmx_compiler.name = compiling[mmx] ${QMAKE_FILE_IN} + silent:mmx_compiler.commands = @echo compiling[mmx] ${QMAKE_FILE_IN} && $$mmx_compiler.commands + QMAKE_EXTRA_COMPILERS += mmx_compiler + } + 3dnow { + mmx3dnow_compiler.commands = $$QMAKE_CXX -c -Winline + + mac { + mmx3dnow_compiler.commands += -Xarch_i386 -m3dnow -Xarch_i386 -mmmx + mmx3dnow_compiler.commands += -Xarch_x86_64 -m3dnow -Xarch_x86_64 -mmmx + } else { + mmx3dnow_compiler.commands += -m3dnow -mmmx + } + + mmx3dnow_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} + mmx3dnow_compiler.dependency_type = TYPE_C + mmx3dnow_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} + mmx3dnow_compiler.input = MMX3DNOW_SOURCES + mmx3dnow_compiler.variable_out = OBJECTS + mmx3dnow_compiler.name = compiling[mmx3dnow] ${QMAKE_FILE_IN} + silent:mmx3dnow_compiler.commands = @echo compiling[mmx3dnow] ${QMAKE_FILE_IN} && $$mmx3dnow_compiler.commands + QMAKE_EXTRA_COMPILERS += mmx3dnow_compiler + sse { + sse3dnow_compiler.commands = $$QMAKE_CXX -c -Winline + + mac { + sse3dnow_compiler.commands += -Xarch_i386 -m3dnow -Xarch_i386 -msse + sse3dnow_compiler.commands += -Xarch_x86_64 -m3dnow -Xarch_x86_64 -msse + } else { + sse3dnow_compiler.commands += -m3dnow -msse + } + + sse3dnow_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} + sse3dnow_compiler.dependency_type = TYPE_C + sse3dnow_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} + sse3dnow_compiler.input = SSE3DNOW_SOURCES + sse3dnow_compiler.variable_out = OBJECTS + sse3dnow_compiler.name = compiling[sse3dnow] ${QMAKE_FILE_IN} + silent:sse3dnow_compiler.commands = @echo compiling[sse3dnow] ${QMAKE_FILE_IN} && $$sse3dnow_compiler.commands + QMAKE_EXTRA_COMPILERS += sse3dnow_compiler + } + } + sse { + sse_compiler.commands = $$QMAKE_CXX -c -Winline + + mac { + sse_compiler.commands += -Xarch_i386 -msse + sse_compiler.commands += -Xarch_x86_64 -msse + } else { + sse_compiler.commands += -msse + } + + sse_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} + sse_compiler.dependency_type = TYPE_C + sse_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} + sse_compiler.input = SSE_SOURCES + sse_compiler.variable_out = OBJECTS + sse_compiler.name = compiling[sse] ${QMAKE_FILE_IN} + silent:sse_compiler.commands = @echo compiling[sse] ${QMAKE_FILE_IN} && $$sse_compiler.commands + QMAKE_EXTRA_COMPILERS += sse_compiler + } + sse2 { + sse2_compiler.commands = $$QMAKE_CXX -c -Winline + + mac { + sse2_compiler.commands += -Xarch_i386 -msse2 + sse2_compiler.commands += -Xarch_x86_64 -msse2 + } else { + sse2_compiler.commands += -msse2 + } + + sse2_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} + sse2_compiler.dependency_type = TYPE_C + sse2_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} + sse2_compiler.input = SSE2_SOURCES + sse2_compiler.variable_out = OBJECTS + sse2_compiler.name = compiling[sse2] ${QMAKE_FILE_IN} + silent:sse2_compiler.commands = @echo compiling[sse2] ${QMAKE_FILE_IN} && $$sse2_compiler.commands + QMAKE_EXTRA_COMPILERS += sse2_compiler + } + iwmmxt { + iwmmxt_compiler.commands = $$QMAKE_CXX -c -Winline + iwmmxt_compiler.commands += -mcpu=iwmmxt + iwmmxt_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} + iwmmxt_compiler.dependency_type = TYPE_C + iwmmxt_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} + iwmmxt_compiler.input = IWMMXT_SOURCES + iwmmxt_compiler.variable_out = OBJECTS + iwmmxt_compiler.name = compiling[iwmmxt] ${QMAKE_FILE_IN} + silent:iwmmxt_compiler.commands = @echo compiling[iwmmxt] ${QMAKE_FILE_IN} && $$iwmmxt_compiler.commands + QMAKE_EXTRA_COMPILERS += iwmmxt_compiler + } + } else { + mmx: SOURCES += $$MMX_SOURCES + 3dnow: SOURCES += $$MMX3DNOW_SOURCES + 3dnow:sse: SOURCES += $$SSE3DNOW_SOURCES + sse: SOURCES += $$SSE_SOURCES + sse2: SOURCES += $$SSE2_SOURCES + iwmmxt: SOURCES += $$IWMMXT_SOURCES + } +} diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 07aabc9..c207c9d 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -202,154 +202,16 @@ x11|embedded { DEFINES += QT_NO_CUPS QT_NO_LPR } -contains(QMAKE_MAC_XARCH, no) { - DEFINES += QT_NO_MAC_XARCH -} else:if(mmx|3dnow|sse|sse2|iwmmxt) { +if(mmx|3dnow|sse|sse2|iwmmxt) { HEADERS += painting/qdrawhelper_x86_p.h \ painting/qdrawhelper_mmx_p.h \ painting/qdrawhelper_sse_p.h - mmx { - DEFINES += QT_HAVE_MMX - MMX_SOURCES += painting/qdrawhelper_mmx.cpp - } - 3dnow { - DEFINES += QT_HAVE_3DNOW - MMX3DNOW_SOURCES += painting/qdrawhelper_mmx3dnow.cpp - sse { - SSE3DNOW_SOURCES += painting/qdrawhelper_sse3dnow.cpp - } - } - sse { - DEFINES += QT_HAVE_SSE - SSE_SOURCES += painting/qdrawhelper_sse.cpp - - DEFINES += QT_HAVE_MMXEXT - } - sse2 { - DEFINES += QT_HAVE_SSE2 - SSE2_SOURCES += painting/qdrawhelper_sse2.cpp - } - iwmmxt { - DEFINES += QT_HAVE_IWMMXT - IWMMXT_SOURCES += painting/qdrawhelper_iwmmxt.cpp - } - - win32-g++*|!win32:!*-icc* { - mmx { - mmx_compiler.commands = $$QMAKE_CXX -c -Winline - - mac { - mmx_compiler.commands += -Xarch_i386 -mmmx - mmx_compiler.commands += -Xarch_x86_64 -mmmx - } else { - mmx_compiler.commands += -mmmx - } - - mmx_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} - mmx_compiler.dependency_type = TYPE_C - mmx_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} - mmx_compiler.input = MMX_SOURCES - mmx_compiler.variable_out = OBJECTS - mmx_compiler.name = compiling[mmx] ${QMAKE_FILE_IN} - silent:mmx_compiler.commands = @echo compiling[mmx] ${QMAKE_FILE_IN} && $$mmx_compiler.commands - QMAKE_EXTRA_COMPILERS += mmx_compiler - } - 3dnow { - mmx3dnow_compiler.commands = $$QMAKE_CXX -c -Winline - - mac { - mmx3dnow_compiler.commands += -Xarch_i386 -m3dnow -Xarch_i386 -mmmx - mmx3dnow_compiler.commands += -Xarch_x86_64 -m3dnow -Xarch_x86_64 -mmmx - } else { - mmx3dnow_compiler.commands += -m3dnow -mmmx - } - - mmx3dnow_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} - mmx3dnow_compiler.dependency_type = TYPE_C - mmx3dnow_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} - mmx3dnow_compiler.input = MMX3DNOW_SOURCES - mmx3dnow_compiler.variable_out = OBJECTS - mmx3dnow_compiler.name = compiling[mmx3dnow] ${QMAKE_FILE_IN} - silent:mmx3dnow_compiler.commands = @echo compiling[mmx3dnow] ${QMAKE_FILE_IN} && $$mmx3dnow_compiler.commands - QMAKE_EXTRA_COMPILERS += mmx3dnow_compiler - sse { - sse3dnow_compiler.commands = $$QMAKE_CXX -c -Winline - - mac { - sse3dnow_compiler.commands += -Xarch_i386 -m3dnow -Xarch_i386 -msse - sse3dnow_compiler.commands += -Xarch_x86_64 -m3dnow -Xarch_x86_64 -msse - } else { - sse3dnow_compiler.commands += -m3dnow -msse - } - - sse3dnow_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} - sse3dnow_compiler.dependency_type = TYPE_C - sse3dnow_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} - sse3dnow_compiler.input = SSE3DNOW_SOURCES - sse3dnow_compiler.variable_out = OBJECTS - sse3dnow_compiler.name = compiling[sse3dnow] ${QMAKE_FILE_IN} - silent:sse3dnow_compiler.commands = @echo compiling[sse3dnow] ${QMAKE_FILE_IN} && $$sse3dnow_compiler.commands - QMAKE_EXTRA_COMPILERS += sse3dnow_compiler - } - } - sse { - sse_compiler.commands = $$QMAKE_CXX -c -Winline - - mac { - sse_compiler.commands += -Xarch_i386 -msse - sse_compiler.commands += -Xarch_x86_64 -msse - } else { - sse_compiler.commands += -msse - } - - sse_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} - sse_compiler.dependency_type = TYPE_C - sse_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} - sse_compiler.input = SSE_SOURCES - sse_compiler.variable_out = OBJECTS - sse_compiler.name = compiling[sse] ${QMAKE_FILE_IN} - silent:sse_compiler.commands = @echo compiling[sse] ${QMAKE_FILE_IN} && $$sse_compiler.commands - QMAKE_EXTRA_COMPILERS += sse_compiler - } - sse2 { - sse2_compiler.commands = $$QMAKE_CXX -c -Winline - - mac { - sse2_compiler.commands += -Xarch_i386 -msse2 - sse2_compiler.commands += -Xarch_x86_64 -msse2 - } else { - sse2_compiler.commands += -msse2 - } - - sse2_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} - sse2_compiler.dependency_type = TYPE_C - sse2_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} - sse2_compiler.input = SSE2_SOURCES - sse2_compiler.variable_out = OBJECTS - sse2_compiler.name = compiling[sse2] ${QMAKE_FILE_IN} - silent:sse2_compiler.commands = @echo compiling[sse2] ${QMAKE_FILE_IN} && $$sse2_compiler.commands - QMAKE_EXTRA_COMPILERS += sse2_compiler - } - iwmmxt { - iwmmxt_compiler.commands = $$QMAKE_CXX -c -Winline - iwmmxt_compiler.commands += -mcpu=iwmmxt - iwmmxt_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} - iwmmxt_compiler.dependency_type = TYPE_C - iwmmxt_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} - iwmmxt_compiler.input = IWMMXT_SOURCES - iwmmxt_compiler.variable_out = OBJECTS - iwmmxt_compiler.name = compiling[iwmmxt] ${QMAKE_FILE_IN} - silent:iwmmxt_compiler.commands = @echo compiling[iwmmxt] ${QMAKE_FILE_IN} && $$iwmmxt_compiler.commands - QMAKE_EXTRA_COMPILERS += iwmmxt_compiler - } - } else { - mmx: SOURCES += $$MMX_SOURCES - 3dnow: SOURCES += $$MMX3DNOW_SOURCES - 3dnow:sse: SOURCES += $$SSE3DNOW_SOURCES - sse: SOURCES += $$SSE_SOURCES - sse2: SOURCES += $$SSE2_SOURCES - iwmmxt: SOURCES += $$IWMMXT_SOURCES - } + MMX_SOURCES += painting/qdrawhelper_mmx.cpp + MMX3DNOW_SOURCES += painting/qdrawhelper_mmx3dnow.cpp + SSE3DNOW_SOURCES += painting/qdrawhelper_sse3dnow.cpp + SSE_SOURCES += painting/qdrawhelper_sse.cpp + SSE2_SOURCES += painting/qdrawhelper_sse2.cpp + IWMMXT_SOURCES += painting/qdrawhelper_iwmmxt.cpp } x11 { -- cgit v0.12 From 93bcbe213e947843184a75f4b237c8dff45ca866 Mon Sep 17 00:00:00 2001 From: John Brooks Date: Mon, 5 Jul 2010 21:17:49 +0200 Subject: Moved primitive SSE2 painting utilities to qdrawingprimitive_sse2_p.h Merge-request: 725 Reviewed-by: Benjamin Poulain --- src/gui/painting/painting.pri | 3 +- src/gui/painting/qdrawhelper_sse2.cpp | 156 -------------------- src/gui/painting/qdrawingprimitive_sse2_p.h | 216 ++++++++++++++++++++++++++++ 3 files changed, 218 insertions(+), 157 deletions(-) create mode 100644 src/gui/painting/qdrawingprimitive_sse2_p.h diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index c207c9d..4023f65 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -205,7 +205,8 @@ x11|embedded { if(mmx|3dnow|sse|sse2|iwmmxt) { HEADERS += painting/qdrawhelper_x86_p.h \ painting/qdrawhelper_mmx_p.h \ - painting/qdrawhelper_sse_p.h + painting/qdrawhelper_sse_p.h \ + painting/qdrawingprimitive_sse2_p.h MMX_SOURCES += painting/qdrawhelper_mmx.cpp MMX3DNOW_SOURCES += painting/qdrawhelper_mmx3dnow.cpp SSE3DNOW_SOURCES += painting/qdrawhelper_sse3dnow.cpp diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp index 6cd8688..ae16fed 100644 --- a/src/gui/painting/qdrawhelper_sse2.cpp +++ b/src/gui/painting/qdrawhelper_sse2.cpp @@ -57,162 +57,6 @@ QT_BEGIN_NAMESPACE -/* - * Multiply the components of pixelVector by alphaChannel - * Each 32bits components of alphaChannel must be in the form 0x00AA00AA - * colorMask must have 0x00ff00ff on each 32 bits component - * half must have the value 128 (0x80) for each 32 bits compnent - */ -#define BYTE_MUL_SSE2(result, pixelVector, alphaChannel, colorMask, half) \ -{ \ - /* 1. separate the colors in 2 vectors so each color is on 16 bits \ - (in order to be multiplied by the alpha \ - each 32 bit of dstVectorAG are in the form 0x00AA00GG \ - each 32 bit of dstVectorRB are in the form 0x00RR00BB */\ - __m128i pixelVectorAG = _mm_srli_epi16(pixelVector, 8); \ - __m128i pixelVectorRB = _mm_and_si128(pixelVector, colorMask); \ - \ - /* 2. multiply the vectors by the alpha channel */\ - pixelVectorAG = _mm_mullo_epi16(pixelVectorAG, alphaChannel); \ - pixelVectorRB = _mm_mullo_epi16(pixelVectorRB, alphaChannel); \ - \ - /* 3. devide by 255, that's the tricky part. \ - we do it like for BYTE_MUL(), with bit shift: X/255 ~= (X + X/256 + rounding)/256 */ \ - /** so first (X + X/256 + rounding) */\ - pixelVectorRB = _mm_add_epi16(pixelVectorRB, _mm_srli_epi16(pixelVectorRB, 8)); \ - pixelVectorRB = _mm_add_epi16(pixelVectorRB, half); \ - pixelVectorAG = _mm_add_epi16(pixelVectorAG, _mm_srli_epi16(pixelVectorAG, 8)); \ - pixelVectorAG = _mm_add_epi16(pixelVectorAG, half); \ - \ - /** second devide by 256 */\ - pixelVectorRB = _mm_srli_epi16(pixelVectorRB, 8); \ - /** for AG, we could >> 8 to divide followed by << 8 to put the \ - bytes in the correct position. By masking instead, we execute \ - only one instruction */\ - pixelVectorAG = _mm_andnot_si128(colorMask, pixelVectorAG); \ - \ - /* 4. combine the 2 pairs of colors */ \ - result = _mm_or_si128(pixelVectorAG, pixelVectorRB); \ -} - -/* - * Each 32bits components of alphaChannel must be in the form 0x00AA00AA - * oneMinusAlphaChannel must be 255 - alpha for each 32 bits component - * colorMask must have 0x00ff00ff on each 32 bits component - * half must have the value 128 (0x80) for each 32 bits compnent - */ -#define INTERPOLATE_PIXEL_255_SSE2(result, srcVector, dstVector, alphaChannel, oneMinusAlphaChannel, colorMask, half) { \ - /* interpolate AG */\ - __m128i srcVectorAG = _mm_srli_epi16(srcVector, 8); \ - __m128i dstVectorAG = _mm_srli_epi16(dstVector, 8); \ - __m128i srcVectorAGalpha = _mm_mullo_epi16(srcVectorAG, alphaChannel); \ - __m128i dstVectorAGoneMinusAlphalpha = _mm_mullo_epi16(dstVectorAG, oneMinusAlphaChannel); \ - __m128i finalAG = _mm_add_epi16(srcVectorAGalpha, dstVectorAGoneMinusAlphalpha); \ - finalAG = _mm_add_epi16(finalAG, _mm_srli_epi16(finalAG, 8)); \ - finalAG = _mm_add_epi16(finalAG, half); \ - finalAG = _mm_andnot_si128(colorMask, finalAG); \ - \ - /* interpolate RB */\ - __m128i srcVectorRB = _mm_and_si128(srcVector, colorMask); \ - __m128i dstVectorRB = _mm_and_si128(dstVector, colorMask); \ - __m128i srcVectorRBalpha = _mm_mullo_epi16(srcVectorRB, alphaChannel); \ - __m128i dstVectorRBoneMinusAlphalpha = _mm_mullo_epi16(dstVectorRB, oneMinusAlphaChannel); \ - __m128i finalRB = _mm_add_epi16(srcVectorRBalpha, dstVectorRBoneMinusAlphalpha); \ - finalRB = _mm_add_epi16(finalRB, _mm_srli_epi16(finalRB, 8)); \ - finalRB = _mm_add_epi16(finalRB, half); \ - finalRB = _mm_srli_epi16(finalRB, 8); \ - \ - /* combine */\ - result = _mm_or_si128(finalAG, finalRB); \ -} - -// Basically blend src over dst with the const alpha defined as constAlphaVector. -// nullVector, half, one, colorMask are constant accross the whole image/texture, and should be defined as: -//const __m128i nullVector = _mm_set1_epi32(0); -//const __m128i half = _mm_set1_epi16(0x80); -//const __m128i one = _mm_set1_epi16(0xff); -//const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); -//const __m128i alphaMask = _mm_set1_epi32(0xff000000); -// -// The computation being done is: -// result = s + d * (1-alpha) -// with shortcuts if fully opaque or fully transparent. -#define BLEND_SOURCE_OVER_ARGB32_SSE2(dst, src, length, nullVector, half, one, colorMask, alphaMask) { \ - int x = 0; \ - for (; x < length-3; x += 4) { \ - const __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); \ - const __m128i srcVectorAlpha = _mm_and_si128(srcVector, alphaMask); \ - if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, alphaMask)) == 0xffff) { \ - /* all opaque */ \ - _mm_storeu_si128((__m128i *)&dst[x], srcVector); \ - } else if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, nullVector)) != 0xffff) { \ - /* not fully transparent */ \ - /* extract the alpha channel on 2 x 16 bits */ \ - /* so we have room for the multiplication */ \ - /* each 32 bits will be in the form 0x00AA00AA */ \ - /* with A being the 1 - alpha */ \ - __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); \ - alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); \ - alphaChannel = _mm_sub_epi16(one, alphaChannel); \ - \ - const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); \ - __m128i destMultipliedByOneMinusAlpha; \ - BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); \ - \ - /* result = s + d * (1-alpha) */\ - const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); \ - _mm_storeu_si128((__m128i *)&dst[x], result); \ - } \ - } \ - for (; x < length; ++x) { \ - uint s = src[x]; \ - if (s >= 0xff000000) \ - dst[x] = s; \ - else if (s != 0) \ - dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); \ - } \ -} - -// Basically blend src over dst with the const alpha defined as constAlphaVector. -// nullVector, half, one, colorMask are constant accross the whole image/texture, and should be defined as: -//const __m128i nullVector = _mm_set1_epi32(0); -//const __m128i half = _mm_set1_epi16(0x80); -//const __m128i one = _mm_set1_epi16(0xff); -//const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); -// -// The computation being done is: -// dest = (s + d * sia) * ca + d * cia -// = s * ca + d * (sia * ca + cia) -// = s * ca + d * (1 - sa*ca) -#define BLEND_SOURCE_OVER_ARGB32_WITH_CONST_ALPHA_SSE2(dst, src, length, nullVector, half, one, colorMask, constAlphaVector) \ -{ \ - int x = 0; \ - for (; x < length-3; x += 4) { \ - __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); \ - if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVector, nullVector)) != 0xffff) { \ - BYTE_MUL_SSE2(srcVector, srcVector, constAlphaVector, colorMask, half); \ -\ - __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); \ - alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); \ - alphaChannel = _mm_sub_epi16(one, alphaChannel); \ - \ - const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); \ - __m128i destMultipliedByOneMinusAlpha; \ - BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); \ - \ - const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); \ - _mm_storeu_si128((__m128i *)&dst[x], result); \ - } \ - } \ - for (; x < length; ++x) { \ - quint32 s = src[x]; \ - if (s != 0) { \ - s = BYTE_MUL(s, const_alpha); \ - dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); \ - } \ - } \ -} - void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, const uchar *srcPixels, int sbpl, int w, int h, diff --git a/src/gui/painting/qdrawingprimitive_sse2_p.h b/src/gui/painting/qdrawingprimitive_sse2_p.h new file mode 100644 index 0000000..2b595c5 --- /dev/null +++ b/src/gui/painting/qdrawingprimitive_sse2_p.h @@ -0,0 +1,216 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDRAWINGPRIMITIVE_SSE2_P_H +#define QDRAWINGPRIMITIVE_SSE2_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. +// + +QT_BEGIN_NAMESPACE + +/* + * Multiply the components of pixelVector by alphaChannel + * Each 32bits components of alphaChannel must be in the form 0x00AA00AA + * colorMask must have 0x00ff00ff on each 32 bits component + * half must have the value 128 (0x80) for each 32 bits compnent + */ +#define BYTE_MUL_SSE2(result, pixelVector, alphaChannel, colorMask, half) \ +{ \ + /* 1. separate the colors in 2 vectors so each color is on 16 bits \ + (in order to be multiplied by the alpha \ + each 32 bit of dstVectorAG are in the form 0x00AA00GG \ + each 32 bit of dstVectorRB are in the form 0x00RR00BB */\ + __m128i pixelVectorAG = _mm_srli_epi16(pixelVector, 8); \ + __m128i pixelVectorRB = _mm_and_si128(pixelVector, colorMask); \ + \ + /* 2. multiply the vectors by the alpha channel */\ + pixelVectorAG = _mm_mullo_epi16(pixelVectorAG, alphaChannel); \ + pixelVectorRB = _mm_mullo_epi16(pixelVectorRB, alphaChannel); \ + \ + /* 3. devide by 255, that's the tricky part. \ + we do it like for BYTE_MUL(), with bit shift: X/255 ~= (X + X/256 + rounding)/256 */ \ + /** so first (X + X/256 + rounding) */\ + pixelVectorRB = _mm_add_epi16(pixelVectorRB, _mm_srli_epi16(pixelVectorRB, 8)); \ + pixelVectorRB = _mm_add_epi16(pixelVectorRB, half); \ + pixelVectorAG = _mm_add_epi16(pixelVectorAG, _mm_srli_epi16(pixelVectorAG, 8)); \ + pixelVectorAG = _mm_add_epi16(pixelVectorAG, half); \ + \ + /** second devide by 256 */\ + pixelVectorRB = _mm_srli_epi16(pixelVectorRB, 8); \ + /** for AG, we could >> 8 to divide followed by << 8 to put the \ + bytes in the correct position. By masking instead, we execute \ + only one instruction */\ + pixelVectorAG = _mm_andnot_si128(colorMask, pixelVectorAG); \ + \ + /* 4. combine the 2 pairs of colors */ \ + result = _mm_or_si128(pixelVectorAG, pixelVectorRB); \ +} + +/* + * Each 32bits components of alphaChannel must be in the form 0x00AA00AA + * oneMinusAlphaChannel must be 255 - alpha for each 32 bits component + * colorMask must have 0x00ff00ff on each 32 bits component + * half must have the value 128 (0x80) for each 32 bits compnent + */ +#define INTERPOLATE_PIXEL_255_SSE2(result, srcVector, dstVector, alphaChannel, oneMinusAlphaChannel, colorMask, half) { \ + /* interpolate AG */\ + __m128i srcVectorAG = _mm_srli_epi16(srcVector, 8); \ + __m128i dstVectorAG = _mm_srli_epi16(dstVector, 8); \ + __m128i srcVectorAGalpha = _mm_mullo_epi16(srcVectorAG, alphaChannel); \ + __m128i dstVectorAGoneMinusAlphalpha = _mm_mullo_epi16(dstVectorAG, oneMinusAlphaChannel); \ + __m128i finalAG = _mm_add_epi16(srcVectorAGalpha, dstVectorAGoneMinusAlphalpha); \ + finalAG = _mm_add_epi16(finalAG, _mm_srli_epi16(finalAG, 8)); \ + finalAG = _mm_add_epi16(finalAG, half); \ + finalAG = _mm_andnot_si128(colorMask, finalAG); \ + \ + /* interpolate RB */\ + __m128i srcVectorRB = _mm_and_si128(srcVector, colorMask); \ + __m128i dstVectorRB = _mm_and_si128(dstVector, colorMask); \ + __m128i srcVectorRBalpha = _mm_mullo_epi16(srcVectorRB, alphaChannel); \ + __m128i dstVectorRBoneMinusAlphalpha = _mm_mullo_epi16(dstVectorRB, oneMinusAlphaChannel); \ + __m128i finalRB = _mm_add_epi16(srcVectorRBalpha, dstVectorRBoneMinusAlphalpha); \ + finalRB = _mm_add_epi16(finalRB, _mm_srli_epi16(finalRB, 8)); \ + finalRB = _mm_add_epi16(finalRB, half); \ + finalRB = _mm_srli_epi16(finalRB, 8); \ + \ + /* combine */\ + result = _mm_or_si128(finalAG, finalRB); \ +} + +// Basically blend src over dst with the const alpha defined as constAlphaVector. +// nullVector, half, one, colorMask are constant accross the whole image/texture, and should be defined as: +//const __m128i nullVector = _mm_set1_epi32(0); +//const __m128i half = _mm_set1_epi16(0x80); +//const __m128i one = _mm_set1_epi16(0xff); +//const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); +//const __m128i alphaMask = _mm_set1_epi32(0xff000000); +// +// The computation being done is: +// result = s + d * (1-alpha) +// with shortcuts if fully opaque or fully transparent. +#define BLEND_SOURCE_OVER_ARGB32_SSE2(dst, src, length, nullVector, half, one, colorMask, alphaMask) { \ + int x = 0; \ + for (; x < length-3; x += 4) { \ + const __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); \ + const __m128i srcVectorAlpha = _mm_and_si128(srcVector, alphaMask); \ + if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, alphaMask)) == 0xffff) { \ + /* all opaque */ \ + _mm_storeu_si128((__m128i *)&dst[x], srcVector); \ + } else if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, nullVector)) != 0xffff) { \ + /* not fully transparent */ \ + /* extract the alpha channel on 2 x 16 bits */ \ + /* so we have room for the multiplication */ \ + /* each 32 bits will be in the form 0x00AA00AA */ \ + /* with A being the 1 - alpha */ \ + __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); \ + alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); \ + alphaChannel = _mm_sub_epi16(one, alphaChannel); \ + \ + const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); \ + __m128i destMultipliedByOneMinusAlpha; \ + BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); \ + \ + /* result = s + d * (1-alpha) */\ + const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); \ + _mm_storeu_si128((__m128i *)&dst[x], result); \ + } \ + } \ + for (; x < length; ++x) { \ + uint s = src[x]; \ + if (s >= 0xff000000) \ + dst[x] = s; \ + else if (s != 0) \ + dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); \ + } \ +} + +// Basically blend src over dst with the const alpha defined as constAlphaVector. +// nullVector, half, one, colorMask are constant accross the whole image/texture, and should be defined as: +//const __m128i nullVector = _mm_set1_epi32(0); +//const __m128i half = _mm_set1_epi16(0x80); +//const __m128i one = _mm_set1_epi16(0xff); +//const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); +// +// The computation being done is: +// dest = (s + d * sia) * ca + d * cia +// = s * ca + d * (sia * ca + cia) +// = s * ca + d * (1 - sa*ca) +#define BLEND_SOURCE_OVER_ARGB32_WITH_CONST_ALPHA_SSE2(dst, src, length, nullVector, half, one, colorMask, constAlphaVector) \ +{ \ + int x = 0; \ + for (; x < length-3; x += 4) { \ + __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); \ + if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVector, nullVector)) != 0xffff) { \ + BYTE_MUL_SSE2(srcVector, srcVector, constAlphaVector, colorMask, half); \ +\ + __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); \ + alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); \ + alphaChannel = _mm_sub_epi16(one, alphaChannel); \ + \ + const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); \ + __m128i destMultipliedByOneMinusAlpha; \ + BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); \ + \ + const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); \ + _mm_storeu_si128((__m128i *)&dst[x], result); \ + } \ + } \ + for (; x < length; ++x) { \ + quint32 s = src[x]; \ + if (s != 0) { \ + s = BYTE_MUL(s, const_alpha); \ + dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); \ + } \ + } \ +} + +QT_END_NAMESPACE + +#endif // QDRAWINGPRIMITIVE_SSE2_P_H -- cgit v0.12 From dad8e33546a209820da1f3d07a0e331e001bc23e Mon Sep 17 00:00:00 2001 From: John Brooks Date: Mon, 5 Jul 2010 21:17:49 +0200 Subject: SSE2 implementation of convert_ARGB_to_ARGB_PM_inplace for QImage Merge-request: 725 Reviewed-by: Benjamin Poulain --- src/corelib/tools/qsimd_p.h | 5 +- src/gui/image/image.pri | 3 + src/gui/image/qimage.cpp | 18 ++++- src/gui/image/qimage_p.h | 2 + src/gui/image/qimage_sse2.cpp | 109 ++++++++++++++++++++++++++++ src/gui/kernel/qapplication.cpp | 3 + src/gui/painting/qdrawhelper_sse2.cpp | 12 +-- src/gui/painting/qdrawingprimitive_sse2_p.h | 6 ++ 8 files changed, 144 insertions(+), 14 deletions(-) create mode 100644 src/gui/image/qimage_sse2.cpp diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index 58d2dcb..0ed9d5d 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -58,8 +58,7 @@ QT_BEGIN_HEADER #endif // SSE intrinsics -#if defined(QT_HAVE_SSE2) && !defined(QT_BOOTSTRAPPED) && (defined(__SSE2__) \ - || (defined(Q_CC_MSVC) && (defined(_M_X64) || _M_IX86_FP == 2))) +#if defined(QT_HAVE_SSE2) && (defined(__SSE2__) || defined(Q_CC_MSVC)) #if defined(QT_LINUXBASE) /// this is an evil hack - the posix_memalign declaration in LSB /// is wrong - see http://bugs.linuxbase.org/show_bug.cgi?id=2431 @@ -73,8 +72,10 @@ QT_BEGIN_HEADER # include #endif +#if !defined(QT_BOOTSTRAPPED) && (!defined(Q_CC_MSVC) || (defined(_M_X64) || _M_IX86_FP == 2)) #define QT_ALWAYS_HAVE_SSE2 #endif +#endif // defined(QT_HAVE_SSE2) && (defined(__SSE2__) || defined(Q_CC_MSVC)) // NEON intrinsics #if defined(QT_HAVE_NEON) diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri index 9f0c87e..3a02d56 100644 --- a/src/gui/image/image.pri +++ b/src/gui/image/image.pri @@ -92,3 +92,6 @@ contains(QT_CONFIG, jpeg):include($$PWD/qjpeghandler.pri) contains(QT_CONFIG, mng):include($$PWD/qmnghandler.pri) contains(QT_CONFIG, tiff):include($$PWD/qtiffhandler.pri) contains(QT_CONFIG, gif):include($$PWD/qgifhandler.pri) + +# SIMD +SSE2_SOURCES += image/qimage_sse2.cpp diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 79f266d..88a0366 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -58,6 +58,7 @@ #include #include #include +#include #include @@ -209,7 +210,7 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format, int nu break; } - const int bytes_per_line = ((width * depth + 31) >> 5) << 2; // bytes per scanline (must be multiple of 8) + const int bytes_per_line = ((width * depth + 31) >> 5) << 2; // bytes per scanline (must be multiple of 4) // sanity check for potential overflows if (INT_MAX/depth < width @@ -3630,7 +3631,7 @@ static const Image_Converter converter_map[QImage::NImageFormats][QImage::NImage } // Format_ARGB4444_Premultiplied }; -static const InPlace_Image_Converter inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats] = +static InPlace_Image_Converter inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 @@ -3727,6 +3728,19 @@ static const InPlace_Image_Converter inplace_converter_map[QImage::NImageFormats } // Format_ARGB4444_Premultiplied }; +void qInitImageConversions() +{ + const uint features = qDetectCPUFeatures(); + Q_UNUSED(features); + +#ifdef QT_HAVE_SSE2 + if (features & SSE2) { + extern bool convert_ARGB_to_ARGB_PM_inplace_SSE2(QImageData *data, Qt::ImageConversionFlags); + inplace_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_inplace_SSE2; + } +#endif +} + /*! Returns a copy of the image in the given \a format. diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h index f1a0c47..5272848 100644 --- a/src/gui/image/qimage_p.h +++ b/src/gui/image/qimage_p.h @@ -108,6 +108,8 @@ struct Q_GUI_EXPORT QImageData { // internal image data QPaintEngine *paintEngine; }; +void qInitImageConversions(); + QT_END_NAMESPACE #endif diff --git a/src/gui/image/qimage_sse2.cpp b/src/gui/image/qimage_sse2.cpp new file mode 100644 index 0000000..e2b89b9 --- /dev/null +++ b/src/gui/image/qimage_sse2.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qimage.h" +#include +#include +#include +#include + +#ifdef QT_HAVE_SSE2 + +QT_BEGIN_NAMESPACE + +bool convert_ARGB_to_ARGB_PM_inplace_SSE2(QImageData *data, Qt::ImageConversionFlags) +{ + Q_ASSERT(data->format == QImage::Format_ARGB32); + + // extra pixels on each line + const int spare = data->width & 3; + // width in pixels of the pad at the end of each line + const int pad = (data->bytes_per_line >> 2) - data->width; + const int iter = data->width >> 2; + int height = data->height; + + const __m128i alphaMask = _mm_set1_epi32(0xff000000); + const __m128i nullVector = _mm_setzero_si128(); + const __m128i half = _mm_set1_epi16(0x80); + const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); + + __m128i *d = reinterpret_cast<__m128i*>(data->data); + while (height--) { + const __m128i *end = d + iter; + + for (; d != end; ++d) { + const __m128i srcVector = _mm_loadu_si128(d); + const __m128i srcVectorAlpha = _mm_and_si128(srcVector, alphaMask); + if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, alphaMask)) == 0xffff) { + // opaque, data is unchanged + } else if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, nullVector)) == 0xffff) { + // fully transparent + _mm_storeu_si128(d, nullVector); + } else { + __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); + alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); + + __m128i result; + BYTE_MUL_SSE2(result, srcVector, alphaChannel, colorMask, half); + result = _mm_or_si128(_mm_andnot_si128(alphaMask, result), srcVectorAlpha); + _mm_storeu_si128(d, result); + } + } + + QRgb *p = reinterpret_cast(d); + QRgb *pe = p+spare; + for (; p != pe; ++p) { + if (*p < 0x00ffffff) + *p = 0; + else if (*p < 0xff000000) + *p = PREMUL(*p); + } + + d = reinterpret_cast<__m128i*>(p+pad); + } + + data->format = QImage::Format_ARGB32_Premultiplied; + return true; +} + +QT_END_NAMESPACE + +#endif // QT_HAVE_SSE2 diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index ccfe88c..94211fd 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -902,6 +902,7 @@ QApplication::QApplication(Display *dpy, int &argc, char **argv, #endif // Q_WS_X11 extern void qInitDrawhelperAsm(); +extern void qInitImageConversions(); extern int qRegisterGuiVariant(); extern int qUnregisterGuiVariant(); #ifndef QT_NO_STATEMACHINE @@ -959,6 +960,8 @@ void QApplicationPrivate::initialize() // Set up which span functions should be used in raster engine... qInitDrawhelperAsm(); + // and QImage conversion functions + qInitImageConversions(); #ifndef QT_NO_WHEELEVENT QApplicationPrivate::wheel_scroll_lines = 3; diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp index ae16fed..346e177 100644 --- a/src/gui/painting/qdrawhelper_sse2.cpp +++ b/src/gui/painting/qdrawhelper_sse2.cpp @@ -43,18 +43,10 @@ #ifdef QT_HAVE_SSE2 +#include +#include #include -#ifdef QT_LINUXBASE -// this is an evil hack - the posix_memalign declaration in LSB -// is wrong - see http://bugs.linuxbase.org/show_bug.cgi?id=2431 -# define posix_memalign _lsb_hack_posix_memalign -# include -# undef posix_memalign -#else -# include -#endif - QT_BEGIN_NAMESPACE void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, diff --git a/src/gui/painting/qdrawingprimitive_sse2_p.h b/src/gui/painting/qdrawingprimitive_sse2_p.h index 2b595c5..3c96946 100644 --- a/src/gui/painting/qdrawingprimitive_sse2_p.h +++ b/src/gui/painting/qdrawingprimitive_sse2_p.h @@ -42,6 +42,10 @@ #ifndef QDRAWINGPRIMITIVE_SSE2_P_H #define QDRAWINGPRIMITIVE_SSE2_P_H +#include + +#ifdef QT_HAVE_SSE2 + // // W A R N I N G // ------------- @@ -213,4 +217,6 @@ QT_BEGIN_NAMESPACE QT_END_NAMESPACE +#endif // QT_HAVE_SSE2 + #endif // QDRAWINGPRIMITIVE_SSE2_P_H -- cgit v0.12 From 03f325217ab8d896327cb8a31f07df4633e9a485 Mon Sep 17 00:00:00 2001 From: Benjamin Poulain Date: Tue, 6 Jul 2010 13:22:10 +0200 Subject: Build fix, the header of QImageData did not declare QImageWriter. Including this header in the SSE2 file broke the build because QImageWriter was not declared. --- src/gui/image/qimage_p.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h index 5272848..da535aa 100644 --- a/src/gui/image/qimage_p.h +++ b/src/gui/image/qimage_p.h @@ -61,6 +61,8 @@ #include #endif +class QImageWriter; + QT_BEGIN_NAMESPACE struct Q_GUI_EXPORT QImageData { // internal image data -- cgit v0.12 From 51509e8df8caf9c84312255a0dae41615fda1168 Mon Sep 17 00:00:00 2001 From: Benjamin Poulain Date: Wed, 7 Jul 2010 11:53:45 +0200 Subject: Add test and fix style for the SSE2 implementation of ARGB32 conversion The commit beba018814b35c4bd032e6b9fa948e4bac34c59a introduce conversion from ARGB32 to ARGB32_PM with SSE2. This patch add a benchmark for this type of usage, and change the name to use lowercase for SSE2 (style convention). --- src/gui/image/qimage.cpp | 4 +- src/gui/image/qimage_sse2.cpp | 2 +- tests/benchmarks/gui/image/qpixmap/tst_qpixmap.cpp | 64 +++++++++++++++++++++- 3 files changed, 66 insertions(+), 4 deletions(-) diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 88a0366..e5930ac 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -3735,8 +3735,8 @@ void qInitImageConversions() #ifdef QT_HAVE_SSE2 if (features & SSE2) { - extern bool convert_ARGB_to_ARGB_PM_inplace_SSE2(QImageData *data, Qt::ImageConversionFlags); - inplace_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_inplace_SSE2; + extern bool convert_ARGB_to_ARGB_PM_inplace_sse2(QImageData *data, Qt::ImageConversionFlags); + inplace_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_inplace_sse2; } #endif } diff --git a/src/gui/image/qimage_sse2.cpp b/src/gui/image/qimage_sse2.cpp index e2b89b9..82d49a6 100644 --- a/src/gui/image/qimage_sse2.cpp +++ b/src/gui/image/qimage_sse2.cpp @@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE -bool convert_ARGB_to_ARGB_PM_inplace_SSE2(QImageData *data, Qt::ImageConversionFlags) +bool convert_ARGB_to_ARGB_PM_inplace_sse2(QImageData *data, Qt::ImageConversionFlags) { Q_ASSERT(data->format == QImage::Format_ARGB32); diff --git a/tests/benchmarks/gui/image/qpixmap/tst_qpixmap.cpp b/tests/benchmarks/gui/image/qpixmap/tst_qpixmap.cpp index 8e9de4a..27e5025 100644 --- a/tests/benchmarks/gui/image/qpixmap/tst_qpixmap.cpp +++ b/tests/benchmarks/gui/image/qpixmap/tst_qpixmap.cpp @@ -40,9 +40,12 @@ ****************************************************************************/ #include -#include #include +#include +#include +#include #include +#include #include class tst_QPixmap : public QObject @@ -62,6 +65,9 @@ private slots: void transformed(); void mask_data(); void mask(); + + void fromImageReader_data(); + void fromImageReader(); }; Q_DECLARE_METATYPE(QImage::Format) @@ -248,6 +254,62 @@ void tst_QPixmap::mask() } } +void tst_QPixmap::fromImageReader_data() +{ + const QString tempDir = QDir::tempPath(); + QTest::addColumn("filename"); + + QImage image(2000, 2000, QImage::Format_ARGB32); + image.fill(0); + { + // Generate an image with opaque and transparent pixels + // with an interesting distribution. + QPainter painter(&image); + + QRadialGradient radialGrad(QPointF(1000, 1000), 1000); + radialGrad.setColorAt(0, QColor(255, 0, 0, 255)); + radialGrad.setColorAt(0.5, QColor(0, 255, 0, 255)); + radialGrad.setColorAt(0.9, QColor(0, 0, 255, 100)); + radialGrad.setColorAt(1, QColor(0, 0, 0, 0)); + + painter.fillRect(image.rect(), radialGrad); + } + image.save("test.png"); + + // RGB32 + const QString rgb32Path = tempDir + QString::fromLatin1("/rgb32.jpg"); + image.save(rgb32Path); + QTest::newRow("gradient RGB32") << rgb32Path; + + // ARGB32 + const QString argb32Path = tempDir + QString::fromLatin1("/argb32.png"); + image.save(argb32Path); + QTest::newRow("gradient ARGB32") << argb32Path; + + // Indexed 8 + const QString indexed8Path = tempDir + QString::fromLatin1("/indexed8.gif"); + image.save(indexed8Path); + QTest::newRow("gradient indexed8") << indexed8Path; + +} + +void tst_QPixmap::fromImageReader() +{ + QFETCH(QString, filename); + // warmup + { + QImageReader imageReader(filename); + QPixmap::fromImageReader(&imageReader); + } + + QBENCHMARK { + QImageReader imageReader(filename); + QPixmap::fromImageReader(&imageReader); + } + QFile::remove(filename); +} + + QTEST_MAIN(tst_QPixmap) #include "tst_qpixmap.moc" -- cgit v0.12 From 1b598281b5071dff6b1c1510fcb4d41a300c47a4 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 7 Jul 2010 13:02:31 +0200 Subject: Add partial update deployment rules to QtNetwork Partial update allows you to build a qtnetwork.sis which can be installed on top of a matching qt.sis, but contains only the qtnetwork.dll file. This is faster to install, so it's useful when developing qtnetwork. Reviewed-by: Simon Hausmann --- src/network/network.pro | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/network/network.pro b/src/network/network.pro index 7ed7d3a..5e33080 100644 --- a/src/network/network.pro +++ b/src/network/network.pro @@ -28,4 +28,19 @@ QMAKE_LIBS += $$QMAKE_LIBS_NETWORK symbian { TARGET.UID3=0x2001B2DE LIBS += -lesock -linsock -lcertstore -lefsrv -lctframework + + # Partial upgrade SIS file + vendorinfo = \ + "; Localised Vendor name" \ + "%{\"Nokia, Qt\"}" \ + " " \ + "; Unique Vendor name" \ + ":\"Nokia, Qt\"" \ + " " + pu_header = "; Partial upgrade package for testing QtGui changes without reinstalling everything" \ + "$${LITERAL_HASH}{\"Qt network\"}, (0x2001E61C), $${QT_MAJOR_VERSION},$${QT_MINOR_VERSION},$${QT_PATCH_VERSION}, TYPE=PU" + partial_upgrade.pkg_prerules = pu_header vendorinfo + partial_upgrade.sources = $$QMAKE_LIBDIR_QT/QtNetwork.dll + partial_upgrade.path = c:/sys/bin + DEPLOYMENT = partial_upgrade $$DEPLOYMENT } -- cgit v0.12 From 584309d3d42f3118efade8f499a3f223665f3d86 Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Tue, 8 Jun 2010 11:30:05 +0100 Subject: Prevent crash when video is played without a VideoWidget The Phonon API allows video to be played via a Phonon::MediaObject, even if no Phonon::VideoWidget has been connected to it. This patch prevents the Phonon MMF backend crashing in this scenario due to dereferencing a null pointer. Reviewed-by: Thierry Bastian --- src/3rdparty/phonon/mmf/abstractvideoplayer.cpp | 10 ++++++++-- src/3rdparty/phonon/mmf/videoplayer_dsa.cpp | 7 ++++++- src/3rdparty/phonon/mmf/videoplayer_surface.cpp | 5 ++++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp b/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp index 2e0ab1c..ecfce9e 100644 --- a/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp +++ b/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp @@ -211,7 +211,8 @@ void MMF::AbstractVideoPlayer::aspectRatioChanged() TRACE_CONTEXT(AbstractVideoPlayer::aspectRatioChanged, EVideoInternal); TRACE_ENTRY("state %d aspectRatio %d", state()); - updateScaleFactors(m_videoOutput->videoWindowSize()); + if (m_videoOutput) + updateScaleFactors(m_videoOutput->videoWindowSize()); TRACE_EXIT_0(); } @@ -221,7 +222,8 @@ void MMF::AbstractVideoPlayer::scaleModeChanged() TRACE_CONTEXT(AbstractVideoPlayer::scaleModeChanged, EVideoInternal); TRACE_ENTRY("state %d", state()); - updateScaleFactors(m_videoOutput->videoWindowSize()); + if (m_videoOutput) + updateScaleFactors(m_videoOutput->videoWindowSize()); TRACE_EXIT_0(); } @@ -357,6 +359,8 @@ void MMF::AbstractVideoPlayer::videoOutputChanged() void MMF::AbstractVideoPlayer::initVideoOutput() { + Q_ASSERT(m_videoOutput); + bool connected = connect( m_videoOutput, SIGNAL(videoWindowChanged()), this, SLOT(videoWindowChanged()) @@ -400,6 +404,8 @@ QSize scaleToAspect(const QSize &srcRect, int aspectWidth, int aspectHeight) void MMF::AbstractVideoPlayer::updateScaleFactors(const QSize &windowSize, bool apply) { + Q_ASSERT(m_videoOutput); + if (m_videoFrameSize.isValid()) { QRect videoRect; diff --git a/src/3rdparty/phonon/mmf/videoplayer_dsa.cpp b/src/3rdparty/phonon/mmf/videoplayer_dsa.cpp index 1925471..f0255b1 100644 --- a/src/3rdparty/phonon/mmf/videoplayer_dsa.cpp +++ b/src/3rdparty/phonon/mmf/videoplayer_dsa.cpp @@ -61,6 +61,8 @@ DsaVideoPlayer::~DsaVideoPlayer() void MMF::DsaVideoPlayer::videoWindowScreenRectChanged() { + Q_ASSERT(m_videoOutput); + QRect windowRect = static_cast(m_videoOutput)->videoWindowScreenRect(); // Clip to physical window size @@ -130,6 +132,8 @@ void MMF::DsaVideoPlayer::createPlayer() void MMF::DsaVideoPlayer::initVideoOutput() { + Q_ASSERT(m_videoOutput); + bool connected = connect( m_videoOutput, SIGNAL(videoWindowScreenRectChanged()), this, SLOT(videoWindowScreenRectChanged()) @@ -156,7 +160,8 @@ void MMF::DsaVideoPlayer::initVideoOutput() void MMF::DsaVideoPlayer::prepareCompleted() { - videoWindowScreenRectChanged(); + if (m_videoOutput) + videoWindowScreenRectChanged(); } void MMF::DsaVideoPlayer::handleVideoWindowChanged() diff --git a/src/3rdparty/phonon/mmf/videoplayer_surface.cpp b/src/3rdparty/phonon/mmf/videoplayer_surface.cpp index fda7342..5d8db26 100644 --- a/src/3rdparty/phonon/mmf/videoplayer_surface.cpp +++ b/src/3rdparty/phonon/mmf/videoplayer_surface.cpp @@ -59,7 +59,8 @@ SurfaceVideoPlayer::~SurfaceVideoPlayer() void MMF::SurfaceVideoPlayer::videoWindowSizeChanged() { - updateScaleFactors(m_videoOutput->videoWindowSize()); + if (m_videoOutput) + updateScaleFactors(m_videoOutput->videoWindowSize()); } @@ -80,6 +81,8 @@ void MMF::SurfaceVideoPlayer::createPlayer() void MMF::SurfaceVideoPlayer::initVideoOutput() { + Q_ASSERT(m_videoOutput); + bool connected = connect( m_videoOutput, SIGNAL(videoWindowSizeChanged()), this, SLOT(videoWindowSizeChanged()) -- cgit v0.12 From 56a2b6315c44d10f2ca4c76729a53ad9dbed37f9 Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Tue, 8 Jun 2010 14:56:31 +0100 Subject: Enable bufferStatus signal during video clip loading on NGA platforms CVideoPlayerUtility::RegisterForVideoLoadingNotification() was only called in the DSA, not the NGA, variant of the Phonon MMF backend. Task-number: QTBUG-11378 Reviewed-by: Thierry Bastian --- src/3rdparty/phonon/mmf/abstractvideoplayer.cpp | 2 ++ src/3rdparty/phonon/mmf/videoplayer_dsa.cpp | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp b/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp index ecfce9e..c45ed98 100644 --- a/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp +++ b/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp @@ -66,6 +66,8 @@ void MMF::AbstractVideoPlayer::construct() createPlayer(); + m_player->RegisterForVideoLoadingNotification(*this); + TRACE_EXIT_0(); } diff --git a/src/3rdparty/phonon/mmf/videoplayer_dsa.cpp b/src/3rdparty/phonon/mmf/videoplayer_dsa.cpp index f0255b1..deb9774 100644 --- a/src/3rdparty/phonon/mmf/videoplayer_dsa.cpp +++ b/src/3rdparty/phonon/mmf/videoplayer_dsa.cpp @@ -126,8 +126,6 @@ void MMF::DsaVideoPlayer::createPlayer() // CVideoPlayerUtility::NewL starts DSA m_dsaActive = true; - - m_player->RegisterForVideoLoadingNotification(*this); } void MMF::DsaVideoPlayer::initVideoOutput() -- cgit v0.12 From a1c7b42e8b67e935fe30310af49524a25fa631fc Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Tue, 8 Jun 2010 14:37:21 +0100 Subject: Close media clip before creating new player object Failure to Close() an existing MMF player utility object before creating a new one - which happens in the MMF backend's implementation of Phonon::MediaObject::setCurrentSource() - causes intialization of the newly-created utility to fail later on. Task-number: QTBUG-11377 Reviewed-by: Thierry Bastian --- src/3rdparty/phonon/mmf/abstractmediaplayer.h | 1 - src/3rdparty/phonon/mmf/abstractplayer.h | 1 + src/3rdparty/phonon/mmf/dummyplayer.cpp | 4 ++++ src/3rdparty/phonon/mmf/dummyplayer.h | 1 + src/3rdparty/phonon/mmf/mediaobject.cpp | 3 +++ 5 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/3rdparty/phonon/mmf/abstractmediaplayer.h b/src/3rdparty/phonon/mmf/abstractmediaplayer.h index 23a8233..7d28caf 100644 --- a/src/3rdparty/phonon/mmf/abstractmediaplayer.h +++ b/src/3rdparty/phonon/mmf/abstractmediaplayer.h @@ -71,7 +71,6 @@ protected: virtual int openFile(RFile& file) = 0; virtual int openUrl(const QString& url) = 0; virtual int bufferStatus() const = 0; - virtual void close() = 0; void updateMetaData(); virtual int numberOfMetaDataEntries() const = 0; diff --git a/src/3rdparty/phonon/mmf/abstractplayer.h b/src/3rdparty/phonon/mmf/abstractplayer.h index ab892f5..30d5243 100644 --- a/src/3rdparty/phonon/mmf/abstractplayer.h +++ b/src/3rdparty/phonon/mmf/abstractplayer.h @@ -55,6 +55,7 @@ public: AbstractPlayer(const AbstractPlayer *player); virtual void open(const Phonon::MediaSource&, RFile&) = 0; + virtual void close() = 0; // MediaObjectInterface (implemented) qint32 tickInterval() const; diff --git a/src/3rdparty/phonon/mmf/dummyplayer.cpp b/src/3rdparty/phonon/mmf/dummyplayer.cpp index 6970088..d39ef76 100644 --- a/src/3rdparty/phonon/mmf/dummyplayer.cpp +++ b/src/3rdparty/phonon/mmf/dummyplayer.cpp @@ -97,6 +97,10 @@ void MMF::DummyPlayer::open(const Phonon::MediaSource &, RFile &) } +void MMF::DummyPlayer::close() +{ + +} //----------------------------------------------------------------------------- // AbstractPlayer diff --git a/src/3rdparty/phonon/mmf/dummyplayer.h b/src/3rdparty/phonon/mmf/dummyplayer.h index 6841b5d..9d45696 100644 --- a/src/3rdparty/phonon/mmf/dummyplayer.h +++ b/src/3rdparty/phonon/mmf/dummyplayer.h @@ -58,6 +58,7 @@ public: // AbstractPlayer virtual void open(const Phonon::MediaSource&, RFile&); + virtual void close(); virtual void doSetTickInterval(qint32 interval); }; } diff --git a/src/3rdparty/phonon/mmf/mediaobject.cpp b/src/3rdparty/phonon/mmf/mediaobject.cpp index e1b921b..d264377 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.cpp +++ b/src/3rdparty/phonon/mmf/mediaobject.cpp @@ -281,6 +281,9 @@ void MMF::MediaObject::createPlayer(const MediaSource &source) break; } + if (oldPlayer) + oldPlayer->close(); + AbstractPlayer* newPlayer = 0; // Construct newPlayer using oldPlayer (if not 0) in order to copy -- cgit v0.12 From 12f56ae9006b75e37365022065b786830b4a3038 Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Tue, 8 Jun 2010 16:06:37 +0100 Subject: Fixed crash which occurs when switching between video clips When Phonon::MediaObject::setCurrentSource() is called when the MediaObject is connected to a Phonon::VideoWidget, the MMF::AbstractVideoOutput pointer is propagated inside the backend from the first MMF::AbstractVideoPlayer to the second. If the VideoWidget is subsquently re-sized, the code path enters the ScaleFactors branch of the MMF::SurfaceVideoPlayer::handleParametersChanged function. At this point, m_displayWindow is still set to the inital null value, and the assertion therefore fails. This change ensures that m_displayWindow is updated before attempting to apply the scale factor change. Task-number: QTBUG-11377 Reviewed-by: Thierry Bastian --- src/3rdparty/phonon/mmf/videoplayer_surface.cpp | 42 +++++++++++++++++-------- src/3rdparty/phonon/mmf/videoplayer_surface.h | 3 ++ 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/3rdparty/phonon/mmf/videoplayer_surface.cpp b/src/3rdparty/phonon/mmf/videoplayer_surface.cpp index 5d8db26..343370c 100644 --- a/src/3rdparty/phonon/mmf/videoplayer_surface.cpp +++ b/src/3rdparty/phonon/mmf/videoplayer_surface.cpp @@ -118,23 +118,14 @@ void MMF::SurfaceVideoPlayer::handleParametersChanged(VideoParameters parameters if (player) { int err = KErrNone; if (parameters & WindowHandle) { - if (m_displayWindow) - player->RemoveDisplayWindow(*m_displayWindow); - - RWindow *window = static_cast(m_window); - if (window) { - window->SetBackgroundColor(TRgb(0, 0, 0, 255)); - TRAP(err, player->AddDisplayWindowL(m_wsSession, m_screenDevice, *window, rect, rect)); - if (KErrNone != err) { - setError(tr("Video display error"), err); - window = 0; - } - } - m_displayWindow = window; + removeDisplayWindow(); + addDisplayWindow(rect); } if (KErrNone == err) { if (parameters & ScaleFactors) { + if (!m_displayWindow) + addDisplayWindow(rect); Q_ASSERT(m_displayWindow); TRAP(err, player->SetVideoExtentL(*m_displayWindow, rect)); if (KErrNone == err) @@ -148,5 +139,30 @@ void MMF::SurfaceVideoPlayer::handleParametersChanged(VideoParameters parameters } } +void MMF::SurfaceVideoPlayer::addDisplayWindow(const TRect &rect) +{ + Q_ASSERT(!m_displayWindow); + RWindow *window = static_cast(m_window); + if (window) { + window->SetBackgroundColor(TRgb(0, 0, 0, 255)); + CVideoPlayerUtility2 *player = static_cast(m_player.data()); + Q_ASSERT(player); + TRAPD(err, player->AddDisplayWindowL(m_wsSession, m_screenDevice, *window, rect, rect)); + if (KErrNone == err) + m_displayWindow = window; + else + setError(tr("Video display error"), err); + } +} + +void MMF::SurfaceVideoPlayer::removeDisplayWindow() +{ + CVideoPlayerUtility2 *player = static_cast(m_player.data()); + if (player && m_displayWindow) { + player->RemoveDisplayWindow(*m_displayWindow); + m_displayWindow = 0; + } +} + QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/mmf/videoplayer_surface.h b/src/3rdparty/phonon/mmf/videoplayer_surface.h index c05da9c..8572fdc 100644 --- a/src/3rdparty/phonon/mmf/videoplayer_surface.h +++ b/src/3rdparty/phonon/mmf/videoplayer_surface.h @@ -62,6 +62,9 @@ private: void handleVideoWindowChanged(); void handleParametersChanged(VideoParameters parameters); + void addDisplayWindow(const TRect &rect); + void removeDisplayWindow(); + private: // Window handle which has been passed to the MMF via // CVideoPlayerUtility2::SetDisplayWindowL -- cgit v0.12 From 1c1094a432fc3b88c86c8af37a80a560571fb2fe Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Thu, 17 Jun 2010 09:42:52 +0100 Subject: MMF Phonon backend: call winId() from VideoWidget constructor This is to be consistent with the backends for other platforms, which also call QWidget::winId() on the VideoWidget (or one of its children) during construction. Reviewed-by: Thierry Bastian --- src/3rdparty/phonon/mmf/abstractvideooutput.cpp | 3 ++- src/3rdparty/phonon/mmf/abstractvideoplayer.cpp | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/3rdparty/phonon/mmf/abstractvideooutput.cpp b/src/3rdparty/phonon/mmf/abstractvideooutput.cpp index a8aabfd..2d221ed 100644 --- a/src/3rdparty/phonon/mmf/abstractvideooutput.cpp +++ b/src/3rdparty/phonon/mmf/abstractvideooutput.cpp @@ -60,7 +60,8 @@ MMF::AbstractVideoOutput::AbstractVideoOutput(QWidget *parent) , m_aspectRatio(DefaultAspectRatio) , m_scaleMode(DefaultScaleMode) { - + // Ensure that this widget has a native window handle + winId(); } MMF::AbstractVideoOutput::~AbstractVideoOutput() diff --git a/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp b/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp index c45ed98..9ea4d18 100644 --- a/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp +++ b/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp @@ -384,9 +384,6 @@ void MMF::AbstractVideoPlayer::initVideoOutput() // Suppress warnings in release builds Q_UNUSED(connected); - // Do these after all connections are complete, to ensure - // that any signals generated get to their destinations. - m_videoOutput->winId(); m_videoOutput->setVideoSize(m_videoFrameSize); } -- cgit v0.12 From 43f67922b2d58b31d9baf48e3d9f177388f90faf Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Wed, 7 Jul 2010 18:12:46 +0100 Subject: Added trace statements to Phonon MMF backend Reviewed-by: trustme --- src/3rdparty/phonon/mmf/videoplayer_surface.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/3rdparty/phonon/mmf/videoplayer_surface.cpp b/src/3rdparty/phonon/mmf/videoplayer_surface.cpp index 343370c..f380e69 100644 --- a/src/3rdparty/phonon/mmf/videoplayer_surface.cpp +++ b/src/3rdparty/phonon/mmf/videoplayer_surface.cpp @@ -107,6 +107,9 @@ void MMF::SurfaceVideoPlayer::handleVideoWindowChanged() void MMF::SurfaceVideoPlayer::handleParametersChanged(VideoParameters parameters) { + TRACE_CONTEXT(SurfaceVideoPlayer::handleParametersChanged, EVideoApi); + TRACE_ENTRY("parameters 0x%x", parameters.operator int()); + TRect rect; if (m_videoOutput) { m_videoOutput->dump(); @@ -137,12 +140,20 @@ void MMF::SurfaceVideoPlayer::handleParametersChanged(VideoParameters parameters } } } + + TRACE_EXIT_0(); } void MMF::SurfaceVideoPlayer::addDisplayWindow(const TRect &rect) { + TRACE_CONTEXT(SurfaceVideoPlayer::addDisplayWindow, EVideoApi); + TRACE_ENTRY("rect %d %d - %d %d", rect.iTl.iX, rect.iTl.iY, rect.iBr.iX, rect.iBr.iY); + Q_ASSERT(!m_displayWindow); RWindow *window = static_cast(m_window); + + TRACE("window 0x%08x", window); + if (window) { window->SetBackgroundColor(TRgb(0, 0, 0, 255)); CVideoPlayerUtility2 *player = static_cast(m_player.data()); @@ -152,11 +163,17 @@ void MMF::SurfaceVideoPlayer::addDisplayWindow(const TRect &rect) m_displayWindow = window; else setError(tr("Video display error"), err); + TRACE("err %d", err); } + + TRACE_EXIT_0(); } void MMF::SurfaceVideoPlayer::removeDisplayWindow() { + TRACE_CONTEXT(SurfaceVideoPlayer::removeDisplayWindow, EVideoApi); + TRACE("player 0x%08x window 0x%08x", m_player.data(), m_displayWindow); + CVideoPlayerUtility2 *player = static_cast(m_player.data()); if (player && m_displayWindow) { player->RemoveDisplayWindow(*m_displayWindow); -- cgit v0.12 From aa7de4f45660b5e1c470bf876606f846e120dd50 Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Wed, 7 Jul 2010 18:43:04 +0100 Subject: Use lower case for including system header files All platform includes are now lower case, i.e. '#include ' rather than '#include '. Note that Qt includes are still camel case, e.g. '#include ' Task-number: QTBUG-6528 Reviewed-by: trustme --- src/3rdparty/phonon/mmf/abstractaudioeffect.h | 2 +- src/3rdparty/phonon/mmf/audioequalizer.cpp | 2 +- src/3rdparty/phonon/mmf/bassboost.cpp | 2 +- src/3rdparty/phonon/mmf/environmentalreverb.cpp | 2 +- src/3rdparty/phonon/mmf/loudness.cpp | 2 +- src/3rdparty/phonon/mmf/stereowidening.cpp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/3rdparty/phonon/mmf/abstractaudioeffect.h b/src/3rdparty/phonon/mmf/abstractaudioeffect.h index 70adcf6..8879636 100644 --- a/src/3rdparty/phonon/mmf/abstractaudioeffect.h +++ b/src/3rdparty/phonon/mmf/abstractaudioeffect.h @@ -21,7 +21,7 @@ along with this library. If not, see . #include -#include +#include #include diff --git a/src/3rdparty/phonon/mmf/audioequalizer.cpp b/src/3rdparty/phonon/mmf/audioequalizer.cpp index 1d2bbd4..28433f6 100644 --- a/src/3rdparty/phonon/mmf/audioequalizer.cpp +++ b/src/3rdparty/phonon/mmf/audioequalizer.cpp @@ -16,7 +16,7 @@ along with this library. If not, see . */ -#include +#include #include "audioequalizer.h" QT_BEGIN_NAMESPACE diff --git a/src/3rdparty/phonon/mmf/bassboost.cpp b/src/3rdparty/phonon/mmf/bassboost.cpp index 67076f6..81d9208 100644 --- a/src/3rdparty/phonon/mmf/bassboost.cpp +++ b/src/3rdparty/phonon/mmf/bassboost.cpp @@ -16,7 +16,7 @@ along with this library. If not, see . */ -#include +#include #include "bassboost.h" QT_BEGIN_NAMESPACE diff --git a/src/3rdparty/phonon/mmf/environmentalreverb.cpp b/src/3rdparty/phonon/mmf/environmentalreverb.cpp index d4f5223..c500385 100644 --- a/src/3rdparty/phonon/mmf/environmentalreverb.cpp +++ b/src/3rdparty/phonon/mmf/environmentalreverb.cpp @@ -16,7 +16,7 @@ along with this library. If not, see . */ -#include +#include #include "environmentalreverb.h" QT_BEGIN_NAMESPACE diff --git a/src/3rdparty/phonon/mmf/loudness.cpp b/src/3rdparty/phonon/mmf/loudness.cpp index ca05ab0..22d7518 100644 --- a/src/3rdparty/phonon/mmf/loudness.cpp +++ b/src/3rdparty/phonon/mmf/loudness.cpp @@ -16,7 +16,7 @@ along with this library. If not, see . */ -#include +#include #include "loudness.h" QT_BEGIN_NAMESPACE diff --git a/src/3rdparty/phonon/mmf/stereowidening.cpp b/src/3rdparty/phonon/mmf/stereowidening.cpp index f90651b..e452160 100644 --- a/src/3rdparty/phonon/mmf/stereowidening.cpp +++ b/src/3rdparty/phonon/mmf/stereowidening.cpp @@ -16,7 +16,7 @@ along with this library. If not, see . */ -#include +#include #include "stereowidening.h" QT_BEGIN_NAMESPACE -- cgit v0.12 From e231da119daec62c0aa2cee055c539154a0f935d Mon Sep 17 00:00:00 2001 From: Charles Yin Date: Thu, 8 Jul 2010 14:25:53 +1000 Subject: Fixes the sqlite driver bug QTBUG-11904 (pointer aliasing) Applying upstream sqlite patch from: http://www.sqlite.org/src/info/d6ae275122 Task-number: QTBUG-11904 Reviewed-by: Michael Goddard --- src/3rdparty/sqlite/sqlite3.c | 47 +++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c index 46d3dfc..27a8d18 100644 --- a/src/3rdparty/sqlite/sqlite3.c +++ b/src/3rdparty/sqlite/sqlite3.c @@ -48449,11 +48449,15 @@ SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe *p){ #endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */ /* -** Allocate space from a fixed size buffer. Make *pp point to the -** allocated space. (Note: pp is a char* rather than a void** to -** work around the pointer aliasing rules of C.) *pp should initially -** be zero. If *pp is not zero, that means that the space has already -** been allocated and this routine is a noop. +** Allocate space from a fixed size buffer and return a pointer to +** that space. If insufficient space is available, return NULL. +** +** The pBuf parameter is the initial value of a pointer which will +** receive the new memory. pBuf is normally NULL. If pBuf is not +** NULL, it means that memory space has already been allocated and that +** this routine should not allocate any new memory. When pBuf is not +** NULL simply return pBuf. Only allocate new memory space when pBuf +** is NULL. ** ** nByte is the number of bytes of space needed. ** @@ -48464,23 +48468,23 @@ SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe *p){ ** to allocate. If there is insufficient space in *ppFrom to satisfy the ** request, then increment *pnByte by the amount of the request. */ -static void allocSpace( - char *pp, /* IN/OUT: Set *pp to point to allocated buffer */ +static void *allocSpace( + void *pBuf, /* Where return pointer will be stored */ int nByte, /* Number of bytes to allocate */ u8 **ppFrom, /* IN/OUT: Allocate from *ppFrom */ u8 *pEnd, /* Pointer to 1 byte past the end of *ppFrom buffer */ int *pnByte /* If allocation cannot be made, increment *pnByte */ ){ assert( EIGHT_BYTE_ALIGNMENT(*ppFrom) ); - if( (*(void**)pp)==0 ){ - nByte = ROUND8(nByte); - if( &(*ppFrom)[nByte] <= pEnd ){ - *(void**)pp = (void *)*ppFrom; - *ppFrom += nByte; - }else{ - *pnByte += nByte; - } + if( pBuf ) return pBuf; + nByte = ROUND8(nByte); + if( &(*ppFrom)[nByte] <= pEnd ){ + pBuf = (void*)*ppFrom; + *ppFrom += nByte; + }else{ + *pnByte += nByte; } + return pBuf; } /* @@ -48553,13 +48557,12 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( do { nByte = 0; - allocSpace((char*)&p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte); - allocSpace((char*)&p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte); - allocSpace((char*)&p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte); - allocSpace((char*)&p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte); - allocSpace((char*)&p->apCsr, - nCursor*sizeof(VdbeCursor*), &zCsr, zEnd, &nByte - ); + p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte); + p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte); + p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte); + p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte); + p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*), + &zCsr, zEnd, &nByte); if( nByte ){ p->pFree = sqlite3DbMallocZero(db, nByte); } -- cgit v0.12 From ebf175b3d68e28cd808204adaba1ec8942ac5a8f Mon Sep 17 00:00:00 2001 From: Benjamin Poulain Date: Thu, 8 Jul 2010 10:49:31 +0200 Subject: The forward declaration should have been in the namespace for QImageData Reviewed-by: Olivier Goffart --- src/gui/image/qimage_p.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h index da535aa..c687448 100644 --- a/src/gui/image/qimage_p.h +++ b/src/gui/image/qimage_p.h @@ -61,10 +61,10 @@ #include #endif -class QImageWriter; - QT_BEGIN_NAMESPACE +class QImageWriter; + struct Q_GUI_EXPORT QImageData { // internal image data QImageData(); ~QImageData(); -- cgit v0.12 From 9f0d39135141e9f048d4cb3647a9e50f3d3db5a1 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 7 Jul 2010 17:55:04 +0200 Subject: Set QThreads to be process critical automatically on Symbian OS On Symbian OS, a thread is non critical by default - this means if it crashes the process does not automatically terminate, rather it is allowed to handle the crash by itself. Only the main thread is critical by default. Since this is not the behaviour on other platforms, application developers are unlikely to have considered this case - and would need to write symbian specific code to catch the crash. For such advanced users, they can reset the critical flag on the thread once they get control in QThread::run(). By default, a crash in any thread created via the QThread API will now crash the process. Reviewed-by: Iain --- src/corelib/thread/qthread_unix.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 6b34b5f..d193b2e 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -247,6 +247,14 @@ void *QThreadPrivate::start(void *arg) data->symbian_thread_handle = RThread(); TThreadId threadId = data->symbian_thread_handle.Id(); data->symbian_thread_handle.Open(threadId); + // On symbian, threads other than the main thread are non critical by default + // This means a worker thread can crash without crashing the application - to + // use this feature, we would need to use RThread::Logon in the main thread + // to catch abnormal thread exit and emit the finished signal. + // For the sake of cross platform consistency, we set the thread as process critical + // - advanced users who want the symbian behaviour can change the critical + // attribute of the thread again once the app gains control in run() + User::SetCritical(User::EProcessCritical); #endif pthread_once(¤t_thread_data_once, create_current_thread_data_key); -- cgit v0.12 From 4f8ec542b123399574d2e509fa99f4bd66a34e25 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 8 Jul 2010 11:42:59 +0200 Subject: Add exception barrier to QCertificateRetriever::RunL() This translates stl exceptions into Symbian OS Leaves, to prevent an assertion failure in the active scheduler. Reviewed-by: mread --- src/network/ssl/qsslsocket_openssl.cpp | 11 ++++++++--- src/network/ssl/qsslsocket_openssl_p.h | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index d7088ee..1d794ae 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -199,7 +199,7 @@ QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(SSL_CIPHER *ciph ciph.d->protocol = QSsl::SslV2; else if (protoString == QLatin1String("TLSv1")) ciph.d->protocol = QSsl::TlsV1; - + if (descriptionList.at(2).startsWith(QLatin1String("Kx="))) ciph.d->keyExchangeMethod = descriptionList.at(2).mid(3); if (descriptionList.at(3).startsWith(QLatin1String("Au="))) @@ -367,7 +367,7 @@ init_context: // Set verification depth. if (configuration.peerVerifyDepth != 0) q_SSL_CTX_set_verify_depth(ctx, configuration.peerVerifyDepth); - + // Create and initialize SSL session if (!(ssl = q_SSL_new(ctx))) { // ### Bad error code @@ -616,6 +616,11 @@ void QCertificateRetriever::retrieveNextCertificate() void QCertificateRetriever::RunL() { + QT_TRYCATCH_LEAVING(run()); +} + +void QCertificateRetriever::run() +{ switch (state) { case Initializing: list(); @@ -818,7 +823,7 @@ void QSslSocketBackendPrivate::transmit() bool transmitting; do { transmitting = false; - + // If the connection is secure, we can transfer data from the write // buffer (in plain text) to the write BIO through SSL_write. if (connectionEncrypted && !writeBuffer.isEmpty()) { diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h index e41320d..987dfae 100644 --- a/src/network/ssl/qsslsocket_openssl_p.h +++ b/src/network/ssl/qsslsocket_openssl_p.h @@ -161,6 +161,7 @@ private: virtual void RunL(); virtual void DoCancel(); + void run(); void list(); void retrieveNextCertificate(); -- cgit v0.12 From 6d5655089fa4e2231a1a8edc98ecbb6b29e344e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 5 Jul 2010 17:38:51 +0200 Subject: Add three new style-hints to QFont to match CSS' generic font families The defaults were chosen to match major web browsers. See: http://xhva.net/log/?p=160 Reviewed-by: Simon Hausmann --- src/gui/text/qfont.cpp | 9 +++++++++ src/gui/text/qfont.h | 5 ++++- src/gui/text/qfont_mac.cpp | 6 ++++++ src/gui/text/qfont_qws.cpp | 1 + src/gui/text/qfont_win.cpp | 5 +++++ src/gui/text/qfont_x11.cpp | 9 +++++++++ 6 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index c229242..3fe98e1 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -1266,6 +1266,15 @@ QFont::StyleHint QFont::styleHint() const \value OldEnglish the font matcher prefers decorative fonts. \value Decorative is a synonym for \c OldEnglish. + \value Monospace the font matcher prefers fonts that map to the + CSS generic font-family 'monospace'. + + \value Fantasy the font matcher prefers fonts that map to the + CSS generic font-family 'fantasy'. + + \value Cursive the font matcher prefers fonts that map to the + CSS generic font-family 'cursive'. + \value System the font matcher prefers system fonts. */ diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h index 6f62424..2cc41e1 100644 --- a/src/gui/text/qfont.h +++ b/src/gui/text/qfont.h @@ -72,7 +72,10 @@ public: Courier, TypeWriter = Courier, OldEnglish, Decorative = OldEnglish, System, - AnyStyle + AnyStyle, + Cursive, + Monospace, + Fantasy }; enum StyleStrategy { diff --git a/src/gui/text/qfont_mac.cpp b/src/gui/text/qfont_mac.cpp index 93985ab..0bc8ca2 100644 --- a/src/gui/text/qfont_mac.cpp +++ b/src/gui/text/qfont_mac.cpp @@ -136,8 +136,14 @@ QString QFont::defaultFamily() const return QString::fromLatin1("Times New Roman"); case QFont::Courier: return QString::fromLatin1("Courier New"); + case QFont::Monospace: + return QString::fromLatin1("Courier"); case QFont::Decorative: return QString::fromLatin1("Bookman Old Style"); + case QFont::Cursive: + return QString::fromLatin1("Apple Chancery"); + case QFont::Fantasy: + return QString::fromLatin1("Papyrus"); case QFont::Helvetica: case QFont::System: default: diff --git a/src/gui/text/qfont_qws.cpp b/src/gui/text/qfont_qws.cpp index 51af1e1..72f8c37 100644 --- a/src/gui/text/qfont_qws.cpp +++ b/src/gui/text/qfont_qws.cpp @@ -108,6 +108,7 @@ QString QFont::defaultFamily() const case QFont::Times: return QString::fromLatin1("times"); case QFont::Courier: + case QFont::Monospace: return QString::fromLatin1("courier"); case QFont::Decorative: return QString::fromLatin1("old english"); diff --git a/src/gui/text/qfont_win.cpp b/src/gui/text/qfont_win.cpp index a9610f7..fa45ae1 100644 --- a/src/gui/text/qfont_win.cpp +++ b/src/gui/text/qfont_win.cpp @@ -148,9 +148,14 @@ QString QFont::defaultFamily() const case QFont::Times: return QString::fromLatin1("Times New Roman"); case QFont::Courier: + case QFont::Monospace: return QString::fromLatin1("Courier New"); case QFont::Decorative: return QString::fromLatin1("Bookman Old Style"); + case QFont::Cursive: + return QString::fromLatin1("Comic Sans MS"); + case QFont::Fantasy: + return QString::fromLatin1("Impact"); case QFont::Helvetica: return QString::fromLatin1("Arial"); case QFont::System: diff --git a/src/gui/text/qfont_x11.cpp b/src/gui/text/qfont_x11.cpp index 39127dc..92e2326 100644 --- a/src/gui/text/qfont_x11.cpp +++ b/src/gui/text/qfont_x11.cpp @@ -281,6 +281,15 @@ QString QFont::defaultFamily() const case QFont::Courier: return QString::fromLatin1("Courier"); + case QFont::Monospace: + return QString::fromLatin1("Courier New"); + + case QFont::Cursive: + return QString::fromLatin1("Comic Sans MS"); + + case QFont::Fantasy: + return QString::fromLatin1("Impact"); + case QFont::Decorative: return QString::fromLatin1("Old English"); -- cgit v0.12 From 2ab84f72671013380d397afe2bb407823446516c Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Thu, 8 Jul 2010 10:43:50 +0200 Subject: Fix subfocus when reparenting panels. When reparenting an item into another, QGraphicsItem will fix the subfocus chain by first removing subfocus from the previous ancestors, and then optionally restoring the subfocus chain to the new ancestors of the reparented item. This allows item trees to be created and assigned a specific focus item before even added to a scene. The QGraphicsItemPrivate::setSubFocus function did not take into account that the root item might be in a different panel than the reparented item, which is the case when reparenting one panel into another. If so, setSubFocus must not mess up the new ancestor panel's sub focus chain. Otherwise (former behavior), the new ancestor panel's focusItem will point to the reparented panel's focus item. This in turn breaks an invariant; one panel's focusItem can never point to an item in another panel. The bundled test case shows this point: Create two panels that each have one child that sets focus. The first panel is added to the scene just to prepare, and verify that it's activated as expected, and its focus child immediately gains input focus. Then we create a second panel, which also has a focus child (but it doesn't have focus as its panel is not active). When we reparent the new panel onto the old one, we expect the new panel to be activated, and the child focus item to gain input focus. However, we also expect the parent panel's focus item to remain intact, so that when we hide the child panel, and the parent panel is reactivated, its original focus item regains focus. Former behavior was that the parent's focus item still pointed to the child panel focus item. This change only has effect when reparenting to or from a panel. Merge-request: 735 Reviewed-by: Yoann Lopes --- src/gui/graphicsview/qgraphicsitem.cpp | 3 ++ tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 49 ++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 51dc543..848de2c 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -5510,6 +5510,9 @@ void QGraphicsItemPrivate::setSubFocus(QGraphicsItem *rootItem) // Update focus child chain. Stop at panels, or if this item // is hidden, stop at the first item with a visible parent. QGraphicsItem *parent = rootItem ? rootItem : q_ptr; + if (parent->panel() != q_ptr->panel()) + return; + do { // Clear any existing ancestor's subFocusItem. if (parent != q_ptr && parent->d_ptr->subFocusItem) { diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 31a6845..1ae3ecf 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -422,6 +422,7 @@ private slots: void setGraphicsEffect(); void panel(); void addPanelToActiveScene(); + void panelWithFocusItem(); void activate(); void setActivePanelOnInactiveScene(); void activationOnShowHide(); @@ -8416,6 +8417,54 @@ void tst_QGraphicsItem::panel() QVERIFY(!panel1->isActive()); } +void tst_QGraphicsItem::panelWithFocusItem() +{ + QGraphicsScene scene; + QEvent activate(QEvent::WindowActivate); + QApplication::sendEvent(&scene, &activate); + + QGraphicsRectItem *parentPanel = new QGraphicsRectItem; + QGraphicsRectItem *parentPanelFocusItem = new QGraphicsRectItem(parentPanel); + parentPanel->setFlag(QGraphicsItem::ItemIsPanel); + parentPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable); + parentPanelFocusItem->setFocus(); + scene.addItem(parentPanel); + + QVERIFY(parentPanel->isActive()); + QVERIFY(parentPanelFocusItem->hasFocus()); + QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem); + QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem); + + QGraphicsRectItem *childPanel = new QGraphicsRectItem; + QGraphicsRectItem *childPanelFocusItem = new QGraphicsRectItem(childPanel); + childPanel->setFlag(QGraphicsItem::ItemIsPanel); + childPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable); + childPanelFocusItem->setFocus(); + + QVERIFY(!childPanelFocusItem->hasFocus()); + QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)childPanelFocusItem); + QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)childPanelFocusItem); + + childPanel->setParentItem(parentPanel); + + QVERIFY(!parentPanel->isActive()); + QVERIFY(!parentPanelFocusItem->hasFocus()); + QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem); + QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem); + + QVERIFY(childPanel->isActive()); + QVERIFY(childPanelFocusItem->hasFocus()); + QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)childPanelFocusItem); + QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)childPanelFocusItem); + + childPanel->hide(); + + QVERIFY(parentPanel->isActive()); + QVERIFY(parentPanelFocusItem->hasFocus()); + QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem); + QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem); +} + void tst_QGraphicsItem::addPanelToActiveScene() { QGraphicsScene scene; -- cgit v0.12 From 627d62c17b29cf5a99252aeff965b4f848d4d171 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 8 Jul 2010 13:40:29 +0200 Subject: Merge tools/runonphone/symbianutils from qtcreator src/shared/symbianutils commit bca434a706c6eb28fe713ea10c857c35e3835f62 Author: Friedemann Kleint Date: Wed Jul 7 14:00:54 2010 +0200 Trk/Launcher: Add infrastructure for reporting crashes. currently used for runonphone only. Initial-patch-by: Shane Kearns commit 9bb67101c5daa42f879f2fcf884277c5fd23bed4 Author: Friedemann Kleint Date: Mon Jul 5 17:14:45 2010 +0200 Trk[TCF]: Proper exit handling commit 52b33a7503866654077b572c1f8005dfc19ed5a6 Author: Friedemann Kleint Date: Wed Jun 30 17:14:57 2010 +0200 Debugger[Trk]: Prepare thread handling. Store threads and cache registers per thread in Snapshot. As Trk does not generate Thread creation/deletion events. try to add threads on the fly if a stop in a new thread id is reported. Remove them in continue. Continue all threads in classic Trk. Pass on state (crash reason) to ThreadData and model. Factor out common code of both adapters to Snapshot/Symbian classes. commit 66e01e881d7cb865338a6a7949f9a085883387c9 Author: Friedemann Kleint Date: Mon Jun 28 16:32:53 2010 +0200 Debugger[TCF-Trk]: Send RemoveExecutables command. commit beba423a16fd0e6e836cd8c26ca30e5167ca56db Author: Friedemann Kleint Date: Fri Jun 25 15:06:30 2010 +0200 Debugger[Trk]: Added TCF experimental adapter. Added adapter to work with TCF over WLAN. Factor out common code for Symbian from TrkAdapter. Improve message logging in TrkGdbAdapter, some cleanup. Added new TcfTrkGdbAdapter based on TcfTrkDevice in symbianutils based on JSON, using QTcpSocket. To be started via special @tcf@ argument. Rubber-stamped-by: hjk create mode 100644 src/shared/symbianutils/json.cpp create mode 100644 src/shared/symbianutils/json.h create mode 100644 src/shared/symbianutils/tcftrkdevice.cpp create mode 100644 src/shared/symbianutils/tcftrkdevice.h create mode 100644 src/shared/symbianutils/tcftrkmessage.cpp create mode 100644 src/shared/symbianutils/tcftrkmessage.h commit 5d5f647f3d9b7a28c605af41a23819b7a24a5814 Author: Tobias Hunger Date: Thu Jun 10 13:12:12 2010 +0200 Fix preprocessor directives * The standard says all preprocessor directives have to start at column 0. commit 6972715a397e8e9a495191a459dcf6db4b75f7a7 Author: Robert Loehning Date: Mon Jun 7 14:58:24 2010 +0200 Symbian/trk: Fixed handling of partial frames Initial-patch-by: Shane Kearns commit a47e06eec946dd2dbb986e614a3c292b91182b95 Author: Robert Loehning Date: Mon Jun 7 14:47:40 2010 +0200 Symbian/trk: Don't try to dereference references commit b6ee94fb5ff652ba22b272a064c2be541b4bcf56 Author: Robert Loehning Date: Mon Jun 7 11:50:38 2010 +0200 Symbian/Trk: Don't try to download a file without respective flag set. Task-number: QTCREATORBUG-1567 Reviewed-by: Friedemann Kleint --- tools/runonphone/symbianutils/json.cpp | 478 ++++++++++++ tools/runonphone/symbianutils/json.h | 137 ++++ tools/runonphone/symbianutils/launcher.cpp | 180 ++++- tools/runonphone/symbianutils/launcher.h | 12 + tools/runonphone/symbianutils/symbianutils.pri | 12 +- tools/runonphone/symbianutils/tcftrkdevice.cpp | 917 ++++++++++++++++++++++++ tools/runonphone/symbianutils/tcftrkdevice.h | 283 ++++++++ tools/runonphone/symbianutils/tcftrkmessage.cpp | 550 ++++++++++++++ tools/runonphone/symbianutils/tcftrkmessage.h | 284 ++++++++ tools/runonphone/symbianutils/trkdevice.cpp | 5 +- tools/runonphone/symbianutils/trkutils.cpp | 143 +++- tools/runonphone/symbianutils/trkutils.h | 31 +- tools/runonphone/symbianutils/trkutils_p.h | 2 +- 13 files changed, 2980 insertions(+), 54 deletions(-) create mode 100644 tools/runonphone/symbianutils/json.cpp create mode 100644 tools/runonphone/symbianutils/json.h create mode 100644 tools/runonphone/symbianutils/tcftrkdevice.cpp create mode 100644 tools/runonphone/symbianutils/tcftrkdevice.h create mode 100644 tools/runonphone/symbianutils/tcftrkmessage.cpp create mode 100644 tools/runonphone/symbianutils/tcftrkmessage.h diff --git a/tools/runonphone/symbianutils/json.cpp b/tools/runonphone/symbianutils/json.cpp new file mode 100644 index 0000000..4171125 --- /dev/null +++ b/tools/runonphone/symbianutils/json.cpp @@ -0,0 +1,478 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "json.h" + +#ifdef TODO_USE_CREATOR +#include +#endif // TODO_USE_CREATOR + +#include +#include +#include +#include + +#include + +//#define DEBUG_JASON +#ifdef DEBUG_JASON +#define JDEBUG(s) qDebug() << s +#else +#define JDEBUG(s) +#endif + +namespace tcftrk { + +static void skipSpaces(const char *&from, const char *to) +{ + while (from != to && isspace(*from)) + ++from; +} + +QTextStream &operator<<(QTextStream &os, const JsonValue &mi) +{ + return os << mi.toString(); +} + +void JsonValue::parsePair(const char *&from, const char *to) +{ + skipSpaces(from, to); + JDEBUG("parsePair: " << QByteArray(from, to - from)); + m_name = parseCString(from, to); + skipSpaces(from, to); + while (from < to && *from != ':') { + JDEBUG("not a colon" << *from); + ++from; + } + ++from; + parseValue(from, to); + skipSpaces(from, to); +} + +QByteArray JsonValue::parseNumber(const char *&from, const char *to) +{ + QByteArray result; + if (from < to && *from == '-') // Leading '-'. + result.append(*from++); + while (from < to && *from >= '0' && *from <= '9') + result.append(*from++); + return result; +} + +QByteArray JsonValue::parseCString(const char *&from, const char *to) +{ + QByteArray result; + JDEBUG("parseCString: " << QByteArray(from, to - from)); + if (*from != '"') { + qDebug() << "JSON Parse Error, double quote expected"; + ++from; // So we don't hang + return QByteArray(); + } + const char *ptr = from; + ++ptr; + while (ptr < to) { + if (*ptr == '"') { + ++ptr; + result = QByteArray(from + 1, ptr - from - 2); + break; + } + if (*ptr == '\\') { + ++ptr; + if (ptr == to) { + qDebug() << "JSON Parse Error, unterminated backslash escape"; + from = ptr; // So we don't hang + return QByteArray(); + } + } + ++ptr; + } + from = ptr; + + int idx = result.indexOf('\\'); + if (idx >= 0) { + char *dst = result.data() + idx; + const char *src = dst + 1, *end = result.data() + result.length(); + do { + char c = *src++; + switch (c) { + case 'a': *dst++ = '\a'; break; + case 'b': *dst++ = '\b'; break; + case 'f': *dst++ = '\f'; break; + case 'n': *dst++ = '\n'; break; + case 'r': *dst++ = '\r'; break; + case 't': *dst++ = '\t'; break; + case 'v': *dst++ = '\v'; break; + case '"': *dst++ = '"'; break; + case '\\': *dst++ = '\\'; break; + default: + { + int chars = 0; + uchar prod = 0; + forever { + if (c < '0' || c > '7') { + --src; + break; + } + prod = prod * 8 + c - '0'; + if (++chars == 3 || src == end) + break; + c = *src++; + } + if (!chars) { + qDebug() << "JSON Parse Error, unrecognized backslash escape"; + return QByteArray(); + } + *dst++ = prod; + } + } + while (src != end) { + char c = *src++; + if (c == '\\') + break; + *dst++ = c; + } + } while (src != end); + *dst = 0; + result.truncate(dst - result.data()); + } + + JDEBUG("parseCString, got " << result); + return result; +} + + + +void JsonValue::parseValue(const char *&from, const char *to) +{ + JDEBUG("parseValue: " << QByteArray(from, to - from)); + switch (*from) { + case '{': + parseObject(from, to); + break; + case 't': + if (to - from >= 4 && qstrncmp(from, "true", 4) == 0) { + m_data = QByteArray(from, 4); + from += m_data.size(); + m_type = Boolean; + } + break; + case 'f': + if (to - from >= 5 && qstrncmp(from, "false", 5) == 0) { + m_data = QByteArray(from, 5); + from += m_data.size(); + m_type = Boolean; + } + break; + case 'n': + if (to - from >= 4 && qstrncmp(from, "null", 4) == 0) { + m_data = QByteArray(from, 4); + from += m_data.size(); + m_type = NullObject; + } + break; + case '[': + parseArray(from, to); + break; + case '"': + m_type = String; + m_data = parseCString(from, to); + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case '-': + m_type = Number; + m_data = parseNumber(from, to); + default: + break; + } +} + +void JsonValue::parseObject(const char *&from, const char *to) +{ + JDEBUG("parseObject: " << QByteArray(from, to - from)); +#ifdef TODO_USE_CREATOR + QTC_ASSERT(*from == '{', /**/); +#endif + ++from; + m_type = Object; + while (from < to) { + if (*from == '}') { + ++from; + break; + } + JsonValue child; + child.parsePair(from, to); + if (!child.isValid()) + return; + m_children += child; + if (*from == ',') + ++from; + } +} + +void JsonValue::parseArray(const char *&from, const char *to) +{ + JDEBUG("parseArray: " << QByteArray(from, to - from)); +#ifdef TODO_USE_CREATOR + QTC_ASSERT(*from == '[', /**/); +#endif + ++from; + m_type = Array; + while (from < to) { + if (*from == ']') { + ++from; + break; + } + JsonValue child; + child.parseValue(from, to); + if (child.isValid()) + m_children += child; + if (*from == ',') + ++from; + } +} + +void JsonValue::setStreamOutput(const QByteArray &name, const QByteArray &content) +{ + if (content.isEmpty()) + return; + JsonValue child; + child.m_type = String; + child.m_name = name; + child.m_data = content; + m_children += child; + if (m_type == Invalid) + m_type = Object; +} + +static QByteArray ind(int indent) +{ + return QByteArray(2 * indent, ' '); +} + +void JsonValue::dumpChildren(QByteArray * str, bool multiline, int indent) const +{ + for (int i = 0; i < m_children.size(); ++i) { + if (i != 0) { + *str += ','; + if (multiline) + *str += '\n'; + } + if (multiline) + *str += ind(indent); + *str += m_children.at(i).toString(multiline, indent); + } +} + +class MyString : public QString { +public: + ushort at(int i) const { return constData()[i].unicode(); } +}; + +template +inline ST escapeCStringTpl(const ST &ba) +{ + ST ret; + ret.reserve(ba.length() * 2); + for (int i = 0; i < ba.length(); ++i) { + CT c = ba.at(i); + switch (c) { + case '\\': ret += "\\\\"; break; + case '\a': ret += "\\a"; break; + case '\b': ret += "\\b"; break; + case '\f': ret += "\\f"; break; + case '\n': ret += "\\n"; break; + case '\r': ret += "\\r"; break; + case '\t': ret += "\\t"; break; + case '\v': ret += "\\v"; break; + case '"': ret += "\\\""; break; + default: + if (c < 32 || c == 127) { + ret += '\\'; + ret += '0' + (c >> 6); + ret += '0' + ((c >> 3) & 7); + ret += '0' + (c & 7); + } else { + ret += c; + } + } + } + return ret; +} + +QString JsonValue::escapeCString(const QString &ba) +{ + return escapeCStringTpl(static_cast(ba)); +} + +QByteArray JsonValue::escapeCString(const QByteArray &ba) +{ + return escapeCStringTpl(ba); +} + +QByteArray JsonValue::toString(bool multiline, int indent) const +{ + QByteArray result; + switch (m_type) { + case Invalid: + if (multiline) + result += ind(indent) + "Invalid\n"; + else + result += "Invalid"; + break; + case String: + if (!m_name.isEmpty()) + result += m_name + "="; + result += '"' + escapeCString(m_data) + '"'; + break; + case Number: + if (!m_name.isEmpty()) + result += '"' + m_name + "\":"; + result += m_data; + break; + case Boolean: + case NullObject: + if (!m_name.isEmpty()) + result += '"' + m_name + "\":"; + result += m_data; + break; + case Object: + if (!m_name.isEmpty()) + result += m_name + '='; + if (multiline) { + result += "{\n"; + dumpChildren(&result, multiline, indent + 1); + result += '\n' + ind(indent) + "}"; + } else { + result += "{"; + dumpChildren(&result, multiline, indent + 1); + result += "}"; + } + break; + case Array: + if (!m_name.isEmpty()) + result += m_name + "="; + if (multiline) { + result += "[\n"; + dumpChildren(&result, multiline, indent + 1); + result += '\n' + ind(indent) + "]"; + } else { + result += "["; + dumpChildren(&result, multiline, indent + 1); + result += "]"; + } + break; + } + return result; +} + +void JsonValue::fromString(const QByteArray &ba) +{ + const char *from = ba.constBegin(); + const char *to = ba.constEnd(); + parseValue(from, to); +} + +JsonValue JsonValue::findChild(const char *name) const +{ + for (int i = 0; i < m_children.size(); ++i) + if (m_children.at(i).m_name == name) + return m_children.at(i); + return JsonValue(); +} + +void JsonInputStream::appendCString(const char *s) +{ + m_target.append('"'); + for (const char *p = s; *p; p++) { + if (*p == '"' || *p == '\\') + m_target.append('\\'); + m_target.append(*p); + } + m_target.append('"'); +} + +void JsonInputStream::appendString(const QString &in) +{ + if (in.isEmpty()) { + m_target.append("\"\""); + return; + } + + const QChar doubleQuote('"'); + const QChar backSlash('\\'); + QString rc; + const int inSize = in.size(); + rc.reserve(in.size() + 5); + rc.append(doubleQuote); + for (int i = 0; i < inSize; i++) { + const QChar c = in.at(i); + if (c == doubleQuote || c == backSlash) + rc.append(backSlash); + rc.append(c); + } + rc.append(doubleQuote); + m_target.append(rc.toUtf8()); + return; +} + +JsonInputStream &JsonInputStream::operator<<(const QStringList &in) +{ + m_target.append('['); + const int count = in.size(); + for (int i = 0 ; i < count; i++) { + if (i) + m_target.append(','); + appendString(in.at(i)); + } + m_target.append(']'); + return *this; +} + +JsonInputStream &JsonInputStream::operator<<(const QVector &ba) +{ + m_target.append('['); + const int count = ba.size(); + for (int i = 0 ; i < count; i++) { + if (i) + m_target.append(','); + appendCString(ba.at(i).constData()); + } + m_target.append(']'); + return *this; +} + +JsonInputStream &JsonInputStream::operator<<(bool b) +{ + m_target.append(b ? "true" : "false"); + return *this; +} + +} // namespace tcftrk + diff --git a/tools/runonphone/symbianutils/json.h b/tools/runonphone/symbianutils/json.h new file mode 100644 index 0000000..ef574bd --- /dev/null +++ b/tools/runonphone/symbianutils/json.h @@ -0,0 +1,137 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef SYMBIANUTILS_JSON_H +#define SYMBIANUTILS_JSON_H + +#include "symbianutils_global.h" + +#include +#include +#include + +namespace tcftrk { + +class SYMBIANUTILS_EXPORT JsonValue +{ +public: + JsonValue() : m_type(Invalid) {} + explicit JsonValue(const QByteArray &str) { fromString(str); } + + QByteArray m_name; + QByteArray m_data; + QList m_children; + + enum Type { + Invalid, + String, + Number, + Boolean, + Object, + NullObject, + Array, + }; + + Type m_type; + + inline Type type() const { return m_type; } + inline QByteArray name() const { return m_name; } + inline bool hasName(const char *name) const { return m_name == name; } + + inline bool isValid() const { return m_type != Invalid; } + inline bool isNumber() const { return m_type == Number; } + inline bool isString() const { return m_type == String; } + inline bool isObject() const { return m_type == Object; } + inline bool isArray() const { return m_type == Array; } + + + inline QByteArray data() const { return m_data; } + inline const QList &children() const { return m_children; } + inline int childCount() const { return m_children.size(); } + + const JsonValue &childAt(int index) const { return m_children[index]; } + JsonValue &childAt(int index) { return m_children[index]; } + JsonValue findChild(const char *name) const; + + QByteArray toString(bool multiline = false, int indent = 0) const; + void fromString(const QByteArray &str); + void setStreamOutput(const QByteArray &name, const QByteArray &content); + +private: + static QByteArray parseCString(const char *&from, const char *to); + static QByteArray parseNumber(const char *&from, const char *to); + static QByteArray escapeCString(const QByteArray &ba); + static QString escapeCString(const QString &ba); + void parsePair(const char *&from, const char *to); + void parseValue(const char *&from, const char *to); + void parseObject(const char *&from, const char *to); + void parseArray(const char *&from, const char *to); + + void dumpChildren(QByteArray *str, bool multiline, int indent) const; +}; + +/* Thin wrapper around QByteArray for formatting JSON input. Use as in: + * JsonInputStream(byteArray) << '{' << "bla" << ':' << "blup" << '}'; + * Note that strings get double quotes and JSON-escaping, characters should be + * used for the array/hash delimiters. + * */ +class SYMBIANUTILS_EXPORT JsonInputStream { +public: + explicit JsonInputStream(QByteArray &a) : m_target(a) {} + + JsonInputStream &operator<<(char c) { m_target.append(c); return *this; } + JsonInputStream &operator<<(const char *c) { appendCString(c); return *this; } + JsonInputStream &operator<<(const QByteArray &a) { appendCString(a.constData()); return *this; } + JsonInputStream &operator<<(const QString &c) { appendString(c); return *this; } + + // Format as array + JsonInputStream &operator<<(const QStringList &c); + + // Format as array + JsonInputStream &operator<<(const QVector &ba); + + JsonInputStream &operator<<(bool b); + + JsonInputStream &operator<<(int i) + { m_target.append(QByteArray::number(i)); return *this; } + JsonInputStream &operator<<(unsigned i) + { m_target.append(QByteArray::number(i)); return *this; } + JsonInputStream &operator<<(quint64 i) + { m_target.append(QByteArray::number(i)); return *this; } + +private: + void appendString(const QString &); + void appendCString(const char *c); + + QByteArray &m_target; +}; + +} // namespace tcftrk + +#endif // SYMBIANUTILS_JSON_H diff --git a/tools/runonphone/symbianutils/launcher.cpp b/tools/runonphone/symbianutils/launcher.cpp index ecb067e..ee87480 100644 --- a/tools/runonphone/symbianutils/launcher.cpp +++ b/tools/runonphone/symbianutils/launcher.cpp @@ -58,6 +58,33 @@ namespace trk { +struct CrashReportState { + CrashReportState(); + void clear(); + + typedef uint Thread; + typedef QList Threads; + Threads threads; + + QList registers; + QByteArray stack; + uint sp; + uint fetchingStackPID; + uint fetchingStackTID; +}; + +CrashReportState::CrashReportState() +{ + clear(); +} + +void CrashReportState::clear() +{ + threads.clear(); + stack.clear(); + sp = fetchingStackPID = fetchingStackTID = 0; +} + struct LauncherPrivate { struct CopyState { QString sourceFileName; @@ -86,6 +113,7 @@ struct LauncherPrivate { int m_verbose; Launcher::Actions m_startupActions; bool m_closeDevice; + CrashReportState m_crashReportState; }; LauncherPrivate::LauncherPrivate(const TrkDevicePtr &d) : @@ -202,6 +230,7 @@ void Launcher::setCloseDevice(bool c) bool Launcher::startServer(QString *errorMessage) { errorMessage->clear(); + d->m_crashReportState.clear(); if (d->m_verbose) { QString msg; QTextStream str(&msg); @@ -375,7 +404,7 @@ void Launcher::handleResult(const TrkResult &result) logMessage("TEXT TRACE: " + msg); } } else { - logMessage("APPLICATION OUTPUT: " + result.data); + logMessage("APPLICATION OUTPUT: " + stringFromArray(result.data)); msg = result.data; } msg.replace("\r\n", "\n"); @@ -416,49 +445,54 @@ void Launcher::handleResult(const TrkResult &result) // target->host OS notification case TrkNotifyCreated: { // Notify Created - /* - const char *data = result.data.data(); - byte error = result.data.at(0); - byte type = result.data.at(1); // type: 1 byte; for dll item, this value is 2. - uint pid = extractInt(data + 2); // ProcessID: 4 bytes; - uint tid = extractInt(data + 6); //threadID: 4 bytes - uint codeseg = extractInt(data + 10); //code address: 4 bytes; code base address for the library - uint dataseg = extractInt(data + 14); //data address: 4 bytes; data base address for the library - uint len = extractShort(data + 18); //length: 2 bytes; length of the library name string to follow - QByteArray name = result.data.mid(20, len); // name: library name - - logMessage(prefix + "NOTE: LIBRARY LOAD: " + str); - logMessage(prefix + "TOKEN: " + result.token); - logMessage(prefix + "ERROR: " + int(error)); - logMessage(prefix + "TYPE: " + int(type)); - logMessage(prefix + "PID: " + pid); - logMessage(prefix + "TID: " + tid); - logMessage(prefix + "CODE: " + codeseg); - logMessage(prefix + "DATA: " + dataseg); - logMessage(prefix + "LEN: " + len); - logMessage(prefix + "NAME: " + name); - */ if (result.data.size() < 10) break; + const char *data = result.data.constData(); + const byte error = result.data.at(0); + Q_UNUSED(error) + const byte type = result.data.at(1); // type: 1 byte; for dll item, this value is 2. + const uint tid = extractInt(data + 6); //threadID: 4 bytes + Q_UNUSED(tid) + if (type == kDSOSDLLItem && result.data.size() >=20) { + const Library lib = Library(result); + d->m_session.libraries.push_back(lib); + emit libraryLoaded(lib); + } QByteArray ba; ba.append(result.data.mid(2, 8)); d->m_device->sendTrkMessage(TrkContinue, TrkCallback(), ba, "CONTINUE"); - //d->m_device->sendTrkAck(result.token) break; } case TrkNotifyDeleted: { // NotifyDeleted const ushort itemType = (unsigned char)result.data.at(1); - const ushort len = result.data.size() > 12 ? extractShort(result.data.data() + 10) : ushort(0); + const uint pid = result.data.size() >= 6 ? extractShort(result.data.constData() + 2) : 0; + const uint tid = result.data.size() >= 10 ? extractShort(result.data.constData() + 6) : 0; + Q_UNUSED(tid) + const ushort len = result.data.size() > 12 ? extractShort(result.data.constData() + 10) : ushort(0); const QString name = len ? QString::fromAscii(result.data.mid(12, len)) : QString(); logMessage(QString::fromLatin1("%1 %2 UNLOAD: %3"). arg(QString::fromAscii(prefix)).arg(itemType ? QLatin1String("LIB") : QLatin1String("PROCESS")). arg(name)); d->m_device->sendTrkAck(result.token); - if (itemType == 0 // process + if (itemType == kDSOSProcessItem // process && result.data.size() >= 10 && d->m_session.pid == extractInt(result.data.data() + 6)) { - copyFileFromRemote(); + if (d->m_startupActions & ActionDownload) + copyFileFromRemote(); + else + disconnectTrk(); + } + else if (itemType == kDSOSDLLItem && len) { + // Remove libraries of process. + for (QList::iterator it = d->m_session.libraries.begin(); it != d->m_session.libraries.end(); ) { + if ((*it).pid == pid && (*it).name == name) { + emit libraryUnloaded(*it); + it = d->m_session.libraries.erase(it); + } else { + ++it; + } + } } break; } @@ -705,6 +739,15 @@ void Launcher::handleCreateProcess(const TrkResult &result) logMessage(msg); } emit applicationRunning(d->m_session.pid); + //create a "library" entry for the executable which launched the process + Library lib; + lib.pid = d->m_session.pid; + lib.codeseg = d->m_session.codeseg; + lib.dataseg = d->m_session.dataseg; + lib.name = d->m_fileName.toUtf8(); + d->m_session.libraries << lib; + emit libraryLoaded(lib); + QByteArray ba; appendInt(&ba, d->m_session.pid); appendInt(&ba, d->m_session.tid); @@ -856,6 +899,30 @@ QByteArray Launcher::startProcessMessage(const QString &executable, return ba; } +QByteArray Launcher::readMemoryMessage(uint pid, uint tid, uint from, uint len) +{ + QByteArray ba; + ba.reserve(11); + ba.append(char(0x8)); // Options, FIXME: why? + appendShort(&ba, len); + appendInt(&ba, from); + appendInt(&ba, pid); + appendInt(&ba, tid); + return ba; +} + +QByteArray Launcher::readRegistersMessage(uint pid, uint tid) +{ + QByteArray ba; + ba.reserve(15); + ba.append(char(0)); // Register set, only 0 supported + appendShort(&ba, 0); //R0 + appendShort(&ba, 16); // last register CPSR + appendInt(&ba, pid); + appendInt(&ba, tid); + return ba; +} + void Launcher::startInferiorIfNeeded() { emit startingApplication(); @@ -907,4 +974,63 @@ void Launcher::releaseToDeviceManager(Launcher *launcher) sdm->releaseDevice(launcher->trkServerName()); } +void Launcher::getRegistersAndCallStack(uint pid, uint tid) +{ + d->m_device->sendTrkMessage(TrkReadRegisters, + TrkCallback(this, &Launcher::handleReadRegisters), + Launcher::readRegistersMessage(pid, tid)); + d->m_crashReportState.fetchingStackPID = pid; + d->m_crashReportState.fetchingStackTID = tid; +} + +void Launcher::handleReadRegisters(const TrkResult &result) +{ + if(result.errorCode() || result.data.size() < (17*4)) { + terminate(); + return; + } + const char* data = result.data.constData() + 1; + d->m_crashReportState.registers.clear(); + d->m_crashReportState.stack.clear(); + for (int i=0;i<17;i++) { + uint r = extractInt(data); + data += 4; + d->m_crashReportState.registers.append(r); + } + d->m_crashReportState.sp = d->m_crashReportState.registers.at(13); + + const ushort len = 1024 - (d->m_crashReportState.sp % 1024); //read to 1k boundary first + const QByteArray ba = Launcher::readMemoryMessage(d->m_crashReportState.fetchingStackPID, + d->m_crashReportState.fetchingStackTID, + d->m_crashReportState.sp, + len); + d->m_device->sendTrkMessage(TrkReadMemory, TrkCallback(this, &Launcher::handleReadStack), ba); + d->m_crashReportState.sp += len; +} + +void Launcher::handleReadStack(const TrkResult &result) +{ + if (result.errorCode()) { + //error implies memory fault when reaching end of stack + emit registersAndCallStackReadComplete(d->m_crashReportState.registers, d->m_crashReportState.stack); + return; + } + + const uint len = extractShort(result.data.constData() + 1); + d->m_crashReportState.stack.append(result.data.mid(3, len)); + + if (d->m_crashReportState.sp - d->m_crashReportState.registers.at(13) > 0x10000) { + //read enough stack, stop here + emit registersAndCallStackReadComplete(d->m_crashReportState.registers, d->m_crashReportState.stack); + return; + } + //read 1k more + const QByteArray ba = Launcher::readMemoryMessage(d->m_crashReportState.fetchingStackPID, + d->m_crashReportState.fetchingStackTID, + d->m_crashReportState.sp, + 1024); + d->m_device->sendTrkMessage(TrkReadMemory, TrkCallback(this, &Launcher::handleReadStack), ba); + d->m_crashReportState.sp += 1024; +} + } // namespace trk diff --git a/tools/runonphone/symbianutils/launcher.h b/tools/runonphone/symbianutils/launcher.h index 6db69d0..230a122 100644 --- a/tools/runonphone/symbianutils/launcher.h +++ b/tools/runonphone/symbianutils/launcher.h @@ -43,6 +43,7 @@ #define LAUNCHER_H #include "trkdevice.h" +#include "trkutils.h" #include #include @@ -122,6 +123,9 @@ public: // Create Trk message to start a process. static QByteArray startProcessMessage(const QString &executable, const QStringList &arguments); + // Create Trk message to read memory + static QByteArray readMemoryMessage(uint pid, uint tid, uint from, uint len); + static QByteArray readRegistersMessage(uint pid, uint tid); // Parse a TrkNotifyStopped message static bool parseNotifyStopped(const QByteArray &a, uint *pid, uint *tid, uint *address, @@ -149,12 +153,18 @@ signals: void copyProgress(int percent); void stateChanged(int); void processStopped(uint pc, uint pid, uint tid, const QString& reason); + void processResumed(uint pid, uint tid); + void libraryLoaded(const trk::Library &lib); + void libraryUnloaded(const trk::Library &lib); + void registersAndCallStackReadComplete(const QList& registers, const QByteArray& stack); // Emitted by the destructor, for releasing devices of SymbianDeviceManager by name void destroyed(const QString &serverName); public slots: void terminate(); void resumeProcess(uint pid, uint tid); + //can be used to obtain traceback after a breakpoint / exception + void getRegistersAndCallStack(uint pid, uint tid); private slots: void handleResult(const trk::TrkResult &data); @@ -182,6 +192,8 @@ private: void handleStop(const TrkResult &result); void handleSupportMask(const TrkResult &result); void handleTrkVersion(const TrkResult &result); + void handleReadRegisters(const TrkResult &result); + void handleReadStack(const TrkResult &result); void copyFileToRemote(); void copyFileFromRemote(); diff --git a/tools/runonphone/symbianutils/symbianutils.pri b/tools/runonphone/symbianutils/symbianutils.pri index 6309517..f07e494 100644 --- a/tools/runonphone/symbianutils/symbianutils.pri +++ b/tools/runonphone/symbianutils/symbianutils.pri @@ -1,5 +1,7 @@ INCLUDEPATH *= $$PWD +QT += network + # Input HEADERS += $$PWD/symbianutils_global.h \ $$PWD/callback.h \ @@ -9,14 +11,20 @@ HEADERS += $$PWD/symbianutils_global.h \ $$PWD/launcher.h \ $$PWD/bluetoothlistener.h \ $$PWD/communicationstarter.h \ - $$PWD/symbiandevicemanager.h + $$PWD/symbiandevicemanager.h \ + $$PWD/tcftrkdevice.h \ + $$PWD/tcftrkmessage.h \ + $$PWD/json.h SOURCES += $$PWD/trkutils.cpp \ $$PWD/trkdevice.cpp \ $$PWD/launcher.cpp \ $$PWD/bluetoothlistener.cpp \ $$PWD/communicationstarter.cpp \ - $$PWD/symbiandevicemanager.cpp + $$PWD/symbiandevicemanager.cpp \ + $$PWD/tcftrkdevice.cpp \ + $$PWD/tcftrkmessage.cpp \ + $$PWD/json.cpp # Tests/trklauncher is a console application contains(QT, gui) { diff --git a/tools/runonphone/symbianutils/tcftrkdevice.cpp b/tools/runonphone/symbianutils/tcftrkdevice.cpp new file mode 100644 index 0000000..723d5e9 --- /dev/null +++ b/tools/runonphone/symbianutils/tcftrkdevice.cpp @@ -0,0 +1,917 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "tcftrkdevice.h" +#include "json.h" + +#include +#include +#include +#include +#include +#include +#include + +enum { debug = 0 }; + +static const char messageTerminatorC[] = "\003\001"; + +namespace tcftrk { +// ------------- TcfTrkCommandError + +TcfTrkCommandError::TcfTrkCommandError() : timeMS(0), code(0), alternativeCode(0) +{ +} + +void TcfTrkCommandError::clear() +{ + timeMS = 0; + code = alternativeCode = 0; + format.clear(); + alternativeOrganization.clear(); +} + +void TcfTrkCommandError::write(QTextStream &str) const +{ + if (timeMS) { + const QDateTime time(QDate(1970, 1, 1)); + str << time.addMSecs(timeMS).toString(Qt::ISODate) << ": Error code: " << code + << " '" << format << '\''; + if (!alternativeOrganization.isEmpty()) + str << " ('" << alternativeOrganization << "', code: " << alternativeCode << ')'; + } else{ + str << ""; + } +} + +QString TcfTrkCommandError::toString() const +{ + QString rc; + QTextStream str(&rc); + write(str); + return rc; +} + +/* {"Time":1277459762255,"Code":1,"AltCode":-6,"AltOrg":"POSIX","Format":"Unknown error: -6"} */ +bool TcfTrkCommandError::parse(const QVector &values) +{ + // Parse an arbitrary hash (that could as well be a command response) + // and check for error elements. + unsigned errorKeyCount = 0; + clear(); + do { + if (values.isEmpty() || values.front().type() != JsonValue::Object) + break; + foreach (const JsonValue &c, values.front().children()) { + if (c.name() == "Time") { + timeMS = c.data().toULongLong(); + errorKeyCount++; + } else if (c.name() == "Code") { + code = c.data().toInt(); + errorKeyCount++; + } else if (c.name() == "Format") { + format = c.data(); + errorKeyCount++; + } else if (c.name() == "AltCode") { + alternativeCode = c.data().toInt(); + errorKeyCount++; + } else if (c.name() == "AltOrg") { + alternativeOrganization = c.data(); + errorKeyCount++; + } + } + } while (false); + const bool errorFound = errorKeyCount >= 2u; // Should be at least 'Time', 'Code'. + if (!errorFound) + clear(); + if (debug) { + qDebug() << "TcfTrkCommandError::parse: Found error: " << errorFound; + if (!values.isEmpty()) + qDebug() << values.front().toString(); + } + return errorFound; +} + +// ------------ TcfTrkCommandResult + +TcfTrkCommandResult::TcfTrkCommandResult(Type t) : + type(t), service(LocatorService) +{ +} + +TcfTrkCommandResult::TcfTrkCommandResult(char typeChar, Services s, + const QByteArray &r, + const QVector &v, + const QVariant &ck) : + type(FailReply), service(s), request(r), values(v), cookie(ck) +{ + switch (typeChar) { + case 'N': + type = FailReply; + break; + case 'P': + type = ProgressReply; + break; + case 'R': + type = commandError.parse(values) ? CommandErrorReply : SuccessReply; + break; + default: + qWarning("Unknown TCF reply type '%c'", typeChar); + } +} + +QString TcfTrkCommandResult::errorString() const +{ + QString rc; + QTextStream str(&rc); + + switch (type) { + case SuccessReply: + case ProgressReply: + str << ""; + return rc; + case FailReply: + str << "NAK"; + case CommandErrorReply: + commandError.write(str); + break; + } + // Append the failed command for reference + str << " (Command was: '"; + QByteArray printableRequest = request; + printableRequest.replace('\0', '|'); + str << printableRequest << "')"; + return rc; +} + +QString TcfTrkCommandResult::toString() const +{ + QString rc; + QTextStream str(&rc); + str << "Command answer "; + switch (type) { + case SuccessReply: + str << "[success]"; + break; + case CommandErrorReply: + str << "[command error]"; + break; + case FailReply: + str << "[fail (NAK)]"; + break; + case ProgressReply: + str << "[progress]"; + break; + } + str << ", " << values.size() << " values(s) to request: '"; + QByteArray printableRequest = request; + printableRequest.replace('\0', '|'); + str << printableRequest << "' "; + if (cookie.isValid()) + str << " cookie: " << cookie.toString(); + str << '\n'; + for (int i = 0, count = values.size(); i < count; i++) + str << '#' << i << ' ' << values.at(i).toString() << '\n'; + if (type == CommandErrorReply) + str << "Error: " << errorString(); + return rc; +} + +struct TcfTrkSendQueueEntry +{ + typedef TcfTrkDevice::MessageType MessageType; + + explicit TcfTrkSendQueueEntry(MessageType mt, + int tok, + Services s, + const QByteArray &d, + const TcfTrkCallback &cb= TcfTrkCallback(), + const QVariant &ck = QVariant()) : + messageType(mt), service(s), data(d), token(tok), cookie(ck), callback(cb) {} + + MessageType messageType; + Services service; + QByteArray data; + int token; + QVariant cookie; + TcfTrkCallback callback; +}; + +struct TcfTrkDevicePrivate { + typedef TcfTrkDevice::IODevicePtr IODevicePtr; + typedef QHash TokenWrittenMessageMap; + + TcfTrkDevicePrivate(); + + const QByteArray m_messageTerminator; + + IODevicePtr m_device; + unsigned m_verbose; + QByteArray m_readBuffer; + int m_token; + QQueue m_sendQueue; + TokenWrittenMessageMap m_writtenMessages; + QVector m_registerNames; +}; + +TcfTrkDevicePrivate::TcfTrkDevicePrivate() : + m_messageTerminator(messageTerminatorC), + m_verbose(0), m_token(0) +{ +} + +TcfTrkDevice::TcfTrkDevice(QObject *parent) : + QObject(parent), d(new TcfTrkDevicePrivate) +{ +} + +TcfTrkDevice::~TcfTrkDevice() +{ + delete d; +} + +QVector TcfTrkDevice::registerNames() const +{ + return d->m_registerNames; +} + +void TcfTrkDevice::setRegisterNames(const QVector& n) +{ + d->m_registerNames = n; + if (d->m_verbose) { + QString msg; + QTextStream str(&msg); + const int count = n.size(); + str << "Registers (" << count << "): "; + for (int i = 0; i < count; i++) + str << '#' << i << '=' << n.at(i) << ' '; + emitLogMessage(msg); + } +} + +TcfTrkDevice::IODevicePtr TcfTrkDevice::device() const +{ + return d->m_device; +} + +TcfTrkDevice::IODevicePtr TcfTrkDevice::takeDevice() +{ + const IODevicePtr old = d->m_device; + if (!old.isNull()) { + old.data()->disconnect(this); + d->m_device = IODevicePtr(); + } + d->m_readBuffer.clear(); + d->m_token = 0; + d->m_sendQueue.clear(); + return old; +} + +void TcfTrkDevice::setDevice(const IODevicePtr &dp) +{ + if (dp.data() == d->m_device.data()) + return; + if (dp.isNull()) { + emitLogMessage(QLatin1String("Internal error: Attempt to set NULL device.")); + return; + } + takeDevice(); + d->m_device = dp; + connect(dp.data(), SIGNAL(readyRead()), this, SLOT(slotDeviceReadyRead())); + if (QAbstractSocket *s = qobject_cast(dp.data())) { + connect(s, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(slotDeviceError())); + connect(s, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(slotDeviceSocketStateChanged())); + } +} + +void TcfTrkDevice::slotDeviceError() +{ + const QString message = d->m_device->errorString(); + emitLogMessage(message); + emit error(message); +} + +void TcfTrkDevice::slotDeviceSocketStateChanged() +{ + if (const QAbstractSocket *s = qobject_cast(d->m_device.data())) { + const QAbstractSocket::SocketState st = s->state(); + switch (st) { + case QAbstractSocket::UnconnectedState: + emitLogMessage(QLatin1String("Unconnected")); + break; + case QAbstractSocket::HostLookupState: + emitLogMessage(QLatin1String("HostLookupState")); + break; + case QAbstractSocket::ConnectingState: + emitLogMessage(QLatin1String("Connecting")); + break; + case QAbstractSocket::ConnectedState: + emitLogMessage(QLatin1String("Connected")); + break; + case QAbstractSocket::ClosingState: + emitLogMessage(QLatin1String("Closing")); + break; + default: + emitLogMessage(QString::fromLatin1("State %1").arg(st)); + break; + } + } +} + +static inline QString debugMessage(QByteArray message, const char *prefix = 0) +{ + message.replace('\0', '|'); + const QString messageS = QString::fromLatin1(message); + return prefix ? + (QLatin1String(prefix) + messageS) : messageS; +} + +void TcfTrkDevice::slotDeviceReadyRead() +{ + d->m_readBuffer += d->m_device->readAll(); + // Take complete message off front of readbuffer. + do { + const int messageEndPos = d->m_readBuffer.indexOf(d->m_messageTerminator); + if (messageEndPos == -1) + break; + const QByteArray message = d->m_readBuffer.left(messageEndPos); + if (debug) + qDebug("Read:\n%s", qPrintable(formatData(message))); + if (const int errorCode = parseMessage(message)) { + emitLogMessage(QString::fromLatin1("Parse error %1 for: %2").arg(errorCode).arg(debugMessage(message))); + } + d->m_readBuffer.remove(0, messageEndPos + d->m_messageTerminator.size()); + } while (!d->m_readBuffer.isEmpty()); + checkSendQueue(); // Send off further message +} + +// Split \0-terminated message into tokens, skipping the initial type character +static inline QVector splitMessage(const QByteArray &message) +{ + QVector tokens; + tokens.reserve(7); + const int messageSize = message.size(); + for (int pos = 2; pos < messageSize; ) { + const int nextPos = message.indexOf('\0', pos); + if (nextPos == -1) + break; + tokens.push_back(message.mid(pos, nextPos - pos)); + pos = nextPos + 1; + } + return tokens; +} + +int TcfTrkDevice::parseMessage(const QByteArray &message) +{ + if (d->m_verbose) + emitLogMessage(debugMessage(message, "TCF ->")); + // Special JSON parse error message or protocol format error. + // The port is usually closed after receiving it. + // "\3\2{"Time":1276096098255,"Code":3,"Format": "Protocol format error"}" + if (message.startsWith("\003\002")) { + QByteArray text = message.mid(2); + const QString errorMessage = QString::fromLatin1("Parse error received: %1").arg(QString::fromAscii(text)); + emit error(errorMessage); + return 0; + } + if (message.size() < 4 || message.at(1) != '\0') + return 1; + // Split into tokens + const char type = message.at(0); + const QVector tokens = splitMessage(message); + switch (type) { + case 'E': + return parseTcfEvent(tokens); + case 'R': // Command replies + case 'N': + case 'P': + return parseTcfCommandReply(type, tokens); + default: + emitLogMessage(QString::fromLatin1("Unhandled message type: %1").arg(debugMessage(message))); + return 756; + } + return 0; +} + +int TcfTrkDevice::parseTcfCommandReply(char type, const QVector &tokens) +{ + typedef TcfTrkDevicePrivate::TokenWrittenMessageMap::iterator TokenWrittenMessageMapIterator; + // Find the corresponding entry in the written messages hash. + const int tokenCount = tokens.size(); + if (tokenCount < 1) + return 234; + bool tokenOk; + const int token = tokens.at(0).toInt(&tokenOk); + if (!tokenOk) + return 235; + const TokenWrittenMessageMapIterator it = d->m_writtenMessages.find(token); + if (it == d->m_writtenMessages.end()) { + qWarning("TcfTrkDevice: Internal error: token %d not found for '%s'", + token, qPrintable(joinByteArrays(tokens))); + return 236; + } + // No callback: remove entry from map, happy + if (!it.value().callback) { + d->m_writtenMessages.erase(it); + return 0; + } + // Parse values into JSON + QVector values; + values.reserve(tokenCount); + for (int i = 1; i < tokenCount; i++) { + if (!tokens.at(i).isEmpty()) { // Strange: Empty tokens occur. + const JsonValue value(tokens.at(i)); + if (value.isValid()) { + values.push_back(value); + } else { + qWarning("JSON parse error for reply to command token %d: #%d '%s'", + token, i, tokens.at(i).constData()); + d->m_writtenMessages.erase(it); + return -1; + } + } + } + + // Construct result and invoke callback, remove entry from map. + TcfTrkCallback callback = it.value().callback; + TcfTrkCommandResult result(type, it.value().service, it.value().data, + values, it.value().cookie); + d->m_writtenMessages.erase(it); + callback(result); + return 0; +} + +static const char locatorAnswerC[] = "E\0Locator\0Hello\0[\"Locator\"]"; + +int TcfTrkDevice::parseTcfEvent(const QVector &tokens) +{ + // Event: Ignore the periodical heartbeat event, answer 'Hello', + // emit signal for the rest + if (tokens.size() < 3) + return 433; + const Services service = serviceFromName(tokens.at(0).constData()); + if (service == LocatorService && tokens.at(1) == "peerHeartBeat") + return 0; + QVector values; + for (int i = 2; i < tokens.size(); i++) { + const JsonValue value(tokens.at(i)); + if (!value.isValid()) + return 434; + values.push_back(value); + } + // Parse known events, emit signals + QScopedPointer knownEvent(TcfTrkEvent::parseEvent(service, tokens.at(1), values)); + if (!knownEvent.isNull()) { + // Answer hello event. + if (knownEvent->type() == TcfTrkEvent::LocatorHello) + writeMessage(QByteArray(locatorAnswerC, sizeof(locatorAnswerC))); + emit tcfEvent(*knownEvent); + } + emit genericTcfEvent(service, tokens.at(1), values); + + if (debug || d->m_verbose) { + QString msg; + QTextStream str(&msg); + if (knownEvent.isNull()) { + str << "Event: " << tokens.at(0) << ' ' << tokens.at(1) << '\n'; + foreach(const JsonValue &val, values) + str << " " << val.toString() << '\n'; + } else { + str << knownEvent->toString(); + } + emitLogMessage(msg); + } + + return 0; +} + +unsigned TcfTrkDevice::verbose() const +{ + return d->m_verbose; +} + +void TcfTrkDevice::setVerbose(unsigned v) +{ + d->m_verbose = v; +} + +void TcfTrkDevice::emitLogMessage(const QString &m) +{ + if (debug) + qWarning("%s", qPrintable(m)); + emit logMessage(m); +} + +bool TcfTrkDevice::checkOpen() +{ + if (d->m_device.isNull()) { + emitLogMessage(QLatin1String("Internal error: No device set on TcfTrkDevice.")); + return false; + } + if (!d->m_device->isOpen()) { + emitLogMessage(QLatin1String("Internal error: Device not open in TcfTrkDevice.")); + return false; + } + return true; +} + +void TcfTrkDevice::sendTcfTrkMessage(MessageType mt, Services service, const char *command, + const char *commandParameters, int commandParametersLength, + const TcfTrkCallback &callBack, + const QVariant &cookie) + +{ + if (!checkOpen()) + return; + // Format the message + const int token = d->m_token++; + QByteArray data; + data.reserve(30 + commandParametersLength); + data.append('C'); + data.append('\0'); + data.append(QByteArray::number(token)); + data.append('\0'); + data.append(serviceName(service)); + data.append('\0'); + data.append(command); + data.append('\0'); + if (commandParametersLength) + data.append(commandParameters, commandParametersLength); + const TcfTrkSendQueueEntry entry(mt, token, service, data, callBack, cookie); + d->m_sendQueue.enqueue(entry); + checkSendQueue(); +} + +void TcfTrkDevice::sendTcfTrkMessage(MessageType mt, Services service, const char *command, + const QByteArray &commandParameters, + const TcfTrkCallback &callBack, + const QVariant &cookie) +{ + sendTcfTrkMessage(mt, service, command, commandParameters.constData(), commandParameters.size(), + callBack, cookie); +} + +// Enclose in message frame and write. +void TcfTrkDevice::writeMessage(QByteArray data) +{ + if (!checkOpen()) + return; + + if (d->m_verbose) + emitLogMessage(debugMessage(data, "TCF <-")); + + // Ensure \0-termination which easily gets lost in QByteArray CT. + if (!data.endsWith('\0')) + data.append('\0'); + data += d->m_messageTerminator; + + if (debug > 1) + qDebug("Writing:\n%s", qPrintable(formatData(data))); + + d->m_device->write(data); + if (QAbstractSocket *as = qobject_cast(d->m_device.data())) + as->flush(); +} + +void TcfTrkDevice::checkSendQueue() +{ + // Fire off messages or invoke noops until a message with reply is found + // and an entry to writtenMessages is made. + while (d->m_writtenMessages.empty()) { + if (d->m_sendQueue.isEmpty()) + break; + TcfTrkSendQueueEntry entry = d->m_sendQueue.dequeue(); + switch (entry.messageType) { + case MessageWithReply: + d->m_writtenMessages.insert(entry.token, entry); + writeMessage(entry.data); + break; + case MessageWithoutReply: + writeMessage(entry.data); + break; + case NoopMessage: // Invoke the noop-callback for synchronization + if (entry.callback) { + TcfTrkCommandResult noopResult(TcfTrkCommandResult::SuccessReply); + noopResult.cookie = entry.cookie; + entry.callback(noopResult); + } + break; + } + } +} + +// Fix slashes +static inline QString fixFileName(QString in) +{ + in.replace(QLatin1Char('/'), QLatin1Char('\\')); + return in; +} + +// Start a process (consisting of a non-reply setSettings and start). +void TcfTrkDevice::sendProcessStartCommand(const TcfTrkCallback &callBack, + const QString &binaryIn, + unsigned uid, + QStringList arguments, + QString workingDirectory, + bool debugControl, + const QStringList &additionalLibraries, + const QVariant &cookie) +{ + // Obtain the bin directory, expand by c:/sys/bin if missing + const QChar backSlash('\\'); + int slashPos = binaryIn.lastIndexOf(QLatin1Char('/')); + if (slashPos == -1) + slashPos = binaryIn.lastIndexOf(backSlash); + const QString sysBin = QLatin1String("c:/sys/bin"); + const QString binaryFileName = slashPos == -1 ? binaryIn : binaryIn.mid(slashPos + 1); + const QString binaryDirectory = slashPos == -1 ? sysBin : binaryIn.left(slashPos); + const QString binary = fixFileName(binaryDirectory + QLatin1Char('/') + binaryFileName); + + // Fixup: Does argv[0] convention exist on Symbian? + arguments.push_front(binary); + if (workingDirectory.isEmpty()) + workingDirectory = sysBin; + + // Format settings with empty dummy parameter + QByteArray setData; + JsonInputStream setStr(setData); + setStr << "" << '\0' + << '[' << "exeToLaunch" << ',' << "addExecutables" << ',' << "addLibraries" << ']' + << '\0' << '[' + << binary << ',' + << '{' << binaryFileName << ':' << QString::number(uid, 16) << '}' << ',' + << additionalLibraries + << ']'; + sendTcfTrkMessage(MessageWithoutReply, SettingsService, "set", setData); + + QByteArray startData; + JsonInputStream startStr(startData); + startStr << fixFileName(workingDirectory) + << '\0' << binary << '\0' << arguments << '\0' + << QStringList() << '\0' // Env is an array ["PATH=value"] (non-standard) + << debugControl; + sendTcfTrkMessage(MessageWithReply, ProcessesService, "start", startData, callBack, cookie); +} + +void TcfTrkDevice::sendProcessTerminateCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << id; + sendTcfTrkMessage(MessageWithReply, ProcessesService, "terminate", data, callBack, cookie); +} + +void TcfTrkDevice::sendRunControlTerminateCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << id; + sendTcfTrkMessage(MessageWithReply, RunControlService, "terminate", data, callBack, cookie); +} + +// Non-standard: Remove executable from settings +void TcfTrkDevice::sendSettingsRemoveExecutableCommand(const QString &binaryIn, + unsigned uid, + const QStringList &additionalLibraries, + const QVariant &cookie) +{ + QByteArray setData; + JsonInputStream setStr(setData); + setStr << "" << '\0' + << '[' << "removedExecutables" << ',' << "removedLibraries" << ']' + << '\0' << '[' + << '{' << QFileInfo(binaryIn).fileName() << ':' << QString::number(uid, 16) << '}' << ',' + << additionalLibraries + << ']'; + sendTcfTrkMessage(MessageWithoutReply, SettingsService, "set", setData, TcfTrkCallback(), cookie); +} + +void TcfTrkDevice::sendRunControlResumeCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + RunControlResumeMode mode, + unsigned count, + quint64 rangeStart, + quint64 rangeEnd, + const QVariant &cookie) +{ + QByteArray resumeData; + JsonInputStream str(resumeData); + str << id << '\0' << int(mode) << '\0' << count; + switch (mode) { + case RM_STEP_OVER_RANGE: + case RM_STEP_INTO_RANGE: + case RM_REVERSE_STEP_OVER_RANGE: + case RM_REVERSE_STEP_INTO_RANGE: + str << '\0' << '{' << "RANGE_START" << ':' << rangeStart + << ',' << "RANGE_END" << ':' << rangeEnd << '}'; + break; + default: + break; + } + sendTcfTrkMessage(MessageWithReply, RunControlService, "resume", resumeData, callBack, cookie); +} + +void TcfTrkDevice::sendRunControlSuspendCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << id; + sendTcfTrkMessage(MessageWithReply, RunControlService, "suspend", data, callBack, cookie); +} + +void TcfTrkDevice::sendRunControlResumeCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + const QVariant &cookie) +{ + sendRunControlResumeCommand(callBack, id, RM_RESUME, 1, 0, 0, cookie); +} + +void TcfTrkDevice::sendBreakpointsAddCommand(const TcfTrkCallback &callBack, + const Breakpoint &bp, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << bp; + sendTcfTrkMessage(MessageWithReply, BreakpointsService, "add", data, callBack, cookie); +} + +void TcfTrkDevice::sendBreakpointsRemoveCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + const QVariant &cookie) +{ + sendBreakpointsRemoveCommand(callBack, QVector(1, id), cookie); +} + +void TcfTrkDevice::sendBreakpointsRemoveCommand(const TcfTrkCallback &callBack, + const QVector &ids, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << ids; + sendTcfTrkMessage(MessageWithReply, BreakpointsService, "remove", data, callBack, cookie); +} + +void TcfTrkDevice::sendBreakpointsEnableCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + bool enable, + const QVariant &cookie) +{ + sendBreakpointsEnableCommand(callBack, QVector(1, id), enable, cookie); +} + +void TcfTrkDevice::sendBreakpointsEnableCommand(const TcfTrkCallback &callBack, + const QVector &ids, + bool enable, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << ids; + sendTcfTrkMessage(MessageWithReply, BreakpointsService, + enable ? "enable" : "disable", + data, callBack, cookie); +} + +void TcfTrkDevice::sendMemorySetCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + quint64 start, const QByteArray& data, + const QVariant &cookie) +{ + QByteArray getData; + JsonInputStream str(getData); + // start/word size/mode. Mode should ideally be 1 (continue on error?) + str << contextId << '\0' << start << '\0' << 1 << '\0' << data.size() << '\0' << 1 + << '\0' << data.toBase64(); + sendTcfTrkMessage(MessageWithReply, MemoryService, "set", getData, callBack, cookie); +} + +void TcfTrkDevice::sendMemoryGetCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + quint64 start, quint64 size, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + // start/word size/mode. Mode should ideally be 1 (continue on error?) + str << contextId << '\0' << start << '\0' << 1 << '\0' << size << '\0' << 1; + sendTcfTrkMessage(MessageWithReply, MemoryService, "get", data, callBack, cookie); +} + +QByteArray TcfTrkDevice::parseMemoryGet(const TcfTrkCommandResult &r) +{ + if (r.type != TcfTrkCommandResult::SuccessReply || r.values.size() < 1) + return QByteArray(); + const JsonValue &memoryV = r.values.front(); + + if (memoryV.type() != JsonValue::String || memoryV.data().size() < 2 + || !memoryV.data().endsWith('=')) + return QByteArray(); + // Catch errors reported as hash: + // R.4."TlVMTA==".{"Time":1276786871255,"Code":1,"AltCode":-38,"AltOrg":"POSIX","Format":"BadDescriptor"} + // Not sure what to make of it. + if (r.values.size() >= 2 && r.values.at(1).type() == JsonValue::Object) + qWarning("Error retrieving memory: %s", r.values.at(1).toString(false).constData()); + // decode + const QByteArray memory = QByteArray::fromBase64(memoryV.data()); + if (memory.isEmpty()) + qWarning("Base64 decoding of %s failed.", memoryV.data().constData()); + if (debug) + qDebug("TcfTrkDevice::parseMemoryGet: received %d bytes", memory.size()); + return memory; +} + +void TcfTrkDevice::sendRegistersGetMCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + const QVector &ids, + const QVariant &cookie) +{ + // TODO: use "Registers" (which uses base64-encoded values) + QByteArray data; + JsonInputStream str(data); + str << contextId << '\0' << ids; + sendTcfTrkMessage(MessageWithReply, SimpleRegistersService, "get", data, callBack, cookie); +} + +void TcfTrkDevice::sendRegistersGetMRangeCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + unsigned start, unsigned count) +{ + const unsigned end = start + count; + if (end > (unsigned)d->m_registerNames.size()) { + qWarning("TcfTrkDevice: No register name set for index %u (size: %d).", end, d->m_registerNames.size()); + return; + } + + QVector ids; + ids.reserve(count); + for (unsigned i = start; i < end; i++) + ids.push_back(d->m_registerNames.at(i)); + sendRegistersGetMCommand(callBack, contextId, ids, QVariant(start)); +} + +// Set register +void TcfTrkDevice::sendRegistersSetCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + const QByteArray &id, + unsigned value, + const QVariant &cookie) +{ + // TODO: use "Registers" (which uses base64-encoded values) + QByteArray data; + JsonInputStream str(data); + str << contextId << '\0' << QVector(1, id) + << '\0' << QVector(1, QByteArray::number(value, 16)); + sendTcfTrkMessage(MessageWithReply, SimpleRegistersService, "set", data, callBack, cookie); +} + +// Set register +void TcfTrkDevice::sendRegistersSetCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + unsigned registerNumber, + unsigned value, + const QVariant &cookie) +{ + if (registerNumber >= (unsigned)d->m_registerNames.size()) { + qWarning("TcfTrkDevice: No register name set for index %u (size: %d).", registerNumber, d->m_registerNames.size()); + return; + } + sendRegistersSetCommand(callBack, contextId, + d->m_registerNames[registerNumber], + value, cookie); +} + +} // namespace tcftrk diff --git a/tools/runonphone/symbianutils/tcftrkdevice.h b/tools/runonphone/symbianutils/tcftrkdevice.h new file mode 100644 index 0000000..bb4c184 --- /dev/null +++ b/tools/runonphone/symbianutils/tcftrkdevice.h @@ -0,0 +1,283 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef TCFTRKENGINE_H +#define TCFTRKENGINE_H + +#include "symbianutils_global.h" +#include "tcftrkmessage.h" +#include "callback.h" +#include "json.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QIODevice; +class QTextStream; +QT_END_NAMESPACE + +namespace tcftrk { + +struct TcfTrkDevicePrivate; +struct Breakpoint; + +/* Command error handling in TCF: + * 1) 'Severe' errors (JSON format, parameter format): Trk emits a + * nonstandard message (\3\2 error paramaters) and closes the connection. + * 2) Protocol errors: 'N' without error message is returned. + * 3) Errors in command execution: 'R' with a TCF error hash is returned + * (see TcfTrkCommandError). */ + +/* Error code return in 'R' reply to command + * (see top of 'Services' documentation). */ +struct SYMBIANUTILS_EXPORT TcfTrkCommandError { + TcfTrkCommandError(); + void clear(); + operator bool() const { return timeMS != 0; } + QString toString() const; + void write(QTextStream &str) const; + bool parse(const QVector &values); + + quint64 timeMS; // Since 1.1.1970 + int code; + QByteArray format; // message + // 'Alternative' meaning, like altOrg="POSIX"/altCode= + QByteArray alternativeOrganization; + int alternativeCode; +}; + +/* Answer to a Tcf command passed to the callback. */ +struct SYMBIANUTILS_EXPORT TcfTrkCommandResult { + enum Type { + SuccessReply, // 'R' and no error -> all happy. + CommandErrorReply, // 'R' with TcfTrkCommandError received + ProgressReply, // 'P', progress indicator + FailReply // 'N' Protocol NAK, severe error + }; + + explicit TcfTrkCommandResult(Type t = SuccessReply); + explicit TcfTrkCommandResult(char typeChar, Services service, + const QByteArray &request, + const QVector &values, + const QVariant &cookie); + + QString toString() const; + QString errorString() const; + operator bool() const { return type == SuccessReply || type == ProgressReply; } + + Type type; + Services service; + QByteArray request; + TcfTrkCommandError commandError; + QVector values; + QVariant cookie; +}; + +typedef trk::Callback TcfTrkCallback; + +/* TcfTrkDevice: TCF communication helper using an asynchronous QIODevice + * implementing the TCF protocol according to: +http://dev.eclipse.org/svnroot/dsdp/org.eclipse.tm.tcf/trunk/docs/TCF%20Specification.html +http://dev.eclipse.org/svnroot/dsdp/org.eclipse.tm.tcf/trunk/docs/TCF%20Services.html + * Commands can be sent along with callbacks that are passed a + * TcfTrkCommandResult and an opaque QVariant cookie. In addition, events are emitted. +*/ + +class SYMBIANUTILS_EXPORT TcfTrkDevice : public QObject +{ + Q_PROPERTY(unsigned verbose READ verbose WRITE setVerbose) + Q_OBJECT +public: + enum MessageType { MessageWithReply, + MessageWithoutReply, /* Non-standard: "Settings:set" command does not reply */ + NoopMessage }; + + typedef QSharedPointer IODevicePtr; + + explicit TcfTrkDevice(QObject *parent = 0); + virtual ~TcfTrkDevice(); + + unsigned verbose() const; + + // Mapping of register names for indices + QVector registerNames() const; + void setRegisterNames(const QVector& n); + + IODevicePtr device() const; + IODevicePtr takeDevice(); + void setDevice(const IODevicePtr &dp); + + void sendTcfTrkMessage(MessageType mt, Services service, + const char *command, + const char *commandParameters, int commandParametersLength, + const TcfTrkCallback &callBack = TcfTrkCallback(), + const QVariant &cookie = QVariant()); + + void sendTcfTrkMessage(MessageType mt, Services service, const char *command, + const QByteArray &commandParameters, + const TcfTrkCallback &callBack = TcfTrkCallback(), + const QVariant &cookie = QVariant()); + + // Convenience messages: Start a process + void sendProcessStartCommand(const TcfTrkCallback &callBack, + const QString &binary, + unsigned uid, + QStringList arguments = QStringList(), + QString workingDirectory = QString(), + bool debugControl = true, + const QStringList &additionalLibraries = QStringList(), + const QVariant &cookie = QVariant()); + + // Preferred over Processes:Terminate by TCF TRK. + void sendRunControlTerminateCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + const QVariant &cookie = QVariant()); + + void sendProcessTerminateCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + const QVariant &cookie = QVariant()); + + // Non-standard: Remove executable from settings. + // Probably needs to be called after stopping. This command has no response. + void sendSettingsRemoveExecutableCommand(const QString &binaryIn, + unsigned uid, + const QStringList &additionalLibraries = QStringList(), + const QVariant &cookie = QVariant()); + + void sendRunControlSuspendCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + const QVariant &cookie = QVariant()); + + // Resume / Step (see RunControlResumeMode). + void sendRunControlResumeCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + RunControlResumeMode mode, + unsigned count /* = 1, currently ignored. */, + quint64 rangeStart, quint64 rangeEnd, + const QVariant &cookie = QVariant()); + + // Convenience to resume a suspended process + void sendRunControlResumeCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + const QVariant &cookie = QVariant()); + + void sendBreakpointsAddCommand(const TcfTrkCallback &callBack, + const Breakpoint &b, + const QVariant &cookie = QVariant()); + + void sendBreakpointsRemoveCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + const QVariant &cookie = QVariant()); + + void sendBreakpointsRemoveCommand(const TcfTrkCallback &callBack, + const QVector &id, + const QVariant &cookie = QVariant()); + + void sendBreakpointsEnableCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + bool enable, + const QVariant &cookie = QVariant()); + + void sendBreakpointsEnableCommand(const TcfTrkCallback &callBack, + const QVector &id, + bool enable, + const QVariant &cookie = QVariant()); + + + void sendMemoryGetCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + quint64 start, quint64 size, + const QVariant &cookie = QVariant()); + + void sendMemorySetCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + quint64 start, const QByteArray& data, + const QVariant &cookie = QVariant()); + + // Reply is an array of hexvalues + void sendRegistersGetMCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + const QVector &ids, + const QVariant &cookie = QVariant()); + + // Convenience to get a range of register "R0" .. "R". + // Cookie will be an int containing "start". + void sendRegistersGetMRangeCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + unsigned start, unsigned count); + + // Set register + void sendRegistersSetCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + const QByteArray &ids, + unsigned value, + const QVariant &cookie = QVariant()); + // Set register + void sendRegistersSetCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + unsigned registerNumber, + unsigned value, + const QVariant &cookie = QVariant()); + + static QByteArray parseMemoryGet(const TcfTrkCommandResult &r); + +signals: + void genericTcfEvent(int service, const QByteArray &name, const QVector &value); + void tcfEvent(const tcftrk::TcfTrkEvent &knownEvent); + + void logMessage(const QString &); + void error(const QString &); + +public slots: + void setVerbose(unsigned v); + +private slots: + void slotDeviceError(); + void slotDeviceSocketStateChanged(); + void slotDeviceReadyRead(); + +private: + bool checkOpen(); + void checkSendQueue(); + void writeMessage(QByteArray data); + void emitLogMessage(const QString &); + int parseMessage(const QByteArray &); + int parseTcfCommandReply(char type, const QVector &tokens); + int parseTcfEvent(const QVector &tokens); + + TcfTrkDevicePrivate *d; +}; + +} // namespace tcftrk + +#endif // TCFTRKENGINE_H diff --git a/tools/runonphone/symbianutils/tcftrkmessage.cpp b/tools/runonphone/symbianutils/tcftrkmessage.cpp new file mode 100644 index 0000000..929bb8d --- /dev/null +++ b/tools/runonphone/symbianutils/tcftrkmessage.cpp @@ -0,0 +1,550 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "tcftrkmessage.h" +#include "json.h" + +#include +#include + +// Names matching the enum +static const char *serviceNamesC[] = +{ "Locator", "RunControl", "Processes", "Memory", "Settings", "Breakpoints", + "Registers", "SimpleRegisters", + "UnknownService"}; + +namespace tcftrk { + +SYMBIANUTILS_EXPORT QString joinByteArrays(const QVector &a, char sep) +{ + QString rc; + const int count = a.size(); + for (int i = 0; i < count; i++) { + if (i) + rc += QLatin1Char(sep); + rc += QString::fromUtf8(a.at(i)); + } + return rc; +} + +static inline bool jsonToBool(const JsonValue& js) +{ + return js.type() == JsonValue::Boolean && js.data() == "true"; +} + +SYMBIANUTILS_EXPORT const char *serviceName(Services s) +{ + return serviceNamesC[s]; +} + +SYMBIANUTILS_EXPORT Services serviceFromName(const char *n) +{ + const int count = sizeof(serviceNamesC)/sizeof(char *); + for (int i = 0; i < count; i++) + if (!qstrcmp(serviceNamesC[i], n)) + return static_cast(i); + return UnknownService; +} + +SYMBIANUTILS_EXPORT QString formatData(const QByteArray &a) +{ + const int columns = 16; + QString rc; + QTextStream str(&rc); + str.setIntegerBase(16); + str.setPadChar(QLatin1Char('0')); + const unsigned char *start = reinterpret_cast(a.constData()); + const unsigned char *end = start + a.size(); + for (const unsigned char *p = start; p < end ; ) { + str << "0x"; + str.setFieldWidth(4); + str << (p - start); + str.setFieldWidth(0); + str << ' '; + QString asc; + int c = 0; + for ( ; c < columns && p < end; c++, p++) { + const unsigned u = *p; + str.setFieldWidth(2); + str << u; + str.setFieldWidth(0); + str << ' '; + switch (u) { + case '\n': + asc += QLatin1String("\\n"); + break; + case '\r': + asc += QLatin1String("\\r"); + break; + case '\t': + asc += QLatin1String("\\t"); + break; + default: + if (u >= 32 && u < 128) { + asc += QLatin1Char(' '); + asc += QLatin1Char(u); + } else { + asc += QLatin1String(" ."); + } + break; + } + } + if (const int remainder = columns - c) + str << QString(3 * remainder, QLatin1Char(' ')); + str << ' ' << asc << '\n'; + } + return rc; +} + +// ----------- RunControlContext +RunControlContext::RunControlContext() : + flags(0), resumeFlags(0) +{ +} + +void RunControlContext::clear() +{ + flags =0; + resumeFlags = 0; + id.clear(); + osid.clear(); + parentId.clear(); +} + +RunControlContext::Type RunControlContext::typeFromTcfId(const QByteArray &id) +{ + // "p12" or "p12.t34"? + return id.contains(".t") ? Thread : Process; +} + +unsigned RunControlContext::processId() const +{ + return processIdFromTcdfId(id); +} + +unsigned RunControlContext::threadId() const +{ + return threadIdFromTcdfId(id); +} + +unsigned RunControlContext::processIdFromTcdfId(const QByteArray &id) +{ + // Cut out process id from "p12" or "p12.t34"? + if (!id.startsWith('p')) + return 0; + const int dotPos = id.indexOf('.'); + const int pLen = dotPos == -1 ? id.size() : dotPos; + return id.mid(1, pLen - 1).toUInt(); +} + +unsigned RunControlContext::threadIdFromTcdfId(const QByteArray &id) +{ + const int tPos = id.indexOf(".t"); + return tPos != -1 ? id.mid(tPos + 2).toUInt() : uint(0); +} + +QByteArray RunControlContext::tcfId(unsigned processId, unsigned threadId /* = 0 */) +{ + QByteArray rc("p"); + rc += QByteArray::number(processId); + if (threadId) { + rc += ".t"; + rc += QByteArray::number(threadId); + } + return rc; +} + +RunControlContext::Type RunControlContext::type() const +{ + return RunControlContext::typeFromTcfId(id); +} + +bool RunControlContext::parse(const JsonValue &val) +{ + clear(); + if (val.type() != JsonValue::Object) + return false; + foreach(const JsonValue &c, val.children()) { + if (c.name() == "ID") { + id = c.data(); + } else if (c.name() == "OSID") { + osid = c.data(); + } else if (c.name() == "ParentID") { + parentId = c.data(); + } else if (c.name() == "IsContainer") { + if (jsonToBool(c)) + flags |= Container; + } else if (c.name() == "CanTerminate") { + if (jsonToBool(c)) + flags |= CanTerminate; + } else if (c.name() == "CanResume") { + resumeFlags = c.data().toUInt(); + } else if (c.name() == "HasState") { + if (jsonToBool(c)) + flags |= HasState; + } else if (c.name() == "CanSuspend") { + if (jsonToBool(c)) + flags |= CanSuspend; + } + } + return true; +} + +QString RunControlContext::toString() const +{ + QString rc; + QTextStream str(&rc); + format(str); + return rc; +} + +void RunControlContext::format(QTextStream &str) const +{ + str << " id='" << id << "' osid='" << osid + << "' parentId='" << parentId <<"' "; + if (flags & Container) + str << "[container] "; + if (flags & HasState) + str << "[has state] "; + if (flags & CanSuspend) + str << "[can suspend] "; + if (flags & CanSuspend) + str << "[can terminate] "; + str.setIntegerBase(16); + str << " resume_flags: 0x" << resumeFlags; + str.setIntegerBase(10); +} + +// ------ ModuleLoadEventInfo +ModuleLoadEventInfo::ModuleLoadEventInfo() : + loaded(false), codeAddress(0), dataAddress(0), requireResume(false) +{ +} + +void ModuleLoadEventInfo::clear() +{ + loaded = requireResume = false; + codeAddress = dataAddress =0; +} + +bool ModuleLoadEventInfo::parse(const JsonValue &val) +{ + clear(); + if (val.type() != JsonValue::Object) + return false; + foreach(const JsonValue &c, val.children()) { + if (c.name() == "Name") { + name = c.data(); + } else if (c.name() == "File") { + file = c.data(); + } else if (c.name() == "CodeAddress") { + codeAddress = c.data().toULongLong(); + } else if (c.name() == "DataAddress") { + dataAddress = c.data().toULongLong(); + } else if (c.name() == "Loaded") { + loaded = jsonToBool(c); + } else if (c.name() == "RequireResume") { + requireResume =jsonToBool(c); + } + } + return true; +} +void ModuleLoadEventInfo::format(QTextStream &str) const +{ + str << "name='" << name << "' file='" << file << "' " << + (loaded ? "[loaded] " : "[not loaded] "); + if (requireResume) + str << "[requires resume] "; + str.setIntegerBase(16); + str << " code: 0x" << codeAddress << " data: 0x" << dataAddress; + str.setIntegerBase(10); +} + +// ---------------------- Breakpoint + +// Types matching enum +static const char *breakPointTypesC[] = {"Software", "Hardware", "Auto"}; + +Breakpoint::Breakpoint(quint64 loc) : + type(Auto), enabled(true), ignoreCount(0), location(loc), size(1), thumb(true) +{ + if (loc) + id = idFromLocation(location); +} + +void Breakpoint::setContextId(unsigned processId, unsigned threadId) +{ + contextIds = QVector(1, RunControlContext::tcfId(processId, threadId)); +} + +QByteArray Breakpoint::idFromLocation(quint64 loc) +{ + return QByteArray("BP_0x") + QByteArray::number(loc, 16); +} + +QString Breakpoint::toString() const +{ + QString rc; + QTextStream str(&rc); + str.setIntegerBase(16); + str << "Breakpoint '" << id << "' " << breakPointTypesC[type] << " for contexts '" + << joinByteArrays(contextIds, ',') << "' at 0x" << location; + str.setIntegerBase(10); + str << " size " << size; + if (enabled) + str << " [enabled]"; + if (thumb) + str << " [thumb]"; + if (ignoreCount) + str << " IgnoreCount " << ignoreCount; + return rc; +} + +JsonInputStream &operator<<(JsonInputStream &str, const Breakpoint &b) +{ + if (b.contextIds.isEmpty()) + qWarning("tcftrk::Breakpoint: No context ids specified"); + + str << '{' << "ID" << ':' << QString::fromUtf8(b.id) << ',' + << "BreakpointType" << ':' << breakPointTypesC[b.type] << ',' + << "Enabled" << ':' << b.enabled << ',' + << "IgnoreCount" << ':' << b.ignoreCount << ',' + << "ContextIds" << ':' << b.contextIds << ',' + << "Location" << ':' << QString::number(b.location) << ',' + << "Size" << ':' << b.size << ',' + << "THUMB_BREAKPOINT" << ':' << b.thumb + << '}'; + return str; +} + +// --- Events +TcfTrkEvent::TcfTrkEvent(Type type) : m_type(type) +{ +} + +TcfTrkEvent::~TcfTrkEvent() +{ +} + +TcfTrkEvent::Type TcfTrkEvent::type() const +{ + return m_type; +} + +QString TcfTrkEvent::toString() const +{ + return QString(); +} + +static const char sharedLibrarySuspendReasonC[] = "Shared Library"; + +TcfTrkEvent *TcfTrkEvent::parseEvent(Services s, const QByteArray &nameBA, const QVector &values) +{ + switch (s) { + case LocatorService: + if (nameBA == "Hello" && values.size() == 1 && values.front().type() == JsonValue::Array) { + QStringList services; + foreach (const JsonValue &jv, values.front().children()) + services.push_back(QString::fromUtf8(jv.data())); + return new TcfTrkLocatorHelloEvent(services); + } + break; + case RunControlService: + if (values.empty()) + return 0; + // "id/PC/Reason/Data" + if (nameBA == "contextSuspended" && values.size() == 4) { + const QByteArray idBA = values.at(0).data(); + const quint64 pc = values.at(1).data().toULongLong(); + const QByteArray reasonBA = values.at(2).data(); + // Module load: Special + if (reasonBA == sharedLibrarySuspendReasonC) { + ModuleLoadEventInfo info; + if (!info.parse(values.at(3))) + return 0; + return new TcfTrkRunControlModuleLoadContextSuspendedEvent(idBA, reasonBA, pc, info); + } + return new TcfTrkRunControlContextSuspendedEvent(idBA, reasonBA, pc); + } // "contextSuspended" + if (nameBA == "contextAdded") + return TcfTrkRunControlContextAddedEvent::parseEvent(values); + if (nameBA == "contextRemoved" && values.front().type() == JsonValue::Array) { + QVector ids; + foreach(const JsonValue &c, values.front().children()) + ids.push_back(c.data()); + return new TcfTrkRunControlContextRemovedEvent(ids); + } + break; + default: + break; + } + return 0; +} + +// -------------- TcfTrkServiceHelloEvent +TcfTrkLocatorHelloEvent::TcfTrkLocatorHelloEvent(const QStringList &s) : + TcfTrkEvent(LocatorHello), + m_services(s) +{ +} + +QString TcfTrkLocatorHelloEvent::toString() const +{ + return QLatin1String("ServiceHello: ") + m_services.join(QLatin1String(", ")); +} + +// -------------- TcfTrkIdEvent +TcfTrkIdEvent::TcfTrkIdEvent(Type t, const QByteArray &id) : + TcfTrkEvent(t), m_id(id) +{ +} + +// ---------- TcfTrkIdsEvent +TcfTrkIdsEvent::TcfTrkIdsEvent(Type t, const QVector &ids) : + TcfTrkEvent(t), m_ids(ids) +{ +} + +QString TcfTrkIdsEvent::joinedIdString(const char sep) const +{ + return joinByteArrays(m_ids, sep); +} + +// ---------------- TcfTrkRunControlContextAddedEvent +TcfTrkRunControlContextAddedEvent::TcfTrkRunControlContextAddedEvent(const RunControlContexts &c) : + TcfTrkEvent(RunControlContextAdded), m_contexts(c) +{ +} + +TcfTrkRunControlContextAddedEvent + *TcfTrkRunControlContextAddedEvent::parseEvent(const QVector &values) +{ + // Parse array of contexts + if (values.size() < 1 || values.front().type() != JsonValue::Array) + return 0; + + RunControlContexts contexts; + foreach (const JsonValue &v, values.front().children()) { + RunControlContext context; + if (context.parse(v)) + contexts.push_back(context); + } + return new TcfTrkRunControlContextAddedEvent(contexts); +} + +QString TcfTrkRunControlContextAddedEvent::toString() const +{ + QString rc; + QTextStream str(&rc); + str << "RunControl: " << m_contexts.size() << " context(s) " + << (type() == RunControlContextAdded ? "added" : "removed") + << '\n'; + foreach (const RunControlContext &c, m_contexts) { + c.format(str); + str << '\n'; + } + return rc; +} + +// --------------- TcfTrkRunControlContextRemovedEvent +TcfTrkRunControlContextRemovedEvent::TcfTrkRunControlContextRemovedEvent(const QVector &ids) : + TcfTrkIdsEvent(RunControlContextRemoved, ids) +{ +} + +QString TcfTrkRunControlContextRemovedEvent::toString() const +{ + return QLatin1String("RunControl: Removed contexts '") + joinedIdString() + ("'."); +} + +// --------------- TcfTrkRunControlContextSuspendedEvent +TcfTrkRunControlContextSuspendedEvent::TcfTrkRunControlContextSuspendedEvent(const QByteArray &id, + const QByteArray &reason, + quint64 pc) : + TcfTrkIdEvent(RunControlSuspended, id), m_pc(pc), m_reason(reason) +{ +} + +TcfTrkRunControlContextSuspendedEvent::TcfTrkRunControlContextSuspendedEvent(Type t, + const QByteArray &id, + const QByteArray &reason, + quint64 pc) : + TcfTrkIdEvent(t, id), m_pc(pc), m_reason(reason) +{ +} + +void TcfTrkRunControlContextSuspendedEvent::format(QTextStream &str) const +{ + str.setIntegerBase(16); + str << "RunControl: '" << idString() << "' suspended at 0x" + << m_pc << ": '" << m_reason << "'."; + str.setIntegerBase(10); +} + +QString TcfTrkRunControlContextSuspendedEvent::toString() const +{ + QString rc; + QTextStream str(&rc); + format(str); + return rc; +} + +TcfTrkRunControlContextSuspendedEvent::Reason TcfTrkRunControlContextSuspendedEvent::reason() const +{ + if (m_reason == sharedLibrarySuspendReasonC) + return ModuleLoad; + if (m_reason == "Breakpoint") + return BreakPoint; + // 'Data abort exception'/'Thread has panicked' ... unfortunately somewhat unspecific. + if (m_reason.contains("exception") || m_reason.contains("panick")) + return Crash; + return Other; +} + +TcfTrkRunControlModuleLoadContextSuspendedEvent::TcfTrkRunControlModuleLoadContextSuspendedEvent(const QByteArray &id, + const QByteArray &reason, + quint64 pc, + const ModuleLoadEventInfo &mi) : + TcfTrkRunControlContextSuspendedEvent(RunControlModuleLoadSuspended, id, reason, pc), + m_mi(mi) +{ +} + +QString TcfTrkRunControlModuleLoadContextSuspendedEvent::toString() const +{ + QString rc; + QTextStream str(&rc); + TcfTrkRunControlContextSuspendedEvent::format(str); + str << ' '; + m_mi.format(str); + return rc; +} + + +} // namespace tcftrk diff --git a/tools/runonphone/symbianutils/tcftrkmessage.h b/tools/runonphone/symbianutils/tcftrkmessage.h new file mode 100644 index 0000000..8b073c8 --- /dev/null +++ b/tools/runonphone/symbianutils/tcftrkmessage.h @@ -0,0 +1,284 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef TRCFTRKMESSAGE_H +#define TRCFTRKMESSAGE_H + +#include "symbianutils_global.h" + +#include +#include + +QT_BEGIN_NAMESPACE +class QTextStream; +QT_END_NAMESPACE + +namespace tcftrk { + +class JsonValue; +class JsonInputStream; + +enum Services { + LocatorService, + RunControlService, + ProcessesService, + MemoryService, + SettingsService, // non-standard, trk specific + BreakpointsService, + RegistersService, + SimpleRegistersService, // non-standard, trk specific + UnknownService +}; // Note: Check string array 'serviceNamesC' of same size when modifying this. + +// Modes of RunControl/'Resume' (see EDF documentation). +// As of 24.6.2010, RM_RESUME, RM_STEP_OVER, RM_STEP_INTO, +// RM_STEP_OVER_RANGE, RM_STEP_INTO_RANGE are supported with +// RANG_START/RANGE_END parameters. +enum RunControlResumeMode { + RM_RESUME = 0, + RM_STEP_OVER = 1, RM_STEP_INTO = 2, + RM_STEP_OVER_LINE = 3, RM_STEP_INTO_LINE = 4, + RM_STEP_OUT = 5, RM_REVERSE_RESUME = 6, + RM_REVERSE_STEP_OVER = 7, RM_REVERSE_STEP_INTO = 8, + RM_REVERSE_STEP_OVER_LINE = 9, RM_REVERSE_STEP_INTO_LINE = 10, + RM_REVERSE_STEP_OUT = 11, RM_STEP_OVER_RANGE = 12, + RM_STEP_INTO_RANGE = 13, RM_REVERSE_STEP_OVER_RANGE = 14, + RM_REVERSE_STEP_INTO_RANGE = 15 +}; + +SYMBIANUTILS_EXPORT const char *serviceName(Services s); +SYMBIANUTILS_EXPORT Services serviceFromName(const char *); + +// Debug helpers +SYMBIANUTILS_EXPORT QString formatData(const QByteArray &a); +SYMBIANUTILS_EXPORT QString joinByteArrays(const QVector &a, char sep = ','); + +// Context used in 'RunControl contextAdded' events and in reply +// to 'Processes start'. Could be thread or process. +struct SYMBIANUTILS_EXPORT RunControlContext { + enum Flags { + Container = 0x1, HasState = 0x2, CanSuspend = 0x4, + CanTerminate = 0x8 + }; + enum Type { Process, Thread }; + + RunControlContext(); + Type type() const; + unsigned processId() const; + unsigned threadId() const; + + void clear(); + bool parse(const JsonValue &v); + void format(QTextStream &str) const; + QString toString() const; + + // Helper for converting the TCF ids ("p12" or "p12.t34") + static Type typeFromTcfId(const QByteArray &id); + static unsigned processIdFromTcdfId(const QByteArray &id); + static unsigned threadIdFromTcdfId(const QByteArray &id); + static QByteArray tcfId(unsigned processId, unsigned threadId = 0); + + unsigned flags; + unsigned resumeFlags; + QByteArray id; // "p434.t699" + QByteArray osid; // Non-standard: Process or thread id + QByteArray parentId; // Parent process id of a thread. +}; + +// Module load information occuring with 'RunControl contextSuspended' events +struct SYMBIANUTILS_EXPORT ModuleLoadEventInfo { + ModuleLoadEventInfo(); + void clear(); + bool parse(const JsonValue &v); + void format(QTextStream &str) const; + + QByteArray name; + QByteArray file; + bool loaded; + quint64 codeAddress; + quint64 dataAddress; + bool requireResume; +}; + +// Breakpoint as supported by TcfTrk source June 2010 +// TODO: Add watchpoints,etc once they are implemented +struct SYMBIANUTILS_EXPORT Breakpoint { + enum Type { Software, Hardware, Auto }; + + explicit Breakpoint(quint64 loc = 0); + void setContextId(unsigned processId, unsigned threadId = 0); + QString toString() const; + + static QByteArray idFromLocation(quint64 loc); // Automagically determine from location + + Type type; + bool enabled; + int ignoreCount; + QVector contextIds; // Process or thread ids. + QByteArray id; // Id of the breakpoint; + quint64 location; + unsigned size; + bool thumb; +}; + +SYMBIANUTILS_EXPORT JsonInputStream &operator<<(JsonInputStream &str, const Breakpoint &b); + +// Event hierarchy +class SYMBIANUTILS_EXPORT TcfTrkEvent { + Q_DISABLE_COPY(TcfTrkEvent) +public: + enum Type { None, + LocatorHello, + RunControlContextAdded, + RunControlContextRemoved, + RunControlSuspended, + RunControlBreakpointSuspended, + RunControlModuleLoadSuspended, + RunControlResumed + }; + + virtual ~TcfTrkEvent(); + + Type type() const; + virtual QString toString() const; + + static TcfTrkEvent *parseEvent(Services s, const QByteArray &name, const QVector &val); + +protected: + explicit TcfTrkEvent(Type type = None); + +private: + const Type m_type; +}; + +// ServiceHello +class SYMBIANUTILS_EXPORT TcfTrkLocatorHelloEvent : public TcfTrkEvent { +public: + explicit TcfTrkLocatorHelloEvent(const QStringList &); + + const QStringList &services() { return m_services; } + virtual QString toString() const; + +private: + QStringList m_services; +}; + +// Base for events that just have one id as parameter +// (simple suspend) +class SYMBIANUTILS_EXPORT TcfTrkIdEvent : public TcfTrkEvent { +protected: + explicit TcfTrkIdEvent(Type t, const QByteArray &id); +public: + QByteArray id() const { return m_id; } + QString idString() const { return QString::fromUtf8(m_id); } + +private: + const QByteArray m_id; +}; + +// Base for events that just have some ids as parameter +// (context removed) +class SYMBIANUTILS_EXPORT TcfTrkIdsEvent : public TcfTrkEvent { +protected: + explicit TcfTrkIdsEvent(Type t, const QVector &ids); + +public: + QVector ids() const { return m_ids; } + QString joinedIdString(const char sep = ',') const; + +private: + const QVector m_ids; +}; + +// RunControlContextAdded +class SYMBIANUTILS_EXPORT TcfTrkRunControlContextAddedEvent : public TcfTrkEvent { +public: + typedef QVector RunControlContexts; + + explicit TcfTrkRunControlContextAddedEvent(const RunControlContexts &c); + + const RunControlContexts &contexts() const { return m_contexts; } + virtual QString toString() const; + + static TcfTrkRunControlContextAddedEvent *parseEvent(const QVector &val); + +private: + const RunControlContexts m_contexts; +}; + +// RunControlContextRemoved +class SYMBIANUTILS_EXPORT TcfTrkRunControlContextRemovedEvent : public TcfTrkIdsEvent { +public: + explicit TcfTrkRunControlContextRemovedEvent(const QVector &id); + virtual QString toString() const; +}; + +// Simple RunControlContextSuspended (process/thread) +class SYMBIANUTILS_EXPORT TcfTrkRunControlContextSuspendedEvent : public TcfTrkIdEvent { +public: + enum Reason { BreakPoint, ModuleLoad, Crash, Other } ; + + explicit TcfTrkRunControlContextSuspendedEvent(const QByteArray &id, + const QByteArray &reason, + quint64 pc = 0); + virtual QString toString() const; + + quint64 pc() const { return m_pc; } + QByteArray reasonID() const { return m_reason; } + Reason reason() const; + +protected: + explicit TcfTrkRunControlContextSuspendedEvent(Type t, + const QByteArray &id, + const QByteArray &reason, + quint64 pc = 0); + void format(QTextStream &str) const; + +private: + const quint64 m_pc; + const QByteArray m_reason; +}; + +// RunControlContextSuspended due to module load +class SYMBIANUTILS_EXPORT TcfTrkRunControlModuleLoadContextSuspendedEvent : public TcfTrkRunControlContextSuspendedEvent { +public: + explicit TcfTrkRunControlModuleLoadContextSuspendedEvent(const QByteArray &id, + const QByteArray &reason, + quint64 pc, + const ModuleLoadEventInfo &mi); + + virtual QString toString() const; + const ModuleLoadEventInfo &info() const { return m_mi; } + +private: + const ModuleLoadEventInfo m_mi; +}; + +} // namespace tcftrk +#endif // TRCFTRKMESSAGE_H diff --git a/tools/runonphone/symbianutils/trkdevice.cpp b/tools/runonphone/symbianutils/trkdevice.cpp index bd24300..9039184 100644 --- a/tools/runonphone/symbianutils/trkdevice.cpp +++ b/tools/runonphone/symbianutils/trkdevice.cpp @@ -636,10 +636,11 @@ private: void readMessages(); QByteArray m_trkReadBuffer; + bool linkEstablishmentMode; }; ReaderThreadBase::ReaderThreadBase(const QSharedPointer &context) : - m_context(context) + m_context(context), linkEstablishmentMode(true) { static const int trkResultMetaId = qRegisterMetaType(); Q_UNUSED(trkResultMetaId) @@ -662,7 +663,7 @@ void ReaderThreadBase::readMessages() { TrkResult r; QByteArray rawData; - while (extractResult(&m_trkReadBuffer, m_context->serialFrame, &r, &rawData)) { + while (extractResult(&m_trkReadBuffer, m_context->serialFrame, &r, linkEstablishmentMode, &rawData)) { emit messageReceived(r, rawData); } } diff --git a/tools/runonphone/symbianutils/trkutils.cpp b/tools/runonphone/symbianutils/trkutils.cpp index 60e391e..d89da20 100644 --- a/tools/runonphone/symbianutils/trkutils.cpp +++ b/tools/runonphone/symbianutils/trkutils.cpp @@ -52,6 +52,25 @@ namespace trk { +Library::Library() : codeseg(0), dataseg(0), pid(0) +{ +} + +Library::Library(const TrkResult &result) : codeseg(0), dataseg(0), pid(0) +{ + if (result.data.size() < 20) { + qWarning("Invalid trk creation notification received."); + return; + } + + const char *data = result.data.constData(); + pid = extractInt(data + 2); + codeseg = extractInt(data + 10); + dataseg = extractInt(data + 14); + const uint len = extractShort(data + 18); + name = result.data.mid(20, len); +} + TrkAppVersion::TrkAppVersion() { reset(); @@ -77,11 +96,11 @@ void Session::reset() extended1TypeSize = 0; extended2TypeSize = 0; pid = 0; + mainTid = 0; tid = 0; codeseg = 0; dataseg = 0; - currentThread = 0; libraries.clear(); trkAppVersion.reset(); } @@ -143,6 +162,90 @@ QString Session::deviceDescription(unsigned verbose) const return msg.arg(formatTrkVersion(trkAppVersion)); } +QByteArray Session::gdbLibraryList() const +{ + const int count = libraries.size(); + QByteArray response = "l"; + for (int i = 0; i != count; ++i) { + const trk::Library &lib = libraries.at(i); + response += ""; + response += "
    "; + response += "
    "; + response += "
    "; + response += ""; + } + response += ""; + return response; +} + +QByteArray Session::gdbQsDllInfo(int start, int count) const +{ + // Happens with gdb 6.4.50.20060226-cvs / CodeSourcery. + // Never made it into FSF gdb that got qXfer:libraries:read instead. + // http://sourceware.org/ml/gdb/2007-05/msg00038.html + // Name=hexname,TextSeg=textaddr[,DataSeg=dataaddr] + const int libraryCount = libraries.size(); + const int end = count < 0 ? libraryCount : qMin(libraryCount, start + count); + QByteArray response(1, end == libraryCount ? 'l' : 'm'); + for (int i = start; i < end; ++i) { + if (i != start) + response += ';'; + const Library &lib = libraries.at(i); + response += "Name="; + response += lib.name.toHex(); + response += ",TextSeg="; + response += hexNumber(lib.codeseg); + response += ",DataSeg="; + response += hexNumber(lib.dataseg); + } + return response; +} + +QString Session::toString() const +{ + QString rc; + QTextStream str(&rc); + str << "Session: " << deviceDescription(false) << '\n' + << "pid: " << pid << "main thread: " << mainTid + << " current thread: " << tid << ' '; + str.setIntegerBase(16); + str << " code: 0x" << codeseg << " data: 0x" << dataseg << '\n'; + if (const int libCount = libraries.size()) { + str << "Libraries:\n"; + for (int i = 0; i < libCount; i++) + str << " #" << i << ' ' << libraries.at(i).name + << " code: 0x" << libraries.at(i).codeseg + << " data: 0x" << libraries.at(i).dataseg << '\n'; + } + if (const int moduleCount = modules.size()) { + str << "Modules:\n"; + for (int i = 0; i < moduleCount; i++) + str << " #" << i << ' ' << modules.at(i) << '\n'; + } + str.setIntegerBase(10); + if (!addressToBP.isEmpty()) { + typedef QHash::const_iterator BP_ConstIterator; + str << "Breakpoints:\n"; + const BP_ConstIterator cend = addressToBP.constEnd(); + for (BP_ConstIterator it = addressToBP.constBegin(); it != cend; ++it) { + str.setIntegerBase(16); + str << " 0x" << it.key(); + str.setIntegerBase(10); + str << ' ' << it.value() << '\n'; + } + } + + return rc; +} + // -------------- QByteArray decode7d(const QByteArray &ba) @@ -188,18 +291,15 @@ SYMBIANUTILS_EXPORT QString stringFromArray(const QByteArray &ba, int maxLen) QString ascii; const int size = maxLen == -1 ? ba.size() : qMin(ba.size(), maxLen); for (int i = 0; i < size; ++i) { - //if (i == 5 || i == ba.size() - 2) - // str += " "; - int c = byte(ba.at(i)); - str += QString("%1 ").arg(c, 2, 16, QChar('0')); - if (i >= 8 && i < ba.size() - 2) - ascii += QChar(c).isPrint() ? QChar(c) : QChar('.'); + const int c = byte(ba.at(i)); + str += QString::fromAscii("%1 ").arg(c, 2, 16, QChar('0')); + ascii += QChar(c).isPrint() ? QChar(c) : QChar('.'); } if (size != ba.size()) { - str += "..."; - ascii += "..."; + str += QLatin1String("..."); + ascii += QLatin1String("..."); } - return str + " " + ascii; + return str + QLatin1String(" ") + ascii; } SYMBIANUTILS_EXPORT QByteArray hexNumber(uint n, int digits) @@ -299,20 +399,30 @@ ushort isValidTrkResult(const QByteArray &buffer, bool serialFrame, ushort& mux) return firstDelimiterPos != -1 ? firstDelimiterPos : buffer.size(); } -bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *result, QByteArray *rawData) +bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *result, bool &linkEstablishmentMode, QByteArray *rawData) { result->clear(); if(rawData) rawData->clear(); - const ushort len = isValidTrkResult(*buffer, serialFrame, result->multiplex); - if (!len) - return false; + ushort len = isValidTrkResult(*buffer, serialFrame, result->multiplex); // handle receiving application output, which is not a regular command const int delimiterPos = serialFrame ? 4 : 0; + if (linkEstablishmentMode) { + //when "hot connecting" a device, we can receive partial frames. + //this code resyncs by discarding data until a TRK frame is found + while (buffer->length() > delimiterPos + && result->multiplex != MuxTextTrace + && !(result->multiplex == MuxTrk && buffer->at(delimiterPos) == 0x7e)) { + buffer->remove(0,1); + len = isValidTrkResult(*buffer, serialFrame, result->multiplex); + } + } + if (!len) + return false; if (buffer->at(delimiterPos) != 0x7e) { result->isDebugOutput = true; result->data = buffer->mid(delimiterPos, len); - *buffer->remove(0, delimiterPos + len); + buffer->remove(0, delimiterPos + len); return true; } // FIXME: what happens if the length contains 0xfe? @@ -320,7 +430,7 @@ bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *result, QByt const QByteArray data = decode7d(buffer->mid(delimiterPos + 1, len - 2)); if(rawData) *rawData = data; - *buffer->remove(0, delimiterPos + len); + buffer->remove(0, delimiterPos + len); byte sum = 0; for (int i = 0; i < data.size(); ++i) // 3 = 2 * 0xfe + sum @@ -335,6 +445,7 @@ bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *result, QByt //logMessage(" CURR DATA: " << stringFromArray(data)); //QByteArray prefix = "READ BUF: "; //logMessage((prefix + "HEADER: " + stringFromArray(header).toLatin1()).data()); + linkEstablishmentMode = false; //have received a good TRK packet, therefore in sync return true; } diff --git a/tools/runonphone/symbianutils/trkutils.h b/tools/runonphone/symbianutils/trkutils.h index e571028..d365f0d 100644 --- a/tools/runonphone/symbianutils/trkutils.h +++ b/tools/runonphone/symbianutils/trkutils.h @@ -56,6 +56,7 @@ QT_END_NAMESPACE namespace trk { typedef unsigned char byte; +struct TrkResult; enum Command { //meta commands @@ -135,6 +136,20 @@ enum Command { TrkDSPositionFile = 0xd4 }; +enum DSOSItemTypes { + kDSOSProcessItem = 0x0000, + kDSOSThreadItem = 0x0001, + kDSOSDLLItem = 0x0002, + kDSOSAppItem = 0x0003, + kDSOSMemBlockItem = 0x0004, + kDSOSProcAttachItem = 0x0005, + kDSOSThreadAttachItem = 0x0006, + kDSOSProcAttach2Item = 0x0007, + kDSOSProcRunItem = 0x0008, + /* 0x0009 - 0x00ff reserved for general expansion */ + /* 0x0100 - 0xffff available for target-specific use */ +}; + enum SerialMultiplexor { MuxRaw = 0, MuxTextTrace = 0x0102, @@ -164,11 +179,14 @@ SYMBIANUTILS_EXPORT void appendString(QByteArray *ba, const QByteArray &str, End struct SYMBIANUTILS_EXPORT Library { - Library() {} + Library(); + explicit Library(const TrkResult &r); QByteArray name; uint codeseg; uint dataseg; + //library addresses are valid for a given process (depending on memory model, they might be loaded at the same address in all processes or not) + uint pid; }; struct SYMBIANUTILS_EXPORT TrkAppVersion @@ -187,6 +205,11 @@ struct SYMBIANUTILS_EXPORT Session Session(); void reset(); QString deviceDescription(unsigned verbose) const; + QString toString() const; + // Answer to qXfer::libraries + QByteArray gdbLibraryList() const; + // Answer to qsDllInfo, can be sent chunk-wise. + QByteArray gdbQsDllInfo(int start = 0, int count = -1) const; // Trk feedback byte cpuMajor; @@ -198,6 +221,7 @@ struct SYMBIANUTILS_EXPORT Session byte extended2TypeSize; TrkAppVersion trkAppVersion; uint pid; + uint mainTid; uint tid; uint codeseg; uint dataseg; @@ -206,12 +230,7 @@ struct SYMBIANUTILS_EXPORT Session typedef QList Libraries; Libraries libraries; - typedef uint Thread; - typedef QList Threads; - Threads threads; - // Gdb request - uint currentThread; QStringList modules; }; diff --git a/tools/runonphone/symbianutils/trkutils_p.h b/tools/runonphone/symbianutils/trkutils_p.h index 12b0109..05df83a 100644 --- a/tools/runonphone/symbianutils/trkutils_p.h +++ b/tools/runonphone/symbianutils/trkutils_p.h @@ -55,7 +55,7 @@ void appendDateTime(QByteArray *ba, QDateTime dateTime, Endianness = TargetByteO // returns a QByteArray containing optionally // the serial frame [0x01 0x90 ] and 0x7e encoded7d(ba) 0x7e QByteArray frameMessage(byte command, byte token, const QByteArray &data, bool serialFrame); -bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *r, QByteArray *rawData = 0); +bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *r, bool& linkEstablishmentMode, QByteArray *rawData = 0); } // namespace trk -- cgit v0.12 From ae2dfea96819a7b145f083bf39a674df90239066 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 8 Jul 2010 13:49:16 +0200 Subject: Implement just in time debug feature for runonphone When the test being run crashes, runonphone will now retrieve the registers and call stack for the crashing thread from the phone and save to a crash log (compatible with d_exc crash logs, so existing tools can be used to analyse the log) To disable just in time debug, use --nocrashlog on the command line To save the crash logs to a different location, use --crashlogpath otherwise, they are saved to the working directory. To convert the crash logs into human readable form, use the crash analyser carbide plugin from symbian foundation; or another symbian tool that can process d_exc style logs. Reviewed-by: Thomas Zander --- tools/runonphone/main.cpp | 16 ++++ tools/runonphone/trksignalhandler.cpp | 165 +++++++++++++++++++++++++++++++++- tools/runonphone/trksignalhandler.h | 8 ++ 3 files changed, 186 insertions(+), 3 deletions(-) diff --git a/tools/runonphone/main.cpp b/tools/runonphone/main.cpp index 885d029..dc83044 100644 --- a/tools/runonphone/main.cpp +++ b/tools/runonphone/main.cpp @@ -62,6 +62,8 @@ void printUsage(QTextStream& outstream, QString exeName) << "-v, --verbose show debugging output" << endl << "-q, --quiet hide progress messages" << endl << "-d, --download copy file from phone to PC after running test" << endl + << "--nocrashlog Don't capture call stack if test crashes" << endl + << "--crashlogpath Path to save crash logs (default=working dir)" << endl << endl << "USB COM ports can usually be autodetected, use -p or -f to force a specific port." << endl << "If using System TRK, it is possible to copy the program directly to sys/bin on the phone." << endl @@ -85,6 +87,8 @@ int main(int argc, char *argv[]) QString downloadLocalFile; int loglevel=1; int timeout=0; + bool crashlog = true; + QString crashlogpath; QListIterator it(args); it.next(); //skip name of program while (it.hasNext()) { @@ -126,6 +130,12 @@ int main(int argc, char *argv[]) loglevel=2; else if (arg == "--quiet" || arg == "-q") loglevel=0; + else if (arg == "--nocrashlog") + crashlog = false; + else if (arg == "--crashlogpath") { + CHECK_PARAMETER_EXISTS + crashlogpath = it.next(); + } else errstream << "unknown command line option " << arg << endl; } else { @@ -199,6 +209,8 @@ int main(int argc, char *argv[]) TrkSignalHandler handler; handler.setLogLevel(loglevel); + handler.setCrashLogging(crashlog); + handler.setCrashLogPath(crashlogpath); QObject::connect(launcher.data(), SIGNAL(copyingStarted()), &handler, SLOT(copyingStarted())); QObject::connect(launcher.data(), SIGNAL(canNotConnect(const QString &)), &handler, SLOT(canNotConnect(const QString &))); @@ -215,8 +227,12 @@ int main(int argc, char *argv[]) QObject::connect(launcher.data(), SIGNAL(copyProgress(int)), &handler, SLOT(copyProgress(int))); QObject::connect(launcher.data(), SIGNAL(stateChanged(int)), &handler, SLOT(stateChanged(int))); QObject::connect(launcher.data(), SIGNAL(processStopped(uint,uint,uint,QString)), &handler, SLOT(stopped(uint,uint,uint,QString))); + QObject::connect(launcher.data(), SIGNAL(libraryLoaded(trk::Library)), &handler, SLOT(libraryLoaded(trk::Library))); + QObject::connect(launcher.data(), SIGNAL(libraryUnloaded(trk::Library)), &handler, SLOT(libraryUnloaded(trk::Library))); + QObject::connect(launcher.data(), SIGNAL(registersAndCallStackReadComplete(const QList &,const QByteArray &)), &handler, SLOT(registersAndCallStackReadComplete(const QList &,const QByteArray &))); QObject::connect(&handler, SIGNAL(resume(uint,uint)), launcher.data(), SLOT(resumeProcess(uint,uint))); QObject::connect(&handler, SIGNAL(terminate()), launcher.data(), SLOT(terminate())); + QObject::connect(&handler, SIGNAL(getRegistersAndCallStack(uint,uint)), launcher.data(), SLOT(getRegistersAndCallStack(uint,uint))); QObject::connect(launcher.data(), SIGNAL(finished()), &handler, SLOT(finished())); QTimer timer; diff --git a/tools/runonphone/trksignalhandler.cpp b/tools/runonphone/trksignalhandler.cpp index 2abf91f..b6d446f 100644 --- a/tools/runonphone/trksignalhandler.cpp +++ b/tools/runonphone/trksignalhandler.cpp @@ -42,7 +42,19 @@ #include #include #include +#include +#include #include "trksignalhandler.h" +#include "trkutils.h" + +class CrashState +{ +public: + uint pid; + uint tid; + QString crashReason; + uint crashPC; +}; class TrkSignalHandlerPrivate { @@ -55,6 +67,12 @@ private: QTextStream err; int loglevel; int lastpercent; + QList libraries; + QFile crashlogtextfile; + QFile crashstackfile; + QList queuedCrashes; + QString crashlogPath; + bool crashlog; }; void TrkSignalHandler::copyingStarted() @@ -108,6 +126,7 @@ void TrkSignalHandler::startingApplication() void TrkSignalHandler::applicationRunning(uint pid) { + Q_UNUSED(pid) if (d->loglevel > 0) d->out << "Running..." << endl; } @@ -155,13 +174,153 @@ void TrkSignalHandler::setLogLevel(int level) d->loglevel = level; } +void TrkSignalHandler::setCrashLogging(bool enabled) +{ + d->crashlog = enabled; +} + +void TrkSignalHandler::setCrashLogPath(QString path) +{ + d->crashlogPath = path; +} + +bool lessThanCodeBase(const trk::Library& cs1, const trk::Library& cs2) +{ + return cs1.codeseg < cs2.codeseg; +} + void TrkSignalHandler::stopped(uint pc, uint pid, uint tid, const QString& reason) { d->err << "STOPPED: pc=" << hex << pc << " pid=" << pid << " tid=" << tid << dec << " - " << reason << endl; - // if it was a breakpoint, then we could continue with "emit resume(pid, tid);" - // since we have set no breakpoints, it will be a just in time debug of a panic / exception - emit terminate(); + + if (d->crashlog) { + CrashState cs; + cs.pid = pid; + cs.tid = tid; + cs.crashPC = pc; + cs.crashReason = reason; + + d->queuedCrashes.append(cs); + + if (d->queuedCrashes.count() == 1) { + d->err << "Fetching registers and stack..." << endl; + emit getRegistersAndCallStack(pid, tid); + } + } + else + emit resume(pid, tid); +} + +void TrkSignalHandler::registersAndCallStackReadComplete(const QList& registers, const QByteArray& stack) +{ + CrashState cs = d->queuedCrashes.first(); + QDir dir(d->crashlogPath); + d->crashlogtextfile.setFileName(dir.filePath(QString("d_exc_%1.txt").arg(cs.tid))); + d->crashstackfile.setFileName(dir.filePath(QString("d_exc_%1.stk").arg(cs.tid))); + d->crashlogtextfile.open(QIODevice::WriteOnly); + QTextStream crashlog(&d->crashlogtextfile); + + crashlog << "-----------------------------------------------------------------------------" << endl; + crashlog << "EKA2 USER CRASH LOG" << endl; + crashlog << "Thread Name: " << QString("ProcessID-%1::ThreadID-%2").arg(cs.pid).arg(cs.tid) << endl; + crashlog << "Thread ID: " << cs.tid << endl; + //this is wrong, but TRK doesn't make stack limit available so we lie + crashlog << QString("User Stack %1-%2").arg(registers.at(13), 8, 16, QChar('0')).arg(registers.at(13) + stack.size(), 8, 16, QChar('0')) << endl; + //this is also wrong, but TRK doesn't give all information for exceptions + crashlog << QString("Panic: PC=%1 ").arg(cs.crashPC, 8, 16, QChar('0')) << cs.crashReason << endl; + crashlog << endl; + crashlog << "USER REGISTERS:" << endl; + crashlog << QString("CPSR=%1").arg(registers.at(16), 8, 16, QChar('0')) << endl; + for (int i=0;i<16;i+=4) { + crashlog << QString("r%1=%2 %3 %4 %5") + .arg(i, 2, 10, QChar('0')) + .arg(registers.at(i), 8, 16, QChar('0')) + .arg(registers.at(i+1), 8, 16, QChar('0')) + .arg(registers.at(i+2), 8, 16, QChar('0')) + .arg(registers.at(i+3), 8, 16, QChar('0')) << endl; + } + crashlog << endl; + + //emit info for post mortem debug + qSort(d->libraries.begin(), d->libraries.end(), lessThanCodeBase); + d->err << "Code Segments:" << endl; + crashlog << "CODE SEGMENTS:" << endl; + for(int i=0; ilibraries.count(); i++) { + const trk::Library& seg = d->libraries.at(i); + if(seg.pid != cs.pid) + continue; + if (d->loglevel > 1) { + d->err << QString("Code: %1 Data: %2 Name: ") + .arg(seg.codeseg, 8, 16, QChar('0')) + .arg(seg.dataseg, 8, 16, QChar('0')) + << seg.name << endl; + } + + //produce fake code segment end addresses since we don't get the real ones from TRK + uint end; + if (i+1 < d->libraries.count()) + end = d->libraries.at(i+1).codeseg - 1; + else + end = 0xFFFFFFFF; + + crashlog << QString("%1-%2 ") + .arg(seg.codeseg, 8, 16, QChar('0')) + .arg(end, 8, 16, QChar('0')) + << seg.name << endl; + } + + d->crashlogtextfile.close(); + + if (d->loglevel > 1) { + d->err << "Registers:" << endl; + for (int i=0;i<16;i++) { + d->err << QString("R%1: %2 ").arg(i, 2, 10, QChar('0')).arg(registers.at(i), 8, 16, QChar('0')); + if (i % 4 == 3) + d->err << endl; + } + d->err << QString("CPSR: %1").arg(registers.at(16), 8, 16, QChar('0')) << endl; + + d->err << "Stack:" << endl; + uint sp = registers.at(13); + for(int i=0; ierr << QString("%1: ").arg(sp, 8, 16, QChar('0')); + d->err << trk::stringFromArray(stack.mid(i,16)); + d->err << endl; + } + } + d->crashstackfile.open(QIODevice::WriteOnly); + d->crashstackfile.write(stack); + d->crashstackfile.close(); + + if (d->loglevel > 0) + d->err << "Crash logs saved to " << d->crashlogtextfile.fileName() << " & " << d->crashstackfile.fileName() << endl; + + // resume the thread to allow Symbian OS to handle the panic normally. + // terminate when a non main thread is suspended reboots the phone (TRK bug) + emit resume(cs.pid, cs.tid); + + //fetch next crashed thread + d->queuedCrashes.removeFirst(); + if (d->queuedCrashes.count()) { + cs = d->queuedCrashes.first(); + d->err << "Fetching registers and stack..." << endl; + emit getRegistersAndCallStack(cs.pid, cs.tid); + } + +} + +void TrkSignalHandler::libraryLoaded(const trk::Library &lib) +{ + d->libraries << lib; +} + +void TrkSignalHandler::libraryUnloaded(const trk::Library &lib) +{ + for (QList::iterator i = d->libraries.begin(); i != d->libraries.end(); i++) { + if((*i).name == lib.name && (*i).pid == lib.pid) + i = d->libraries.erase(i); + } } void TrkSignalHandler::timeout() diff --git a/tools/runonphone/trksignalhandler.h b/tools/runonphone/trksignalhandler.h index d31e46f..bfe2c3e 100644 --- a/tools/runonphone/trksignalhandler.h +++ b/tools/runonphone/trksignalhandler.h @@ -43,6 +43,7 @@ #define TRKSIGNALHANDLER_H #include #include +#include "symbianutils/trkutils.h" class TrkSignalHandlerPrivate; class TrkSignalHandler : public QObject @@ -66,13 +67,20 @@ public slots: void stateChanged(int); void stopped(uint pc, uint pid, uint tid, const QString& reason); void timeout(); + void libraryLoaded(const trk::Library &lib); + void libraryUnloaded(const trk::Library &lib); + void registersAndCallStackReadComplete(const QList& registers, const QByteArray& stack); signals: void resume(uint pid, uint tid); + void stop(uint pid, uint tid); void terminate(); + void getRegistersAndCallStack(uint pid, uint tid); public: TrkSignalHandler(); ~TrkSignalHandler(); void setLogLevel(int); + void setCrashLogging(bool); + void setCrashLogPath(QString); private: TrkSignalHandlerPrivate *d; }; -- cgit v0.12 From 83e3f716c795a8be0a6e5d6aa4d6ff51a994cae1 Mon Sep 17 00:00:00 2001 From: Jason McDonald Date: Fri, 9 Jul 2010 14:39:21 +1000 Subject: Fix qdoc warning. Reviewed-by: Trust Me --- src/network/access/qnetworkrequest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index 911eadc..bccfec1 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -215,7 +215,7 @@ QT_BEGIN_NAMESPACE \since 4.7 - \value AuthenticationReuseControlAttribute + \value AuthenticationReuseAttribute Requests only, type: QVariant::Int (default: QNetworkRequest::Automatic) Indicates whether to use cached authorization credentials in the request, if available. If this is set to QNetworkRequest::Manual and the authentication -- cgit v0.12 From 5c50c6a782b127442c3fa748b3dd4d1007db69dc Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 9 Jul 2010 10:01:30 +0200 Subject: Updated WebKit to ad96ca2f9b57271da4ea7432022ac686ee0981c2 Integrated changes: || || FrameView's layout root can be detached by style recalc || || || innerHTML decompilation issues in textarea || || || REGRESSION: Trailing colon on hostnames (with no port specified) causes "Not allowed to use restricted network port" || || || [XHR] Cross-Origin synchronous request with credential raises NETWORK_ERR || || || Cross-origin bypass: iFrame.src can be set to a JavaScript URL via nodeValue or textContent || || || WebKit crash on WebCore::Node::nodeIndex() || || || Cross-origin bypass: Javascript URL can be set as iframe.src via multiple DOM aliases || || || [Qt] Rename QWebSettings::XSSAuditorEnabled to XSSAuditingEnabled || || || Use of stale pointers whilst normalizing DOM nodes with mutation event handlers that modify element attributes || || || [Qt] Canvas arcTo() should draw straight line to p1 if p0, p1 and p2 are collinear || || || [Qt]: REGRESSION(r58703): QWebSettings::JavascriptCanAccessClipboard has wrong case in "Javascript" part. || || || focus() behavior permits keystrokes to be redirected across domains || || || Crash in WebCore::toAlphabetic() while running MangleMe || || || WebKit should treat port numbers outside of the valid range as being blacklisted || || || Make sure that http URLs always have a host in SecurityOrigin || || || ZDI-CAN-765: CSS Charset Text Transformation Vulnerability || || || Cross-origin image theft via SVGs as a canvas pattern || || || [sg:high] Copying text to the system clipboard can be done in any context || || || REGRESSION (r47291): XHR allows arbitrary XSRF across domains || || || REGRESSION (4.0.5): Safari asks for credentials all the time when authenticating to Windows IIS Server || || || Memory Corruption with Drag-Drop item from a purged document. || || || Frame.src allows javascript URLs with starting spaces || || || Table layout crash bug || --- src/3rdparty/webkit/.tag | 2 +- src/3rdparty/webkit/VERSION | 2 +- src/3rdparty/webkit/WebCore/ChangeLog | 502 +++++++++++++++++++++ .../webkit/WebCore/bindings/js/JSAttrCustom.cpp | 10 +- .../webkit/WebCore/bindings/js/JSDOMBinding.cpp | 12 + .../webkit/WebCore/bindings/js/JSDOMBinding.h | 2 + .../webkit/WebCore/bindings/js/JSElementCustom.cpp | 11 +- .../WebCore/bindings/js/JSNamedNodeMapCustom.cpp | 32 ++ .../webkit/WebCore/bindings/js/JSNodeCustom.cpp | 70 ++- src/3rdparty/webkit/WebCore/css/CSSHelper.cpp | 6 +- src/3rdparty/webkit/WebCore/dom/Attr.idl | 2 + src/3rdparty/webkit/WebCore/dom/ContainerNode.cpp | 47 +- src/3rdparty/webkit/WebCore/dom/Document.cpp | 22 + src/3rdparty/webkit/WebCore/dom/Document.h | 3 + src/3rdparty/webkit/WebCore/dom/Element.cpp | 14 +- src/3rdparty/webkit/WebCore/dom/NamedAttrMap.cpp | 5 + src/3rdparty/webkit/WebCore/dom/NamedAttrMap.h | 2 + src/3rdparty/webkit/WebCore/dom/NamedNodeMap.idl | 4 +- src/3rdparty/webkit/WebCore/dom/Node.idl | 4 +- src/3rdparty/webkit/WebCore/dom/Range.cpp | 25 + src/3rdparty/webkit/WebCore/dom/Range.h | 1 + .../webkit/WebCore/editing/EditorCommand.cpp | 21 +- src/3rdparty/webkit/WebCore/editing/markup.cpp | 4 +- .../webkit/WebCore/generated/JSNamedNodeMap.cpp | 18 +- .../webkit/WebCore/generated/JSNamedNodeMap.h | 4 + src/3rdparty/webkit/WebCore/generated/JSNode.cpp | 12 +- src/3rdparty/webkit/WebCore/generated/JSNode.h | 4 + .../html/canvas/CanvasRenderingContext2D.cpp | 2 +- .../WebCore/loader/DocumentThreadableLoader.cpp | 29 +- .../webkit/WebCore/page/DragController.cpp | 8 +- src/3rdparty/webkit/WebCore/page/DragController.h | 8 +- src/3rdparty/webkit/WebCore/page/EventHandler.cpp | 8 +- src/3rdparty/webkit/WebCore/page/FrameView.cpp | 7 +- .../webkit/WebCore/page/SecurityOrigin.cpp | 18 + src/3rdparty/webkit/WebCore/page/Settings.cpp | 6 + src/3rdparty/webkit/WebCore/page/Settings.h | 4 + src/3rdparty/webkit/WebCore/platform/KURL.cpp | 18 +- .../webkit/WebCore/platform/KURLGoogle.cpp | 10 +- .../webkit/WebCore/platform/graphics/qt/PathQt.cpp | 43 +- .../WebCore/platform/network/ProtectionSpace.h | 1 + .../webkit/WebCore/rendering/FixedTableLayout.cpp | 3 +- .../webkit/WebCore/rendering/RenderButton.h | 4 +- .../webkit/WebCore/rendering/RenderDataGrid.h | 2 + .../WebCore/rendering/RenderFileUploadControl.h | 2 + .../webkit/WebCore/rendering/RenderInline.cpp | 2 +- .../webkit/WebCore/rendering/RenderLayer.cpp | 27 +- .../webkit/WebCore/rendering/RenderListItem.h | 2 + .../webkit/WebCore/rendering/RenderListMarker.cpp | 6 +- .../webkit/WebCore/rendering/RenderMedia.h | 2 + .../webkit/WebCore/rendering/RenderMenuList.h | 2 + .../webkit/WebCore/rendering/RenderObject.h | 3 +- .../webkit/WebCore/rendering/RenderProgress.h | 2 + .../webkit/WebCore/rendering/RenderSlider.h | 2 + .../webkit/WebCore/rendering/RenderText.cpp | 2 +- .../webkit/WebCore/rendering/RenderTextControl.h | 2 + .../WebCore/rendering/RenderTextFragment.cpp | 4 +- src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.cpp | 5 +- src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.h | 2 +- src/3rdparty/webkit/WebKit/qt/ChangeLog | 62 +++ 59 files changed, 979 insertions(+), 160 deletions(-) diff --git a/src/3rdparty/webkit/.tag b/src/3rdparty/webkit/.tag index 0b824b7..1d1c8ed 100644 --- a/src/3rdparty/webkit/.tag +++ b/src/3rdparty/webkit/.tag @@ -1 +1 @@ -d59845f6fec84f15da116f50a1a0e52ce26116e9 +ad96ca2f9b57271da4ea7432022ac686ee0981c2 diff --git a/src/3rdparty/webkit/VERSION b/src/3rdparty/webkit/VERSION index c970745..2e5ebd0 100644 --- a/src/3rdparty/webkit/VERSION +++ b/src/3rdparty/webkit/VERSION @@ -4,4 +4,4 @@ This is a snapshot of the Qt port of WebKit from and has the sha1 checksum - d59845f6fec84f15da116f50a1a0e52ce26116e9 + ad96ca2f9b57271da4ea7432022ac686ee0981c2 diff --git a/src/3rdparty/webkit/WebCore/ChangeLog b/src/3rdparty/webkit/WebCore/ChangeLog index a4ae758..a993a97 100644 --- a/src/3rdparty/webkit/WebCore/ChangeLog +++ b/src/3rdparty/webkit/WebCore/ChangeLog @@ -1,3 +1,505 @@ +2010-05-14 Abhishek Arya + + Reviewed by David Hyatt. + + Move the m_width(Length) and m_columns(RenderTable::ColumnStruct) + vector out-of-bounds check out of the ASSERT into the main code. + https://bugs.webkit.org/show_bug.cgi?id=38261 + + Test: fast/table/fixed-table-layout-large-colspan-crash.html + + * rendering/FixedTableLayout.cpp: + (WebCore::FixedTableLayout::calcWidthArray): + +2010-05-21 Beth Dakin + + Reviewed by Darin Adler. + + Fix for Crash in WebCore::toAlphabetic() + while running MangleMe + -and corresponding- + https://bugs.webkit.org/show_bug.cgi?id=39508 + + The math was slightly off here, and we wound up trying to access an + array at index -1 in some cases. We need to decrement numberShadow + rather than subtracting one from the result of the modulo + operation. + + * rendering/RenderListMarker.cpp: + (WebCore::toAlphabeticOrNumeric): + +2010-05-20 Dan Bernstein + + Reviewed by Dave Hyatt. + + Textarea using custom font appears blank + + Test: fast/css/font-face-in-shadow-DOM.html + + When a remote font is loaded, CSSFontSelector forces a style recalc, which replaces all + RenderSyles that have FontFallbackLists referencing the placeholder font with fresh + RenderStyles. However, it does not descend into shadow DOM trees, so those may end up with + styles that still reference the placeholder font. + + The fix is to add RenderObject::requiresForcedStyleRecalcPropagation() and have it return + true from renderers that maintain shadow DOM trees or otherwise keep their own RenderStyles. + + * dom/Element.cpp: + (WebCore::Element::recalcStyle): Check if forced style recalc needs to propagated. + * rendering/RenderButton.h: + (WebCore::RenderButton::requiresForcedStyleRecalcPropagation): + * rendering/RenderDataGrid.h: + (WebCore::RenderDataGrid::requiresForcedStyleRecalcPropagation): + * rendering/RenderFileUploadControl.h: + (WebCore::RenderFileUploadControl::requiresForcedStyleRecalcPropagation): + * rendering/RenderListItem.h: + (WebCore::RenderListItem::requiresForcedStyleRecalcPropagation): + * rendering/RenderMedia.h: + (WebCore::RenderMedia::requiresForcedStyleRecalcPropagation): + * rendering/RenderMenuList.h: + (WebCore::RenderMenuList::RenderMenuList::requiresForcedStyleRecalcPropagation): + * rendering/RenderObject.h: + (WebCore::RenderObject::requiresForcedStyleRecalcPropagation): + * rendering/RenderProgress.h: + (WebCore::RenderProgress::requiresForcedStyleRecalcPropagation): + * rendering/RenderSlider.h: + (WebCore::RenderSlider::requiresForcedStyleRecalcPropagation): + * rendering/RenderTextControl.h: + (WebCore::RenderTextControl::requiresForcedStyleRecalcPropagation): + +2010-04-02 Justin Schuh + + Reviewed by Alexey Proskuryakov. + + XHR allows arbitrary XSRF across domains + https://bugs.webkit.org/show_bug.cgi?id=36843 + + Added a one-line change to prevent bypassing the XDC check on + synchronous preflighted requests. Added layout tests to cover + variations of this problem. + + Tests: http/tests/xmlhttprequest/access-control-preflight-async-header-denied.html + http/tests/xmlhttprequest/access-control-preflight-async-method-denied.html + http/tests/xmlhttprequest/access-control-preflight-sync-header-denied.html + http/tests/xmlhttprequest/access-control-preflight-sync-method-denied.html + + * loader/DocumentThreadableLoader.cpp: + (WebCore::DocumentThreadableLoader::preflightFailure): + +2010-04-28 Julien Chaffraix + + Reviewed by Alexey Proskuryakov. + + [XHR] Cross-Origin synchronous request with credential raises NETWORK_ERR + https://bugs.webkit.org/show_bug.cgi?id=37781 + + + Tests: http/tests/xmlhttprequest/access-control-preflight-credential-async.html + http/tests/xmlhttprequest/access-control-preflight-credential-sync.html + + Rolling the patch in as I could not reproduce Qt results locally. + + * loader/DocumentThreadableLoader.cpp: + (WebCore::DocumentThreadableLoader::DocumentThreadableLoader): Now we remove the + credential from the request here to avoid forgetting to do so in the different code path. + (WebCore::DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest): Just add the + "Origin" header. + (WebCore::DocumentThreadableLoader::loadRequest): Check here the the credential have + been removed so that we don't leak them. Also tweaked a comment to make it clear that + the URL check has issue when credential is involved. + +2010-04-21 Alexey Proskuryakov + + Reviewed by Adam Roben. + + Windows build fix. + + * platform/network/cf/ResourceHandleCFNet.cpp: Declare CFURLConnectionCreateWithProperties + for now, as it's mistakenly missing from WebKitSupportLibrary headers. + +2010-05-19 Abhishek Arya + + Reviewed by David Hyatt. + + Check that the node is a text node before doing a static cast + to a Text class pointer. + https://bugs.webkit.org/show_bug.cgi?id=38626 + + Test: fast/text/text-transform-nontext-node-crash.xhtml + + * rendering/RenderText.cpp: + (WebCore::RenderText::originalText): + * rendering/RenderTextFragment.cpp: + (WebCore::RenderTextFragment::originalText): + (WebCore::RenderTextFragment::previousCharacter): + +2010-05-12 Abhishek Arya + + Reviewed by Darin Adler. + + HTML Entity Escape the contents of a textarea node when accessed + via the innerHTML and outerHTML node properties. + https://bugs.webkit.org/show_bug.cgi?id=38922 + + Test: fast/innerHTML/innerHTML-special-elements.html + + * editing/markup.cpp: + (WebCore::appendStartMarkup): + +2010-05-12 James Robinson + + Patch by Dan Bernstein. + + Reviewed by David Hyatt. + + Fix marking the layout root's parent as needing layout + https://bugs.webkit.org/show_bug.cgi?id=37760 + + If an element gets marked as needing layout due to the recalcStyle() + call in FrameView::layout(), the m_layoutSchedulingEnabled flag will + be set to false. It's possible at this point that a parent of the + existing FrameView::m_layoutRoot will be marked as needing layout. + + This patch updates FrameView::scheduleRelayoutOfSubtree to account + for this case. + + Manual test only due to subtle timing issues. + + * manual-tests/layoutroot_detach.xml: Added. + * page/FrameView.cpp: + (WebCore::FrameView::scheduleRelayoutOfSubtree): + +2010-05-10 Sam Weinig + + Reviewed by Darin Adler. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=38583 + Crash in Element::normalizeAttributes. + + Test: fast/dom/Element/normalize-crash.html + + * dom/Element.cpp: + (WebCore::Element::normalizeAttributes): Copy attributes to a vector + before iterating. + * dom/NamedAttrMap.cpp: + (WebCore::NamedNodeMap::copyAttributesToVector): Added. + * dom/NamedAttrMap.h: + +2010-05-10 Alexey Proskuryakov + + Reviewed by Darin Adler. + + Based on a patch by Eric Seidel. + + https://bugs.webkit.org/show_bug.cgi?id=28697 + WebKit crash on WebCore::Node::nodeIndex() + + It's not OK to call ContainerNode::willRemoveChild() in a loop, because Range code assumes + that it can adjust start and end position to any node except for the one being removed - + so these notifications cannot be batched. + + Test: fast/dom/Range/remove-all-children-crash.html + + * dom/ContainerNode.cpp: + (WebCore::willRemoveChild): Removed unused ExceptionCode. + (WebCore::willRemoveChildren): New function, used in removeChildren() case. + (WebCore::ContainerNode::removeChild): ExceptionCode return was always 0, don't bother with it. + (WebCore::ContainerNode::removeChildren): Call willRemoveChildrenFromNode. + (WebCore::dispatchChildRemovalEvents): Moved some logic out into willRemoveChildrenFromNode + and willRemoveChild. + + * dom/Document.cpp: + (WebCore::Document::nodeChildrenWillBeRemoved): New function, used in removeChildren() case. + + * dom/Document.h: + (WebCore::Document::nodeChildrenWillBeRemoved): New function, used in removeChildren() case. + + * dom/Range.h: + * dom/Range.cpp: + (WebCore::boundaryNodeChildrenWillBeRemoved): New function, used in removeChildren() case. + (WebCore::Range::nodeChildrenWillBeRemoved): Ditto. + +2010-05-03 Alexey Proskuryakov + + Reviewed by Adam Barth. + + https://bugs.webkit.org/show_bug.cgi?id=38497 + Make sure that http URLs always have a host in SecurityOrigin + + This is a hardening fix, and behavior really depends on what an underlying networking layer + does. So, no test. + + * page/SecurityOrigin.cpp: + (WebCore::schemeRequiresAuthority): List schemes that need an authority for successful loading. + (WebCore::SecurityOrigin::SecurityOrigin): Never let e.g. http origins with empty authorities + have the same security origin. + +2010-05-03 Abhishek Arya + + Reviewed by Adam Barth. + + Add support for controlling clipboard access from javascript. + Clipboard access from javascript is disabled by default. + https://bugs.webkit.org/show_bug.cgi?id=27751 + + Test: editing/execCommand/clipboard-access.html + + * WebCore.base.exp: + * editing/EditorCommand.cpp: + (WebCore::supportedCopyCut): + (WebCore::supportedPaste): + (WebCore::createCommandMap): + * page/Settings.cpp: + (WebCore::Settings::Settings): + (WebCore::Settings::setJavaScriptCanAccessClipboard): + * page/Settings.h: + (WebCore::Settings::javaScriptCanAccessClipboard): + +2010-04-30 Abhishek Arya + + Reviewed by David Kilzer. + + Convert m_documentUnderMouse, m_dragInitiator to RefPtr. + Eliminated unused m_dragInitiator accessor to prevent dereferencing. + https://bugs.webkit.org/show_bug.cgi?id=37618 + + Test: editing/pasteboard/drag-drop-iframe-refresh-crash.html + + * page/DragController.cpp: + (WebCore::DragController::tryDocumentDrag): + (WebCore::DragController::concludeEditDrag): + * page/DragController.h: + (WebCore::DragController::draggingImageURL): + (WebCore::DragController::documentUnderMouse): + +2010-04-14 Justin Schuh + + Reviewed by Adam Barth. + + Javascript URL can be set as iframe.src via multiple DOM aliases + https://bugs.webkit.org/show_bug.cgi?id=37031 + + Moved frame/iframe checks from Attr to Node on inherited members. + Node child manipulation methods now return NOT_SUPPORTED_ERR if used + on a frame/iframe src attribute. + NamedNodeMap set methods now perform frame/iframe src checks. + Moved allowSettingSrcToJavascriptURL static helper function from + JSElementCustom.cpp to exported function in JSDOMBinding.h. + + * bindings/js/JSAttrCustom.cpp: + (WebCore::JSAttr::setValue): + * bindings/js/JSDOMBinding.cpp: + (WebCore::allowSettingSrcToJavascriptURL): + * bindings/js/JSDOMBinding.h: + * bindings/js/JSElementCustom.cpp: + * bindings/js/JSNamedNodeMapCustom.cpp: + (WebCore::JSNamedNodeMap::setNamedItem): + (WebCore::JSNamedNodeMap::setNamedItemNS): + * bindings/js/JSNodeCustom.cpp: + (WebCore::isAttrFrameSrc): + (WebCore::JSNode::setNodeValue): + (WebCore::JSNode::setTextContent): + (WebCore::JSNode::insertBefore): + (WebCore::JSNode::replaceChild): + (WebCore::JSNode::removeChild): + (WebCore::JSNode::appendChild): + * bindings/v8/custom/V8AttrCustom.cpp: + * bindings/v8/custom/V8NamedNodeMapCustom.cpp: + (WebCore::V8NamedNodeMap::setNamedItemNSCallback): + (WebCore::V8NamedNodeMap::setNamedItemCallback): + (WebCore::toV8): + * bindings/v8/custom/V8NodeCustom.cpp: + (WebCore::isFrameSrc): + (WebCore::V8Node::textContentAccessorSetter): + (WebCore::V8Node::nodeValueAccessorSetter): + (WebCore::V8Node::insertBeforeCallback): + (WebCore::V8Node::replaceChildCallback): + (WebCore::V8Node::removeChildCallback): + (WebCore::V8Node::appendChildCallback): + * dom/Attr.idl: + * dom/NamedNodeMap.idl: + * dom/Node.idl: + +2010-03-26 Justin Schuh + + Reviewed by Adam Barth. + + Security: iFrame.src accepts JavaScript URL via nodeValue or textContent + https://bugs.webkit.org/show_bug.cgi?id=36502 + + Overrode inherited nodeValue and textContent in Attr.idl so they proxy + to value, which performs a security check. + + Test: http/tests/security/xss-DENIED-iframe-src-alias.html + + * bindings/js/JSAttrCustom.cpp: + (WebCore::JSAttr::nodeValue): + (WebCore::JSAttr::setNodeValue): + (WebCore::JSAttr::textContent): + (WebCore::JSAttr::setTextContent): + * bindings/v8/custom/V8AttrCustom.cpp: + (WebCore::V8Attr::nodeValueAccessorSetter): + (WebCore::V8Attr::nodeValueAccessorGetter): + (WebCore::V8Attr::textContentAccessorSetter): + (WebCore::V8Attr::textContentAccessorGetter): + * dom/Attr.idl: + +2010-05-05 Alexey Proskuryakov + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=38260 + Fix whitespace removing in deprecatedParseURL(). + + Broken all the way since r4 (yes, that's a revision number). + + Test: http/tests/security/xss-DENIED-javascript-with-spaces.html + + * css/CSSHelper.cpp: (WebCore::deprecatedParseURL): Fixed loop conditions for remaining length. + +2010-04-23 Dan Bernstein + + Reviewed by Simon Fraser. + + :after content is duplicated + + Test: fast/css-generated-content/after-duplicated-after-split.html + + * rendering/RenderInline.cpp: + (WebCore::RenderInline::splitInlines): Pass the correct owner of the child list. + +2010-03-30 Chris Evans + + Reviewed by Adam Barth. + + Taint the canvas if an SVG-derived pattern is rendered into it. + + https://bugs.webkit.org/show_bug.cgi?id=36838 + + Test: fast/canvas/svg-taint.html + + * html/canvas/CanvasRenderingContext2D.cpp: + (WebCore::CanvasRenderingContext2D::createPattern): + Take into account the image's hasSingleSecurityOrigin() property. + +2010-04-07 Alexey Proskuryakov + + Reviewed by Darinn Adler. + + https://bugs.webkit.org/show_bug.cgi?id=37230 + REGRESSION (4.0.5): Safari asks for credentials all the time when + authenticating to Windows IIS Server + + * platform/network/ProtectionSpace.h: (WebCore::ProtectionSpaceAuthenticationScheme): Added + a constant for ProtectionSpaceAuthenticationSchemeUnknown. + + * platform/network/cf/AuthenticationCF.cpp: (WebCore::core): + * platform/network/cf/SocketStreamHandleCFNet.cpp: (WebCore::authenticationSchemeFromAuthenticationMethod): + Return ProtectionSpaceAuthenticationSchemeUnknown for unknown scheme. + + * platform/network/mac/AuthenticationMac.mm: + (WebCore::mac): Support NTLM on systems older than 10.6. We actually get this string from + NSURLConnection, even though there was no public constant. + (WebCore::core): Return ProtectionSpaceAuthenticationSchemeUnknown for unknown scheme. + +2010-04-19 Dan Bernstein + + Reviewed by Darin Adler. + + Make the fix for from r57759 more robust. + + * rendering/RenderLayer.cpp: + (WebCore::RenderLayer::updateHoverActiveState): Use RefPtrs for the Nodes. + +2010-04-16 Dan Bernstein + + Reviewed by Simon Fraser. + + Crash when updating hover state + + Test: fast/dynamic/hover-style-recalc-crash.html + + Updating the hover state of an element caused the document to need style + recalc, and then updating the hover state of a link caused style recalc, + which changed the render tree while updateHoverActiveState() was iterating + over it, leading to a crash. + + * rendering/RenderLayer.cpp: + (WebCore::RenderLayer::updateHoverActiveState): Collect the nodes to be + updated into vectors, then update their active and hover states. + +2010-03-31 Mark Rowe + + Reviewed by Darin Adler. + + REGRESSION: Trailing colon on hostnames (with no port specified) causes "Not allowed to use restricted network port" + + * platform/KURL.cpp: + (WebCore::KURL::port): Explicitly handle the case of a colon being present in the URL after the host name but with + no port number before the path. This is handled in the same manner as the colon and port being omitted completely. + +2010-03-24 Mark Rowe + + Revert the portion of r56489 that dealt with port zero as it introduced some test failures. + + * platform/KURL.cpp: + (WebCore::KURL::port): Use the "ok" argument to charactersToUIntStrict to determine whether + it was able to successfully parse the string as an unsigned integer, rather than relying on + the fact it returned zero when it failed. + +2010-03-24 Mark Rowe + + Reviewed by Darin Adler. + + WebKit should treat port numbers outside the valid range as being blacklisted + / + + * platform/KURL.cpp: + (WebCore::KURL::port): Map invalid port numbers to invalidPortNumber. + (WebCore::portAllowed): Add invalidPortNumber to the blacklist. + * platform/KURLGoogle.cpp: invalid port numbers to invalidPortNumber. + (WebCore::KURL::port): Add invalidPortNumber to the blacklist. + Also bring this in to sync with KURL. Having this identical code in two places is stupid. + +2010-05-05 Alexey Proskuryakov + + Reviewed by Adele Peterson. + + https://bugs.webkit.org/show_bug.cgi?id=26824 + EventHandler can operate on a wrong frame if focus changes during + keyboard event dispatch. + + EventHandler object is tied to a frame, so it's wrong for it to continue processing a keyboard + event if focused frame changes between keydown and keypress. + + * manual-tests/focus-change-between-key-events.html: Added. + + * page/EventHandler.cpp: (WebCore::EventHandler::keyEvent): Bail out early if focused frame + changes while dispatching keydown. Also made similar changes for Windows to maintain matching + behavior, even though EventHandler was re-entered anyway due to WM_KEYDOWN and WM_CHAR being + separate events. + +2010-07-02 Tor Arne Vestbø + + Reviewed by Simon Hausmann. + + [Qt] Canvas arcTo() should draw straight line to p1 if p0, p1 and p2 are collinear + + The implementation of PathQt's addArcTo() was not float-safe and also had + a case where it drew an 'infinite' line, which is not part of the spec. + + http://www.whatwg.org/specs/web-apps/current-work/#dom-context-2d-arcto + + We now use qFuzzyCompare() in both cases. The method isPointOnPathBorder() + also had the same problem, and was refactored a bit in the process of fixing + the bug. + + Initial patch by Andreas Kling. + + https://bugs.webkit.org/show_bug.cgi?id=41412 + + * platform/graphics/qt/PathQt.cpp: + 2010-03-26 Shu Chang Reviewed by Eric Seidel. diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSAttrCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSAttrCustom.cpp index 3c01535..4cd40ac 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSAttrCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSAttrCustom.cpp @@ -33,6 +33,7 @@ #include "Document.h" #include "HTMLFrameElementBase.h" #include "HTMLNames.h" +#include "JSDOMBinding.h" using namespace JSC; @@ -46,13 +47,8 @@ void JSAttr::setValue(ExecState* exec, JSValue value) String attrValue = valueToStringWithNullCheck(exec, value); Element* ownerElement = imp->ownerElement(); - if (ownerElement && (ownerElement->hasTagName(iframeTag) || ownerElement->hasTagName(frameTag))) { - if (equalIgnoringCase(imp->name(), "src") && protocolIsJavaScript(deprecatedParseURL(attrValue))) { - Document* contentDocument = static_cast(ownerElement)->contentDocument(); - if (contentDocument && !checkNodeSecurity(exec, contentDocument)) - return; - } - } + if (ownerElement && !allowSettingSrcToJavascriptURL(exec, ownerElement, imp->name(), attrValue)) + return; ExceptionCode ec = 0; imp->setValue(attrValue, ec); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.cpp index f294dad..393c1ee 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.cpp @@ -24,6 +24,7 @@ #include "debugger/DebuggerCallFrame.h" #include "ActiveDOMObject.h" +#include "CSSHelper.h" #include "DOMCoreException.h" #include "DOMObjectHashTableMap.h" #include "Document.h" @@ -33,6 +34,7 @@ #include "Frame.h" #include "HTMLAudioElement.h" #include "HTMLCanvasElement.h" +#include "HTMLFrameElementBase.h" #include "HTMLImageElement.h" #include "HTMLNames.h" #include "HTMLScriptElement.h" @@ -630,6 +632,16 @@ bool shouldAllowNavigation(ExecState* exec, Frame* frame) return lexicalFrame && lexicalFrame->loader()->shouldAllowNavigation(frame); } +bool allowSettingSrcToJavascriptURL(ExecState* exec, Element* element, const String& name, const String& value) +{ + if ((element->hasTagName(iframeTag) || element->hasTagName(frameTag)) && equalIgnoringCase(name, "src") && protocolIsJavaScript(deprecatedParseURL(value))) { + Document* contentDocument = static_cast(element)->contentDocument(); + if (contentDocument && !checkNodeSecurity(exec, contentDocument)) + return false; + } + return true; +} + void printErrorMessageForFrame(Frame* frame, const String& message) { if (!frame) diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.h b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.h index 219472b..40f7e40 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.h +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.h @@ -301,6 +301,8 @@ namespace WebCore { bool allowsAccessFromFrame(JSC::ExecState*, Frame*); bool allowsAccessFromFrame(JSC::ExecState*, Frame*, String& message); bool shouldAllowNavigation(JSC::ExecState*, Frame*); + bool allowSettingSrcToJavascriptURL(JSC::ExecState*, Element*, const String&, const String&); + void printErrorMessageForFrame(Frame*, const String& message); JSC::JSValue objectToStringFunctionGetter(JSC::ExecState*, JSC::JSValue, const JSC::Identifier& propertyName); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSElementCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSElementCustom.cpp index c725290..94012fd 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSElementCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSElementCustom.cpp @@ -36,6 +36,7 @@ #include "HTMLFrameElementBase.h" #include "HTMLNames.h" #include "JSAttr.h" +#include "JSDOMBinding.h" #include "JSHTMLElementWrapperFactory.h" #include "JSNodeList.h" #include "NodeList.h" @@ -63,16 +64,6 @@ void JSElement::markChildren(MarkStack& markStack) markDOMObjectWrapper(markStack, globalData, static_cast(element)->inlineStyleDecl()); } -static inline bool allowSettingSrcToJavascriptURL(ExecState* exec, Element* element, const String& name, const String& value) -{ - if ((element->hasTagName(iframeTag) || element->hasTagName(frameTag)) && equalIgnoringCase(name, "src") && protocolIsJavaScript(deprecatedParseURL(value))) { - Document* contentDocument = static_cast(element)->contentDocument(); - if (contentDocument && !checkNodeSecurity(exec, contentDocument)) - return false; - } - return true; -} - JSValue JSElement::setAttribute(ExecState* exec, const ArgList& args) { ExceptionCode ec = 0; diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSNamedNodeMapCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSNamedNodeMapCustom.cpp index 13f3628..965498a 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSNamedNodeMapCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSNamedNodeMapCustom.cpp @@ -35,6 +35,38 @@ using namespace JSC; namespace WebCore { +JSValue JSNamedNodeMap::setNamedItem(ExecState* exec, const ArgList& args) +{ + NamedNodeMap* imp = static_cast(impl()); + ExceptionCode ec = 0; + Node* newNode = toNode(args.at(0)); + + if (newNode && newNode->nodeType() == Node::ATTRIBUTE_NODE && imp->element()) { + if (!allowSettingSrcToJavascriptURL(exec, imp->element(), newNode->nodeName(), newNode->nodeValue())) + return jsNull(); + } + + JSValue result = toJS(exec, globalObject(), WTF::getPtr(imp->setNamedItem(newNode, ec))); + setDOMException(exec, ec); + return result; +} + +JSValue JSNamedNodeMap::setNamedItemNS(ExecState* exec, const ArgList& args) +{ + NamedNodeMap* imp = static_cast(impl()); + ExceptionCode ec = 0; + Node* newNode = toNode(args.at(0)); + + if (newNode && newNode->nodeType() == Node::ATTRIBUTE_NODE && imp->element()) { + if (!allowSettingSrcToJavascriptURL(exec, imp->element(), newNode->nodeName(), newNode->nodeValue())) + return jsNull(); + } + + JSValue result = toJS(exec, globalObject(), WTF::getPtr(imp->setNamedItemNS(newNode, ec))); + setDOMException(exec, ec); + return result; +} + bool JSNamedNodeMap::canGetItemsForName(ExecState*, NamedNodeMap* impl, const Identifier& propertyName) { return impl->getNamedItem(propertyName); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSNodeCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSNodeCustom.cpp index 134c581..bf6c633 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSNodeCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSNodeCustom.cpp @@ -38,6 +38,7 @@ #include "JSAttr.h" #include "JSCDATASection.h" #include "JSComment.h" +#include "JSDOMBinding.h" #include "JSDocument.h" #include "JSDocumentFragment.h" #include "JSDocumentType.h" @@ -66,12 +67,53 @@ using namespace JSC; namespace WebCore { -typedef int ExpectionCode; +static inline bool isAttrFrameSrc(Element *element, const String& name) +{ + return element && (element->hasTagName(HTMLNames::iframeTag) || element->hasTagName(HTMLNames::frameTag)) && equalIgnoringCase(name, "src"); +} + +void JSNode::setNodeValue(JSC::ExecState* exec, JSC::JSValue value) +{ + Node* imp = static_cast(impl()); + String nodeValue = valueToStringWithNullCheck(exec, value); + + if (imp->nodeType() == Node::ATTRIBUTE_NODE) { + Element* ownerElement = static_cast(impl())->ownerElement(); + if (ownerElement && !allowSettingSrcToJavascriptURL(exec, ownerElement, imp->nodeName(), nodeValue)) + return; + } + + ExceptionCode ec = 0; + imp->setNodeValue(nodeValue, ec); + setDOMException(exec, ec); +} + +void JSNode::setTextContent(JSC::ExecState* exec, JSC::JSValue value) +{ + Node* imp = static_cast(impl()); + String nodeValue = valueToStringWithNullCheck(exec, value); + + if (imp->nodeType() == Node::ATTRIBUTE_NODE) { + Element* ownerElement = static_cast(impl())->ownerElement(); + if (ownerElement && !allowSettingSrcToJavascriptURL(exec, ownerElement, imp->nodeName(), nodeValue)) + return; + } + + ExceptionCode ec = 0; + imp->setTextContent(nodeValue, ec); + setDOMException(exec, ec); +} JSValue JSNode::insertBefore(ExecState* exec, const ArgList& args) { + Node* imp = static_cast(impl()); + if (imp->nodeType() == Node::ATTRIBUTE_NODE && isAttrFrameSrc(static_cast(impl())->ownerElement(), imp->nodeName())) { + setDOMException(exec, NOT_SUPPORTED_ERR); + return jsNull(); + } + ExceptionCode ec = 0; - bool ok = impl()->insertBefore(toNode(args.at(0)), toNode(args.at(1)), ec, true); + bool ok = imp->insertBefore(toNode(args.at(0)), toNode(args.at(1)), ec, true); setDOMException(exec, ec); if (ok) return args.at(0); @@ -80,8 +122,14 @@ JSValue JSNode::insertBefore(ExecState* exec, const ArgList& args) JSValue JSNode::replaceChild(ExecState* exec, const ArgList& args) { + Node* imp = static_cast(impl()); + if (imp->nodeType() == Node::ATTRIBUTE_NODE && isAttrFrameSrc(static_cast(impl())->ownerElement(), imp->nodeName())) { + setDOMException(exec, NOT_SUPPORTED_ERR); + return jsNull(); + } + ExceptionCode ec = 0; - bool ok = impl()->replaceChild(toNode(args.at(0)), toNode(args.at(1)), ec, true); + bool ok = imp->replaceChild(toNode(args.at(0)), toNode(args.at(1)), ec, true); setDOMException(exec, ec); if (ok) return args.at(1); @@ -90,8 +138,14 @@ JSValue JSNode::replaceChild(ExecState* exec, const ArgList& args) JSValue JSNode::removeChild(ExecState* exec, const ArgList& args) { + Node* imp = static_cast(impl()); + if (imp->nodeType() == Node::ATTRIBUTE_NODE && isAttrFrameSrc(static_cast(impl())->ownerElement(), imp->nodeName())) { + setDOMException(exec, NOT_SUPPORTED_ERR); + return jsNull(); + } + ExceptionCode ec = 0; - bool ok = impl()->removeChild(toNode(args.at(0)), ec); + bool ok = imp->removeChild(toNode(args.at(0)), ec); setDOMException(exec, ec); if (ok) return args.at(0); @@ -100,8 +154,14 @@ JSValue JSNode::removeChild(ExecState* exec, const ArgList& args) JSValue JSNode::appendChild(ExecState* exec, const ArgList& args) { + Node* imp = static_cast(impl()); + if (imp->nodeType() == Node::ATTRIBUTE_NODE && isAttrFrameSrc(static_cast(impl())->ownerElement(), imp->nodeName())) { + setDOMException(exec, NOT_SUPPORTED_ERR); + return jsNull(); + } + ExceptionCode ec = 0; - bool ok = impl()->appendChild(toNode(args.at(0)), ec, true); + bool ok = imp->appendChild(toNode(args.at(0)), ec, true); setDOMException(exec, ec); if (ok) return args.at(0); diff --git a/src/3rdparty/webkit/WebCore/css/CSSHelper.cpp b/src/3rdparty/webkit/WebCore/css/CSSHelper.cpp index 8e6f3a0..c3418b4 100644 --- a/src/3rdparty/webkit/WebCore/css/CSSHelper.cpp +++ b/src/3rdparty/webkit/WebCore/css/CSSHelper.cpp @@ -36,7 +36,7 @@ String deprecatedParseURL(const String& url) int o = 0; int l = i->length(); - while (o < l && (*i)[o] <= ' ') { + while (0 < l && (*i)[o] <= ' ') { ++o; --l; } @@ -53,7 +53,7 @@ String deprecatedParseURL(const String& url) l -= 5; } - while (o < l && (*i)[o] <= ' ') { + while (0 < l && (*i)[o] <= ' ') { ++o; --l; } @@ -65,7 +65,7 @@ String deprecatedParseURL(const String& url) l -= 2; } - while (o < l && (*i)[o] <= ' ') { + while (0 < l && (*i)[o] <= ' ') { ++o; --l; } diff --git a/src/3rdparty/webkit/WebCore/dom/Attr.idl b/src/3rdparty/webkit/WebCore/dom/Attr.idl index af84478..3c73bc0 100644 --- a/src/3rdparty/webkit/WebCore/dom/Attr.idl +++ b/src/3rdparty/webkit/WebCore/dom/Attr.idl @@ -28,7 +28,9 @@ module core { // DOM Level 1 readonly attribute [ConvertNullStringTo=Null] DOMString name; + readonly attribute boolean specified; + attribute [ConvertNullStringTo=Null, ConvertNullToNullString, CustomSetter] DOMString value setter raises(DOMException); diff --git a/src/3rdparty/webkit/WebCore/dom/ContainerNode.cpp b/src/3rdparty/webkit/WebCore/dom/ContainerNode.cpp index fb2852f..c17489a 100644 --- a/src/3rdparty/webkit/WebCore/dom/ContainerNode.cpp +++ b/src/3rdparty/webkit/WebCore/dom/ContainerNode.cpp @@ -292,19 +292,32 @@ void ContainerNode::willRemove() Node::willRemove(); } -static ExceptionCode willRemoveChild(Node *child) +static void willRemoveChild(Node* child) { - ExceptionCode ec = 0; + // update auxiliary doc info (e.g. iterators) to note that node is being removed + child->document()->nodeWillBeRemoved(child); + child->document()->incDOMTreeVersion(); // fire removed from document mutation events. dispatchChildRemovalEvents(child); - if (ec) - return ec; if (child->attached()) child->willRemove(); - - return 0; +} + +static void willRemoveChildren(ContainerNode* container) +{ + container->document()->nodeChildrenWillBeRemoved(container); + container->document()->incDOMTreeVersion(); + + // FIXME: Adding new children from event handlers can cause an infinite loop here. + for (RefPtr child = container->firstChild(); child; child = child->nextSibling()) { + // fire removed from document mutation events. + dispatchChildRemovalEvents(child.get()); + + if (child->attached()) + child->willRemove(); + } } bool ContainerNode::removeChild(Node* oldChild, ExceptionCode& ec) @@ -328,10 +341,7 @@ bool ContainerNode::removeChild(Node* oldChild, ExceptionCode& ec) } RefPtr child = oldChild; - - ec = willRemoveChild(child.get()); - if (ec) - return false; + willRemoveChild(child.get()); // Mutation events might have moved this child into a different parent. if (child->parentNode() != this) { @@ -399,14 +409,12 @@ bool ContainerNode::removeChildren() return false; // The container node can be removed from event handlers. - RefPtr protect(this); - + RefPtr protect(this); + // Do any prep work needed before actually starting to detach // and remove... e.g. stop loading frames, fire unload events. - // FIXME: Adding new children from event handlers can cause an infinite loop here. - for (RefPtr n = m_firstChild; n; n = n->nextSibling()) - willRemoveChild(n.get()); - + willRemoveChildren(protect.get()); + // exclude this node when looking for removed focusedNode since only children will be removed document()->removeFocusedNodeOfSubtree(this, true); @@ -936,6 +944,8 @@ static void dispatchChildInsertionEvents(Node* child) static void dispatchChildRemovalEvents(Node* child) { + ASSERT(!eventDispatchForbidden()); + #if ENABLE(INSPECTOR) if (Page* page = child->document()->page()) { if (InspectorController* inspectorController = page->inspectorController()) @@ -946,11 +956,6 @@ static void dispatchChildRemovalEvents(Node* child) RefPtr c = child; RefPtr document = child->document(); - // update auxiliary doc info (e.g. iterators) to note that node is being removed - document->nodeWillBeRemoved(child); - - document->incDOMTreeVersion(); - // dispatch pre-removal mutation events if (c->parentNode() && document->hasListenerType(Document::DOMNODEREMOVED_LISTENER)) c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, c->parentNode())); diff --git a/src/3rdparty/webkit/WebCore/dom/Document.cpp b/src/3rdparty/webkit/WebCore/dom/Document.cpp index 545819d..9803cf5 100644 --- a/src/3rdparty/webkit/WebCore/dom/Document.cpp +++ b/src/3rdparty/webkit/WebCore/dom/Document.cpp @@ -2957,6 +2957,28 @@ void Document::nodeChildrenChanged(ContainerNode* container) } } +void Document::nodeChildrenWillBeRemoved(ContainerNode* container) +{ + if (!disableRangeMutation(page())) { + HashSet::const_iterator end = m_ranges.end(); + for (HashSet::const_iterator it = m_ranges.begin(); it != end; ++it) + (*it)->nodeChildrenWillBeRemoved(container); + } + + HashSet::const_iterator nodeIteratorsEnd = m_nodeIterators.end(); + for (HashSet::const_iterator it = m_nodeIterators.begin(); it != nodeIteratorsEnd; ++it) { + for (Node* n = container->firstChild(); n; n = n->nextSibling()) + (*it)->nodeWillBeRemoved(n); + } + + if (Frame* frame = this->frame()) { + for (Node* n = container->firstChild(); n; n = n->nextSibling()) { + frame->selection()->nodeWillBeRemoved(n); + frame->dragCaretController()->nodeWillBeRemoved(n); + } + } +} + void Document::nodeWillBeRemoved(Node* n) { HashSet::const_iterator nodeIteratorsEnd = m_nodeIterators.end(); diff --git a/src/3rdparty/webkit/WebCore/dom/Document.h b/src/3rdparty/webkit/WebCore/dom/Document.h index 44cdf0d..68927f4 100644 --- a/src/3rdparty/webkit/WebCore/dom/Document.h +++ b/src/3rdparty/webkit/WebCore/dom/Document.h @@ -616,6 +616,9 @@ public: void detachRange(Range*); void nodeChildrenChanged(ContainerNode*); + // nodeChildrenWillBeRemoved is used when removing all node children at once. + void nodeChildrenWillBeRemoved(ContainerNode*); + // nodeWillBeRemoved is only safe when removing one node at a time. void nodeWillBeRemoved(Node*); void textInserted(Node*, unsigned offset, unsigned length); diff --git a/src/3rdparty/webkit/WebCore/dom/Element.cpp b/src/3rdparty/webkit/WebCore/dom/Element.cpp index 6bd512d..a02bb4c 100644 --- a/src/3rdparty/webkit/WebCore/dom/Element.cpp +++ b/src/3rdparty/webkit/WebCore/dom/Element.cpp @@ -937,7 +937,7 @@ void Element::recalcStyle(StyleChange change) newStyle->setChildrenAffectedByDirectAdjacentRules(); } - if (ch != NoChange || pseudoStyleCacheIsInvalid(currentStyle.get(), newStyle.get())) { + if (ch != NoChange || pseudoStyleCacheIsInvalid(currentStyle.get(), newStyle.get()) || change == Force && renderer() && renderer()->requiresForcedStyleRecalcPropagation()) { setRenderStyle(newStyle); } else if (needsStyleRecalc() && (styleChangeType() != SyntheticStyleChange) && (document()->usesSiblingRules() || document()->usesDescendantRules())) { // Although no change occurred, we use the new style so that the cousin style sharing code won't get @@ -1429,9 +1429,15 @@ void Element::normalizeAttributes() NamedNodeMap* attrs = attributes(true); if (!attrs) return; - unsigned numAttrs = attrs->length(); - for (unsigned i = 0; i < numAttrs; i++) { - if (Attr* attr = attrs->attributeItem(i)->attr()) + + if (attrs->isEmpty()) + return; + + Vector > attributeVector; + attrs->copyAttributesToVector(attributeVector); + size_t numAttrs = attributeVector.size(); + for (size_t i = 0; i < numAttrs; ++i) { + if (Attr* attr = attributeVector[i]->attr()) attr->normalize(); } } diff --git a/src/3rdparty/webkit/WebCore/dom/NamedAttrMap.cpp b/src/3rdparty/webkit/WebCore/dom/NamedAttrMap.cpp index d8a6ba8..ee979cf 100644 --- a/src/3rdparty/webkit/WebCore/dom/NamedAttrMap.cpp +++ b/src/3rdparty/webkit/WebCore/dom/NamedAttrMap.cpp @@ -172,6 +172,11 @@ PassRefPtr NamedNodeMap::item(unsigned index) const return m_attributes[index]->createAttrIfNeeded(m_element); } +void NamedNodeMap::copyAttributesToVector(Vector >& copy) +{ + copy = m_attributes; +} + Attribute* NamedNodeMap::getAttributeItemSlowCase(const String& name, bool shouldIgnoreAttributeCase) const { unsigned len = length(); diff --git a/src/3rdparty/webkit/WebCore/dom/NamedAttrMap.h b/src/3rdparty/webkit/WebCore/dom/NamedAttrMap.h index d5136b5..e292576 100644 --- a/src/3rdparty/webkit/WebCore/dom/NamedAttrMap.h +++ b/src/3rdparty/webkit/WebCore/dom/NamedAttrMap.h @@ -72,6 +72,8 @@ public: Attribute* attributeItem(unsigned index) const { return m_attributes[index].get(); } Attribute* getAttributeItem(const QualifiedName&) const; + void copyAttributesToVector(Vector >&); + void shrinkToLength() { m_attributes.shrinkCapacity(length()); } void reserveInitialCapacity(unsigned capacity) { m_attributes.reserveInitialCapacity(capacity); } diff --git a/src/3rdparty/webkit/WebCore/dom/NamedNodeMap.idl b/src/3rdparty/webkit/WebCore/dom/NamedNodeMap.idl index 4d36577..7bfbf23 100644 --- a/src/3rdparty/webkit/WebCore/dom/NamedNodeMap.idl +++ b/src/3rdparty/webkit/WebCore/dom/NamedNodeMap.idl @@ -28,7 +28,7 @@ module core { Node getNamedItem(in DOMString name); - Node setNamedItem(in Node node) + [Custom] Node setNamedItem(in Node node) raises(DOMException); Node removeNamedItem(in DOMString name) @@ -46,7 +46,7 @@ module core { // FIXME: the implementation does take an exceptioncode parameter. /*raises(DOMException)*/; - Node setNamedItemNS(in Node node) + [Custom] Node setNamedItemNS(in Node node) raises(DOMException); [OldStyleObjC] Node removeNamedItemNS(in [ConvertNullToNullString] DOMString namespaceURI, diff --git a/src/3rdparty/webkit/WebCore/dom/Node.idl b/src/3rdparty/webkit/WebCore/dom/Node.idl index 0489316..22d9a85 100644 --- a/src/3rdparty/webkit/WebCore/dom/Node.idl +++ b/src/3rdparty/webkit/WebCore/dom/Node.idl @@ -51,7 +51,7 @@ module core { readonly attribute [ConvertNullStringTo=Null] DOMString nodeName; // FIXME: the spec says this can also raise on retrieval. - attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString nodeValue + attribute [CustomSetter, ConvertNullStringTo=Null, ConvertNullToNullString] DOMString nodeValue setter raises(DOMException); readonly attribute unsigned short nodeType; @@ -96,7 +96,7 @@ module core { readonly attribute [ConvertNullStringTo=Null] DOMString baseURI; // FIXME: the spec says this can also raise on retrieval. - attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString textContent + attribute [CustomSetter, ConvertNullStringTo=Null, ConvertNullToNullString] DOMString textContent setter raises(DOMException); boolean isSameNode(in Node other); diff --git a/src/3rdparty/webkit/WebCore/dom/Range.cpp b/src/3rdparty/webkit/WebCore/dom/Range.cpp index 52d1785..689b590 100644 --- a/src/3rdparty/webkit/WebCore/dom/Range.cpp +++ b/src/3rdparty/webkit/WebCore/dom/Range.cpp @@ -1716,6 +1716,31 @@ void Range::nodeChildrenChanged(ContainerNode* container) boundaryNodeChildrenChanged(m_end, container); } +static inline void boundaryNodeChildrenWillBeRemoved(RangeBoundaryPoint& boundary, ContainerNode* container) +{ + for (Node* nodeToBeRemoved = container->firstChild(); nodeToBeRemoved; nodeToBeRemoved = nodeToBeRemoved->nextSibling()) { + if (boundary.childBefore() == nodeToBeRemoved) { + boundary.setToStartOfNode(container); + return; + } + + for (Node* n = boundary.container(); n; n = n->parentNode()) { + if (n == nodeToBeRemoved) { + boundary.setToStartOfNode(container); + return; + } + } + } +} + +void Range::nodeChildrenWillBeRemoved(ContainerNode* container) +{ + ASSERT(container); + ASSERT(container->document() == m_ownerDocument); + boundaryNodeChildrenWillBeRemoved(m_start, container); + boundaryNodeChildrenWillBeRemoved(m_end, container); +} + static inline void boundaryNodeWillBeRemoved(RangeBoundaryPoint& boundary, Node* nodeToBeRemoved) { if (boundary.childBefore() == nodeToBeRemoved) { diff --git a/src/3rdparty/webkit/WebCore/dom/Range.h b/src/3rdparty/webkit/WebCore/dom/Range.h index fd0f66a..bfddd32 100644 --- a/src/3rdparty/webkit/WebCore/dom/Range.h +++ b/src/3rdparty/webkit/WebCore/dom/Range.h @@ -111,6 +111,7 @@ public: void textQuads(Vector&, bool useSelectionHeight = false); void nodeChildrenChanged(ContainerNode*); + void nodeChildrenWillBeRemoved(ContainerNode*); void nodeWillBeRemoved(Node*); void textInserted(Node*, unsigned offset, unsigned length); diff --git a/src/3rdparty/webkit/WebCore/editing/EditorCommand.cpp b/src/3rdparty/webkit/WebCore/editing/EditorCommand.cpp index 34fa46d..4cb34ac 100644 --- a/src/3rdparty/webkit/WebCore/editing/EditorCommand.cpp +++ b/src/3rdparty/webkit/WebCore/editing/EditorCommand.cpp @@ -1069,6 +1069,21 @@ static bool supportedFromMenuOrKeyBinding(Frame*, EditorCommandSource source) return source == CommandFromMenuOrKeyBinding; } +static bool supportedCopyCut(Frame* frame, EditorCommandSource source) +{ + switch (source) { + case CommandFromMenuOrKeyBinding: + return true; + case CommandFromDOM: + case CommandFromDOMWithUserInterface: { + Settings* settings = frame ? frame->settings() : 0; + return settings && settings->javaScriptCanAccessClipboard(); + } + } + ASSERT_NOT_REACHED(); + return false; +} + static bool supportedPaste(Frame* frame, EditorCommandSource source) { switch (source) { @@ -1077,7 +1092,7 @@ static bool supportedPaste(Frame* frame, EditorCommandSource source) case CommandFromDOM: case CommandFromDOMWithUserInterface: { Settings* settings = frame ? frame->settings() : 0; - return settings && settings->isDOMPasteAllowed(); + return settings && (settings->javaScriptCanAccessClipboard() ? settings->isDOMPasteAllowed() : 0); } } ASSERT_NOT_REACHED(); @@ -1304,9 +1319,9 @@ static const CommandMap& createCommandMap() { "BackColor", { executeBackColor, supported, enabledInRichlyEditableText, stateNone, valueBackColor, notTextInsertion, doNotAllowExecutionWhenDisabled } }, { "BackwardDelete", { executeDeleteBackward, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } }, // FIXME: remove BackwardDelete when Safari for Windows stops using it. { "Bold", { executeToggleBold, supported, enabledInRichlyEditableText, stateBold, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } }, - { "Copy", { executeCopy, supported, enabledCopy, stateNone, valueNull, notTextInsertion, allowExecutionWhenDisabled } }, + { "Copy", { executeCopy, supportedCopyCut, enabledCopy, stateNone, valueNull, notTextInsertion, allowExecutionWhenDisabled } }, { "CreateLink", { executeCreateLink, supported, enabledInRichlyEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } }, - { "Cut", { executeCut, supported, enabledCut, stateNone, valueNull, notTextInsertion, allowExecutionWhenDisabled } }, + { "Cut", { executeCut, supportedCopyCut, enabledCut, stateNone, valueNull, notTextInsertion, allowExecutionWhenDisabled } }, { "Delete", { executeDelete, supported, enabledDelete, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } }, { "DeleteBackward", { executeDeleteBackward, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } }, { "DeleteBackwardByDecomposingPreviousCharacter", { executeDeleteBackwardByDecomposingPreviousCharacter, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } }, diff --git a/src/3rdparty/webkit/WebCore/editing/markup.cpp b/src/3rdparty/webkit/WebCore/editing/markup.cpp index 787dad9..7e90107 100644 --- a/src/3rdparty/webkit/WebCore/editing/markup.cpp +++ b/src/3rdparty/webkit/WebCore/editing/markup.cpp @@ -404,10 +404,12 @@ static void appendStartMarkup(Vector& result, const Node* node, const Ran if (Node* parent = node->parentNode()) { if (parent->hasTagName(scriptTag) || parent->hasTagName(styleTag) - || parent->hasTagName(textareaTag) || parent->hasTagName(xmpTag)) { appendUCharRange(result, ucharRange(node, range)); break; + } else if (parent->hasTagName(textareaTag)) { + appendEscapedContent(result, ucharRange(node, range), documentIsHTML); + break; } } if (!annotate) { diff --git a/src/3rdparty/webkit/WebCore/generated/JSNamedNodeMap.cpp b/src/3rdparty/webkit/WebCore/generated/JSNamedNodeMap.cpp index 7aed66c..1232cfc 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSNamedNodeMap.cpp +++ b/src/3rdparty/webkit/WebCore/generated/JSNamedNodeMap.cpp @@ -264,14 +264,7 @@ JSValue JSC_HOST_CALL jsNamedNodeMapPrototypeFunctionSetNamedItem(ExecState* exe if (!thisValue.inherits(&JSNamedNodeMap::s_info)) return throwError(exec, TypeError); JSNamedNodeMap* castedThisObj = static_cast(asObject(thisValue)); - NamedNodeMap* imp = static_cast(castedThisObj->impl()); - ExceptionCode ec = 0; - Node* node = toNode(args.at(0)); - - - JSC::JSValue result = toJS(exec, castedThisObj->globalObject(), WTF::getPtr(imp->setNamedItem(node, ec))); - setDOMException(exec, ec); - return result; + return castedThisObj->setNamedItem(exec, args); } JSValue JSC_HOST_CALL jsNamedNodeMapPrototypeFunctionRemoveNamedItem(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) @@ -325,14 +318,7 @@ JSValue JSC_HOST_CALL jsNamedNodeMapPrototypeFunctionSetNamedItemNS(ExecState* e if (!thisValue.inherits(&JSNamedNodeMap::s_info)) return throwError(exec, TypeError); JSNamedNodeMap* castedThisObj = static_cast(asObject(thisValue)); - NamedNodeMap* imp = static_cast(castedThisObj->impl()); - ExceptionCode ec = 0; - Node* node = toNode(args.at(0)); - - - JSC::JSValue result = toJS(exec, castedThisObj->globalObject(), WTF::getPtr(imp->setNamedItemNS(node, ec))); - setDOMException(exec, ec); - return result; + return castedThisObj->setNamedItemNS(exec, args); } JSValue JSC_HOST_CALL jsNamedNodeMapPrototypeFunctionRemoveNamedItemNS(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) diff --git a/src/3rdparty/webkit/WebCore/generated/JSNamedNodeMap.h b/src/3rdparty/webkit/WebCore/generated/JSNamedNodeMap.h index 0fa1fdf..b79e97c 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSNamedNodeMap.h +++ b/src/3rdparty/webkit/WebCore/generated/JSNamedNodeMap.h @@ -50,6 +50,10 @@ public: virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties); static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); + + // Custom functions + JSC::JSValue setNamedItem(JSC::ExecState*, const JSC::ArgList&); + JSC::JSValue setNamedItemNS(JSC::ExecState*, const JSC::ArgList&); NamedNodeMap* impl() const { return m_impl.get(); } private: diff --git a/src/3rdparty/webkit/WebCore/generated/JSNode.cpp b/src/3rdparty/webkit/WebCore/generated/JSNode.cpp index 47dafd4..1e16be6 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSNode.cpp +++ b/src/3rdparty/webkit/WebCore/generated/JSNode.cpp @@ -394,11 +394,7 @@ void JSNode::put(ExecState* exec, const Identifier& propertyName, JSValue value, void setJSNodeNodeValue(ExecState* exec, JSObject* thisObject, JSValue value) { - JSNode* castedThisObj = static_cast(thisObject); - Node* imp = static_cast(castedThisObj->impl()); - ExceptionCode ec = 0; - imp->setNodeValue(valueToStringWithNullCheck(exec, value), ec); - setDOMException(exec, ec); + static_cast(thisObject)->setNodeValue(exec, value); } void setJSNodePrefix(ExecState* exec, JSObject* thisObject, JSValue value) @@ -412,11 +408,7 @@ void setJSNodePrefix(ExecState* exec, JSObject* thisObject, JSValue value) void setJSNodeTextContent(ExecState* exec, JSObject* thisObject, JSValue value) { - JSNode* castedThisObj = static_cast(thisObject); - Node* imp = static_cast(castedThisObj->impl()); - ExceptionCode ec = 0; - imp->setTextContent(valueToStringWithNullCheck(exec, value), ec); - setDOMException(exec, ec); + static_cast(thisObject)->setTextContent(exec, value); } JSValue JSNode::getConstructor(ExecState* exec, JSGlobalObject* globalObject) diff --git a/src/3rdparty/webkit/WebCore/generated/JSNode.h b/src/3rdparty/webkit/WebCore/generated/JSNode.h index be6dd23..e2c82c4 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSNode.h +++ b/src/3rdparty/webkit/WebCore/generated/JSNode.h @@ -54,6 +54,10 @@ public: static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); + // Custom attributes + void setNodeValue(JSC::ExecState*, JSC::JSValue); + void setTextContent(JSC::ExecState*, JSC::JSValue); + // Custom functions JSC::JSValue insertBefore(JSC::ExecState*, const JSC::ArgList&); JSC::JSValue replaceChild(JSC::ExecState*, const JSC::ArgList&); diff --git a/src/3rdparty/webkit/WebCore/html/canvas/CanvasRenderingContext2D.cpp b/src/3rdparty/webkit/WebCore/html/canvas/CanvasRenderingContext2D.cpp index 9cec7a9..73a572e 100644 --- a/src/3rdparty/webkit/WebCore/html/canvas/CanvasRenderingContext2D.cpp +++ b/src/3rdparty/webkit/WebCore/html/canvas/CanvasRenderingContext2D.cpp @@ -1215,7 +1215,7 @@ PassRefPtr CanvasRenderingContext2D::createPattern(HTMLImageEleme if (!cachedImage || !image->cachedImage()->image()) return CanvasPattern::create(Image::nullImage(), repeatX, repeatY, true); - bool originClean = !canvas()->document()->securityOrigin()->taintsCanvas(KURL(KURL(), cachedImage->url())); + bool originClean = !canvas()->document()->securityOrigin()->taintsCanvas(KURL(KURL(), cachedImage->url())) && cachedImage->image()->hasSingleSecurityOrigin(); return CanvasPattern::create(cachedImage->image(), repeatX, repeatY, originClean); } diff --git a/src/3rdparty/webkit/WebCore/loader/DocumentThreadableLoader.cpp b/src/3rdparty/webkit/WebCore/loader/DocumentThreadableLoader.cpp index de0a0b0..55f51ac 100644 --- a/src/3rdparty/webkit/WebCore/loader/DocumentThreadableLoader.cpp +++ b/src/3rdparty/webkit/WebCore/loader/DocumentThreadableLoader.cpp @@ -81,16 +81,19 @@ DocumentThreadableLoader::DocumentThreadableLoader(Document* document, Threadabl ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); - if (!m_options.forcePreflight && isSimpleCrossOriginAccessRequest(request.httpMethod(), request.httpHeaderFields())) - makeSimpleCrossOriginAccessRequest(request); + OwnPtr crossOriginRequest(new ResourceRequest(request)); + crossOriginRequest->removeCredentials(); + crossOriginRequest->setAllowCookies(m_options.allowCredentials); + + if (!m_options.forcePreflight && isSimpleCrossOriginAccessRequest(crossOriginRequest->httpMethod(), crossOriginRequest->httpHeaderFields())) + makeSimpleCrossOriginAccessRequest(*crossOriginRequest); else { - m_actualRequest.set(new ResourceRequest(request)); - m_actualRequest->setAllowCookies(m_options.allowCredentials); + m_actualRequest.set(crossOriginRequest.release()); - if (CrossOriginPreflightResultCache::shared().canSkipPreflight(document->securityOrigin()->toString(), request.url(), m_options.allowCredentials, request.httpMethod(), request.httpHeaderFields())) + if (CrossOriginPreflightResultCache::shared().canSkipPreflight(document->securityOrigin()->toString(), m_actualRequest->url(), m_options.allowCredentials, m_actualRequest->httpMethod(), m_actualRequest->httpHeaderFields())) preflightSuccess(); else - makeCrossOriginAccessRequestWithPreflight(request); + makeCrossOriginAccessRequestWithPreflight(*m_actualRequest); } } @@ -106,8 +109,6 @@ void DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest(const Resource // Make a copy of the passed request so that we can modify some details. ResourceRequest crossOriginRequest(request); - crossOriginRequest.removeCredentials(); - crossOriginRequest.setAllowCookies(m_options.allowCredentials); crossOriginRequest.setHTTPOrigin(m_document->securityOrigin()->toString()); loadRequest(crossOriginRequest, DoSecurityCheck); @@ -287,11 +288,17 @@ void DocumentThreadableLoader::preflightSuccess() void DocumentThreadableLoader::preflightFailure() { + m_actualRequest = 0; // Prevent didFinishLoading() from bypassing access check. m_client->didFail(ResourceError()); } void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, SecurityCheckPolicy securityCheck) { + // Any credential should have been removed from the cross-site requests. + const KURL& requestURL = request.url(); + ASSERT(m_sameOriginRequest || requestURL.user().isEmpty()); + ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty()); + if (m_async) { // Don't sniff content or send load callbacks for the preflight request. bool sendLoadCallbacks = m_options.sendLoadCallbacks && !m_actualRequest; @@ -315,15 +322,15 @@ void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, Secur // No exception for file:/// resources, see . // Also, if we have an HTTP response, then it wasn't a network error in fact. - if (!error.isNull() && !request.url().isLocalFile() && response.httpStatusCode() <= 0) { + if (!error.isNull() && !requestURL.isLocalFile() && response.httpStatusCode() <= 0) { m_client->didFail(error); return; } // FIXME: FrameLoader::loadSynchronously() does not tell us whether a redirect happened or not, so we guess by comparing the // request and response URLs. This isn't a perfect test though, since a server can serve a redirect to the same URL that was - // requested. - if (request.url() != response.url() && !isAllowedRedirect(response.url())) { + // requested. Also comparing the request and response URLs as strings will fail if the requestURL still has its credentials. + if (requestURL != response.url() && !isAllowedRedirect(response.url())) { m_client->didFailRedirectCheck(); return; } diff --git a/src/3rdparty/webkit/WebCore/page/DragController.cpp b/src/3rdparty/webkit/WebCore/page/DragController.cpp index f238b27..0da6873 100644 --- a/src/3rdparty/webkit/WebCore/page/DragController.cpp +++ b/src/3rdparty/webkit/WebCore/page/DragController.cpp @@ -313,7 +313,7 @@ bool DragController::tryDocumentDrag(DragData* dragData, DragDestinationAction a } IntPoint point = frameView->windowToContents(dragData->clientPosition()); - Element* element = elementUnderMouse(m_documentUnderMouse, point); + Element* element = elementUnderMouse(m_documentUnderMouse.get(), point); if (!asFileInput(element)) { VisibleSelection dragCaret = m_documentUnderMouse->frame()->visiblePositionForPoint(point); m_page->dragCaretController()->setSelection(dragCaret); @@ -363,7 +363,7 @@ bool DragController::concludeEditDrag(DragData* dragData) return false; IntPoint point = m_documentUnderMouse->view()->windowToContents(dragData->clientPosition()); - Element* element = elementUnderMouse(m_documentUnderMouse, point); + Element* element = elementUnderMouse(m_documentUnderMouse.get(), point); Frame* innerFrame = element->ownerDocument()->frame(); ASSERT(innerFrame); @@ -439,7 +439,7 @@ bool DragController::concludeEditDrag(DragData* dragData) applyCommand(MoveSelectionCommand::create(fragment, dragCaret.base(), smartInsert, smartDelete)); } else { if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) - applyCommand(ReplaceSelectionCommand::create(m_documentUnderMouse, fragment, true, dragData->canSmartReplace(), chosePlainText)); + applyCommand(ReplaceSelectionCommand::create(m_documentUnderMouse.get(), fragment, true, dragData->canSmartReplace(), chosePlainText)); } } else { String text = dragData->asPlainText(); @@ -450,7 +450,7 @@ bool DragController::concludeEditDrag(DragData* dragData) m_client->willPerformDragDestinationAction(DragDestinationActionEdit, dragData); if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) - applyCommand(ReplaceSelectionCommand::create(m_documentUnderMouse, createFragmentFromText(range.get(), text), true, false, true)); + applyCommand(ReplaceSelectionCommand::create(m_documentUnderMouse.get(), createFragmentFromText(range.get(), text), true, false, true)); } loader->setAllowStaleResources(false); diff --git a/src/3rdparty/webkit/WebCore/page/DragController.h b/src/3rdparty/webkit/WebCore/page/DragController.h index 3b2b083..712f9ab 100644 --- a/src/3rdparty/webkit/WebCore/page/DragController.h +++ b/src/3rdparty/webkit/WebCore/page/DragController.h @@ -67,13 +67,11 @@ namespace WebCore { DragOperation sourceDragOperation() const { return m_sourceDragOperation; } void setDraggingImageURL(const KURL& url) { m_draggingImageURL = url; } const KURL& draggingImageURL() const { return m_draggingImageURL; } - void setDragInitiator(Document* initiator) { m_dragInitiator = initiator; m_didInitiateDrag = true; } - Document* dragInitiator() const { return m_dragInitiator; } void setDragOffset(const IntPoint& offset) { m_dragOffset = offset; } const IntPoint& dragOffset() const { return m_dragOffset; } DragSourceAction dragSourceAction() const { return m_dragSourceAction; } - Document* documentUnderMouse() const { return m_documentUnderMouse; } + Document* documentUnderMouse() const { return m_documentUnderMouse.get(); } DragDestinationAction dragDestinationAction() const { return m_dragDestinationAction; } DragSourceAction delegateDragSourceAction(const IntPoint& pagePoint); @@ -114,8 +112,8 @@ namespace WebCore { Page* m_page; DragClient* m_client; - Document* m_documentUnderMouse; // The document the mouse was last dragged over. - Document* m_dragInitiator; // The Document (if any) that initiated the drag. + RefPtr m_documentUnderMouse; // The document the mouse was last dragged over. + RefPtr m_dragInitiator; // The Document (if any) that initiated the drag. DragDestinationAction m_dragDestinationAction; DragSourceAction m_dragSourceAction; diff --git a/src/3rdparty/webkit/WebCore/page/EventHandler.cpp b/src/3rdparty/webkit/WebCore/page/EventHandler.cpp index 1654257..f1ee742 100644 --- a/src/3rdparty/webkit/WebCore/page/EventHandler.cpp +++ b/src/3rdparty/webkit/WebCore/page/EventHandler.cpp @@ -2163,7 +2163,9 @@ bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent) if (initialKeyEvent.type() == PlatformKeyboardEvent::RawKeyDown) { node->dispatchEvent(keydown, ec); - return keydown->defaultHandled() || keydown->defaultPrevented(); + // If frame changed as a result of keydown dispatch, then return true to avoid sending a subsequent keypress message to the new frame. + bool changedFocusedFrame = m_frame->page() && m_frame != m_frame->page()->focusController()->focusedOrMainFrame(); + return keydown->defaultHandled() || keydown->defaultPrevented() || changedFocusedFrame; } // Run input method in advance of DOM event handling. This may result in the IM @@ -2183,7 +2185,9 @@ bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent) } node->dispatchEvent(keydown, ec); - bool keydownResult = keydown->defaultHandled() || keydown->defaultPrevented(); + // If frame changed as a result of keydown dispatch, then return early to avoid sending a subsequent keypress message to the new frame. + bool changedFocusedFrame = m_frame->page() && m_frame != m_frame->page()->focusController()->focusedOrMainFrame(); + bool keydownResult = keydown->defaultHandled() || keydown->defaultPrevented() || changedFocusedFrame; if (handledByInputMethod || (keydownResult && !backwardCompatibilityMode)) return keydownResult; diff --git a/src/3rdparty/webkit/WebCore/page/FrameView.cpp b/src/3rdparty/webkit/WebCore/page/FrameView.cpp index 639414b..01f0375 100644 --- a/src/3rdparty/webkit/WebCore/page/FrameView.cpp +++ b/src/3rdparty/webkit/WebCore/page/FrameView.cpp @@ -1315,14 +1315,13 @@ void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot) { ASSERT(m_frame->view() == this); - if (!m_layoutSchedulingEnabled || (m_frame->contentRenderer() - && m_frame->contentRenderer()->needsLayout())) { + if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout()) { if (relayoutRoot) relayoutRoot->markContainingBlocksForLayout(false); return; } - if (layoutPending()) { + if (layoutPending() || !m_layoutSchedulingEnabled) { if (m_layoutRoot != relayoutRoot) { if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) { // Keep the current root @@ -1339,7 +1338,7 @@ void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot) relayoutRoot->markContainingBlocksForLayout(false); } } - } else { + } else if (m_layoutSchedulingEnabled) { int delay = m_frame->document()->minimumLayoutDelay(); m_layoutRoot = relayoutRoot; m_delayedLayout = delay != 0; diff --git a/src/3rdparty/webkit/WebCore/page/SecurityOrigin.cpp b/src/3rdparty/webkit/WebCore/page/SecurityOrigin.cpp index c0b3e22..516c533 100644 --- a/src/3rdparty/webkit/WebCore/page/SecurityOrigin.cpp +++ b/src/3rdparty/webkit/WebCore/page/SecurityOrigin.cpp @@ -90,6 +90,20 @@ static URLSchemesMap& schemesWithUniqueOrigins() return schemesWithUniqueOrigins; } +static bool schemeRequiresAuthority(const String& scheme) +{ + DEFINE_STATIC_LOCAL(URLSchemesMap, schemes, ()); + + if (schemes.isEmpty()) { + schemes.add("http"); + schemes.add("https"); + schemes.add("ftp"); + } + + return schemes.contains(scheme); +} + + SecurityOrigin::SecurityOrigin(const KURL& url, SandboxFlags sandboxFlags) : m_sandboxFlags(sandboxFlags) , m_protocol(url.protocol().isNull() ? "" : url.protocol().lower()) @@ -103,6 +117,10 @@ SecurityOrigin::SecurityOrigin(const KURL& url, SandboxFlags sandboxFlags) if (m_protocol == "about" || m_protocol == "javascript") m_protocol = ""; + // For edge case URLs that were probably misparsed, make sure that the origin is unique. + if (schemeRequiresAuthority(m_protocol) && m_host.isEmpty()) + m_isUnique = true; + // document.domain starts as m_host, but can be set by the DOM. m_domain = m_host; diff --git a/src/3rdparty/webkit/WebCore/page/Settings.cpp b/src/3rdparty/webkit/WebCore/page/Settings.cpp index 475d373..c0659d2 100644 --- a/src/3rdparty/webkit/WebCore/page/Settings.cpp +++ b/src/3rdparty/webkit/WebCore/page/Settings.cpp @@ -79,6 +79,7 @@ Settings::Settings(Page* page) , m_allowUniversalAccessFromFileURLs(true) , m_allowFileAccessFromFileURLs(true) , m_javaScriptCanOpenWindowsAutomatically(false) + , m_javaScriptCanAccessClipboard(false) , m_shouldPrintBackgrounds(false) , m_textAreasAreResizable(false) #if ENABLE(DASHBOARD_SUPPORT) @@ -291,6 +292,11 @@ void Settings::setJavaScriptCanOpenWindowsAutomatically(bool javaScriptCanOpenWi m_javaScriptCanOpenWindowsAutomatically = javaScriptCanOpenWindowsAutomatically; } +void Settings::setJavaScriptCanAccessClipboard(bool javaScriptCanAccessClipboard) +{ + m_javaScriptCanAccessClipboard = javaScriptCanAccessClipboard; +} + void Settings::setDefaultTextEncodingName(const String& defaultTextEncodingName) { m_defaultTextEncodingName = defaultTextEncodingName; diff --git a/src/3rdparty/webkit/WebCore/page/Settings.h b/src/3rdparty/webkit/WebCore/page/Settings.h index b677712..a6653ce 100644 --- a/src/3rdparty/webkit/WebCore/page/Settings.h +++ b/src/3rdparty/webkit/WebCore/page/Settings.h @@ -122,6 +122,9 @@ namespace WebCore { void setJavaScriptCanOpenWindowsAutomatically(bool); bool javaScriptCanOpenWindowsAutomatically() const { return m_javaScriptCanOpenWindowsAutomatically; } + void setJavaScriptCanAccessClipboard(bool); + bool javaScriptCanAccessClipboard() const { return m_javaScriptCanAccessClipboard; } + void setSpatialNavigationEnabled(bool); bool isSpatialNavigationEnabled() const { return m_isSpatialNavigationEnabled; } @@ -330,6 +333,7 @@ namespace WebCore { bool m_allowUniversalAccessFromFileURLs: 1; bool m_allowFileAccessFromFileURLs: 1; bool m_javaScriptCanOpenWindowsAutomatically : 1; + bool m_javaScriptCanAccessClipboard : 1; bool m_shouldPrintBackgrounds : 1; bool m_textAreasAreResizable : 1; #if ENABLE(DASHBOARD_SUPPORT) diff --git a/src/3rdparty/webkit/WebCore/platform/KURL.cpp b/src/3rdparty/webkit/WebCore/platform/KURL.cpp index 40adfbc..3c8d50f 100644 --- a/src/3rdparty/webkit/WebCore/platform/KURL.cpp +++ b/src/3rdparty/webkit/WebCore/platform/KURL.cpp @@ -215,6 +215,9 @@ static const unsigned char characterClassTable[256] = { /* 252 */ BadChar, /* 253 */ BadChar, /* 254 */ BadChar, /* 255 */ BadChar }; +static const unsigned maximumValidPortNumber = 0xFFFE; +static const unsigned invalidPortNumber = 0xFFFF; + static int copyPathRemovingDots(char* dst, const char* src, int srcStart, int srcEnd); static void encodeRelativeString(const String& rel, const TextEncoding&, CharBuffer& ouput); static String substituteBackslashes(const String&); @@ -573,12 +576,17 @@ String KURL::host() const unsigned short KURL::port() const { - if (m_hostEnd == m_portEnd) + // We return a port of 0 if there is no port specified. This can happen in two situations: + // 1) The URL contains no colon after the host name and before the path component of the URL. + // 2) The URL contains a colon but there's no port number before the path component of the URL begins. + if (m_hostEnd == m_portEnd || m_hostEnd == m_portEnd - 1) return 0; - int number = m_string.substring(m_hostEnd + 1, m_portEnd - m_hostEnd - 1).toInt(); - if (number < 0 || number > 0xFFFF) - return 0; + const UChar* stringData = m_string.characters(); + bool ok = false; + unsigned number = charactersToUIntStrict(stringData + m_hostEnd + 1, m_portEnd - m_hostEnd - 1, &ok); + if (!ok || number > maximumValidPortNumber) + return invalidPortNumber; return number; } @@ -1757,7 +1765,7 @@ bool portAllowed(const KURL& url) 6667, // Standard IRC [Apple addition] 6668, // Alternate IRC [Apple addition] 6669, // Alternate IRC [Apple addition] - + invalidPortNumber, // Used to block all invalid port numbers }; const unsigned short* const blockedPortListEnd = blockedPortList + sizeof(blockedPortList) / sizeof(blockedPortList[0]); diff --git a/src/3rdparty/webkit/WebCore/platform/KURLGoogle.cpp b/src/3rdparty/webkit/WebCore/platform/KURLGoogle.cpp index 8be7009..10b9bb8 100644 --- a/src/3rdparty/webkit/WebCore/platform/KURLGoogle.cpp +++ b/src/3rdparty/webkit/WebCore/platform/KURLGoogle.cpp @@ -57,6 +57,8 @@ using std::binary_search; namespace WebCore { +static const unsigned invalidPortNumber = 0xFFFF; + // Wraps WebCore's text encoding in a character set converter for the // canonicalizer. class KURLCharsetConverter : public url_canon::CharsetConverter { @@ -499,7 +501,7 @@ String KURL::host() const unsigned short KURL::port() const { if (!m_url.m_isValid || m_url.m_parsed.port.len <= 0) - return 0; + return invalidPortNumber; int port = url_parse::ParsePort(m_url.utf8String().data(), m_url.m_parsed.port); if (port == url_parse::PORT_UNSPECIFIED) return 0; @@ -853,6 +855,12 @@ bool portAllowed(const KURL& url) 3659, // apple-sasl / PasswordServer [Apple addition] 4045, // lockd 6000, // X11 + 6665, // Alternate IRC [Apple addition] + 6666, // Alternate IRC [Apple addition] + 6667, // Standard IRC [Apple addition] + 6668, // Alternate IRC [Apple addition] + 6669, // Alternate IRC [Apple addition] + invalidPortNumber, // Used to block all invalid port numbers }; const unsigned short* const blockedPortListEnd = blockedPortList + sizeof(blockedPortList) / sizeof(blockedPortList[0]); diff --git a/src/3rdparty/webkit/WebCore/platform/graphics/qt/PathQt.cpp b/src/3rdparty/webkit/WebCore/platform/graphics/qt/PathQt.cpp index a7351a0..c96fe25 100644 --- a/src/3rdparty/webkit/WebCore/platform/graphics/qt/PathQt.cpp +++ b/src/3rdparty/webkit/WebCore/platform/graphics/qt/PathQt.cpp @@ -69,23 +69,31 @@ Path& Path::operator=(const Path& other) return *this; } +static inline bool areCollinear(const QPointF& a, const QPointF& b, const QPointF& c) +{ + // Solved from comparing the slopes of a to b and b to c: (ay-by)/(ax-bx) == (cy-by)/(cx-bx) + return qFuzzyCompare((c.y() - b.y()) * (a.x() - b.x()), (a.y() - b.y()) * (c.x() - b.x())); +} + +static inline bool withinRange(qreal p, qreal a, qreal b) +{ + return (p >= a && p <= b) || (p >= b && p <= a); +} + // Check whether a point is on the border -bool isPointOnPathBorder(const QPolygonF& border, const QPointF& p) +static bool isPointOnPathBorder(const QPolygonF& border, const QPointF& p) { QPointF p1 = border.at(0); QPointF p2; for (int i = 1; i < border.size(); ++i) { p2 = border.at(i); - // (x1<=x<=x2||x1=>x>=x2) && (y1<=y<=y2||y1=>y>=y2) && (y2-y1)(x-x1) == (y-y1)(x2-x1) - // In which, (y2-y1)(x-x1) == (y-y1)(x2-x1) is from (y2-y1)/(x2-x1) == (y-y1)/(x-x1) - // it want to check the slope between p1 and p2 is same with slope between p and p1, - // if so then the three points lie on the same line. - // In which, (x1<=x<=x2||x1=>x>=x2) && (y1<=y<=y2||y1=>y>=y2) want to make sure p is - // between p1 and p2, not outside. - if (((p.x() <= p1.x() && p.x() >= p2.x()) || (p.x() >= p1.x() && p.x() <= p2.x())) - && ((p.y() <= p1.y() && p.y() >= p2.y()) || (p.y() >= p1.y() && p.y() <= p2.y())) - && (p2.y() - p1.y()) * (p.x() - p1.x()) == (p.y() - p1.y()) * (p2.x() - p1.x())) { + if (areCollinear(p, p1, p2) + // Once we know that the points are collinear we + // only need to check one of the coordinates + && (qAbs(p2.x() - p1.x()) > qAbs(p2.y() - p1.y()) ? + withinRange(p.x(), p1.x(), p2.x()) : + withinRange(p.y(), p1.y(), p2.y()))) { return true; } p1 = p2; @@ -199,19 +207,14 @@ void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius) float p1p2_length = sqrtf(p1p2.x() * p1p2.x() + p1p2.y() * p1p2.y()); double cos_phi = (p1p0.x() * p1p2.x() + p1p0.y() * p1p2.y()) / (p1p0_length * p1p2_length); - // all points on a line logic - if (cos_phi == -1) { + + // The points p0, p1, and p2 are on the same straight line (HTML5, 4.8.11.1.8) + // We could have used areCollinear() here, but since we're reusing + // the variables computed above later on we keep this logic. + if (qFuzzyCompare(qAbs(cos_phi), 1.0)) { m_path.lineTo(p1); return; } - if (cos_phi == 1) { - // add infinite far away point - unsigned int max_length = 65535; - double factor_max = max_length / p1p0_length; - FloatPoint ep((p0.x() + factor_max * p1p0.x()), (p0.y() + factor_max * p1p0.y())); - m_path.lineTo(ep); - return; - } float tangent = radius / tan(acos(cos_phi) / 2); float factor_p1p0 = tangent / p1p0_length; diff --git a/src/3rdparty/webkit/WebCore/platform/network/ProtectionSpace.h b/src/3rdparty/webkit/WebCore/platform/network/ProtectionSpace.h index 126b499..42cbc8a 100644 --- a/src/3rdparty/webkit/WebCore/platform/network/ProtectionSpace.h +++ b/src/3rdparty/webkit/WebCore/platform/network/ProtectionSpace.h @@ -47,6 +47,7 @@ enum ProtectionSpaceAuthenticationScheme { ProtectionSpaceAuthenticationSchemeHTMLForm = 4, ProtectionSpaceAuthenticationSchemeNTLM = 5, ProtectionSpaceAuthenticationSchemeNegotiate = 6, + ProtectionSpaceAuthenticationSchemeUnknown = 100, }; class ProtectionSpace { diff --git a/src/3rdparty/webkit/WebCore/rendering/FixedTableLayout.cpp b/src/3rdparty/webkit/WebCore/rendering/FixedTableLayout.cpp index 09af518..4d6b88c 100644 --- a/src/3rdparty/webkit/WebCore/rendering/FixedTableLayout.cpp +++ b/src/3rdparty/webkit/WebCore/rendering/FixedTableLayout.cpp @@ -166,8 +166,7 @@ int FixedTableLayout::calcWidthArray(int) int usedSpan = 0; int i = 0; - while (usedSpan < span) { - ASSERT(cCol + i < nEffCols); + while (usedSpan < span && cCol + i < nEffCols) { int eSpan = m_table->spanOfEffCol(cCol + i); // Only set if no col element has already set it. if (m_width[cCol + i].isAuto() && w.type() != Auto) { diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderButton.h b/src/3rdparty/webkit/WebCore/rendering/RenderButton.h index 7fd6ab0..1fc5eb6 100644 --- a/src/3rdparty/webkit/WebCore/rendering/RenderButton.h +++ b/src/3rdparty/webkit/WebCore/rendering/RenderButton.h @@ -57,12 +57,14 @@ public: virtual bool canHaveChildren() const; -protected: +private: virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle); virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); virtual bool hasLineIfEmpty() const { return true; } + virtual bool requiresForcedStyleRecalcPropagation() const { return true; } + void timerFired(Timer*); RenderTextFragment* m_buttonText; diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderDataGrid.h b/src/3rdparty/webkit/WebCore/rendering/RenderDataGrid.h index 467edcc..ce221ea 100644 --- a/src/3rdparty/webkit/WebCore/rendering/RenderDataGrid.h +++ b/src/3rdparty/webkit/WebCore/rendering/RenderDataGrid.h @@ -53,6 +53,8 @@ public: private: virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); + virtual bool requiresForcedStyleRecalcPropagation() const { return true; } + RenderStyle* columnStyle(DataGridColumn*); RenderStyle* headerStyle(DataGridColumn*); void recalcStyleForColumns(); diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderFileUploadControl.h b/src/3rdparty/webkit/WebCore/rendering/RenderFileUploadControl.h index 99dd35c..a5f3367 100644 --- a/src/3rdparty/webkit/WebCore/rendering/RenderFileUploadControl.h +++ b/src/3rdparty/webkit/WebCore/rendering/RenderFileUploadControl.h @@ -56,6 +56,8 @@ private: virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); + virtual bool requiresForcedStyleRecalcPropagation() const { return true; } + // FileChooserClient methods. void valueChanged(); void repaint() { RenderBlock::repaint(); } diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderInline.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderInline.cpp index 1d76742..5b1deff 100644 --- a/src/3rdparty/webkit/WebCore/rendering/RenderInline.cpp +++ b/src/3rdparty/webkit/WebCore/rendering/RenderInline.cpp @@ -274,7 +274,7 @@ void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock, // has to move into the inline continuation. Call updateBeforeAfterContent to ensure that the inline's :after // content gets properly destroyed. if (document()->usesBeforeAfterRules()) - inlineCurr->children()->updateBeforeAfterContent(this, AFTER); + inlineCurr->children()->updateBeforeAfterContent(inlineCurr, AFTER); // Now we need to take all of the children starting from the first child // *after* currChild and append them all to the clone. diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderLayer.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderLayer.cpp index a012868..2aec361 100644 --- a/src/3rdparty/webkit/WebCore/rendering/RenderLayer.cpp +++ b/src/3rdparty/webkit/WebCore/rendering/RenderLayer.cpp @@ -3178,22 +3178,33 @@ void RenderLayer::updateHoverActiveState(const HitTestRequest& request, HitTestR // Locate the common ancestor render object for the two renderers. RenderObject* ancestor = commonAncestor(oldHoverObj, newHoverObj); + Vector, 32> nodesToRemoveFromChain; + Vector, 32> nodesToAddToChain; + if (oldHoverObj != newHoverObj) { // The old hover path only needs to be cleared up to (and not including) the common ancestor; for (RenderObject* curr = oldHoverObj; curr && curr != ancestor; curr = curr->hoverAncestor()) { - if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain())) { - curr->node()->setActive(false); - curr->node()->setHovered(false); - } + if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain())) + nodesToRemoveFromChain.append(curr->node()); } } // Now set the hover state for our new object up to the root. for (RenderObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) { - if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain())) { - curr->node()->setActive(request.active()); - curr->node()->setHovered(true); - } + if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain())) + nodesToAddToChain.append(curr->node()); + } + + size_t removeCount = nodesToRemoveFromChain.size(); + for (size_t i = 0; i < removeCount; ++i) { + nodesToRemoveFromChain[i]->setActive(false); + nodesToRemoveFromChain[i]->setHovered(false); + } + + size_t addCount = nodesToAddToChain.size(); + for (size_t i = 0; i < addCount; ++i) { + nodesToAddToChain[i]->setActive(request.active()); + nodesToAddToChain[i]->setHovered(true); } } diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderListItem.h b/src/3rdparty/webkit/WebCore/rendering/RenderListItem.h index c4c41dc..d140979 100644 --- a/src/3rdparty/webkit/WebCore/rendering/RenderListItem.h +++ b/src/3rdparty/webkit/WebCore/rendering/RenderListItem.h @@ -63,6 +63,8 @@ private: virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); + virtual bool requiresForcedStyleRecalcPropagation() const { return true; } + void updateMarkerLocation(); inline int calcValue() const; void updateValueNow() const; diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderListMarker.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderListMarker.cpp index d0353ee..6c8f769 100644 --- a/src/3rdparty/webkit/WebCore/rendering/RenderListMarker.cpp +++ b/src/3rdparty/webkit/WebCore/rendering/RenderListMarker.cpp @@ -101,8 +101,10 @@ static inline String toAlphabeticOrNumeric(int number, const UChar* sequence, in int length = 1; if (type == AlphabeticSequence) { - while ((numberShadow /= sequenceSize) > 0) - letters[lettersSize - ++length] = sequence[numberShadow % sequenceSize - 1]; + while ((numberShadow /= sequenceSize) > 0) { + --numberShadow; + letters[lettersSize - ++length] = sequence[numberShadow % sequenceSize]; + } } else { while ((numberShadow /= sequenceSize) > 0) letters[lettersSize - ++length] = sequence[numberShadow % sequenceSize]; diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderMedia.h b/src/3rdparty/webkit/WebCore/rendering/RenderMedia.h index 0d24c4c..32d6d65 100644 --- a/src/3rdparty/webkit/WebCore/rendering/RenderMedia.h +++ b/src/3rdparty/webkit/WebCore/rendering/RenderMedia.h @@ -118,6 +118,8 @@ private: virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); + virtual bool requiresForcedStyleRecalcPropagation() const { return true; } + RefPtr m_controlsShadowRoot; RefPtr m_panel; RefPtr m_muteButton; diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderMenuList.h b/src/3rdparty/webkit/WebCore/rendering/RenderMenuList.h index aeb6205..5ee8588 100644 --- a/src/3rdparty/webkit/WebCore/rendering/RenderMenuList.h +++ b/src/3rdparty/webkit/WebCore/rendering/RenderMenuList.h @@ -78,6 +78,8 @@ private: virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); + virtual bool requiresForcedStyleRecalcPropagation() const { return true; } + // PopupMenuClient methods virtual String itemText(unsigned listIndex) const; virtual String itemToolTip(unsigned listIndex) const; diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderObject.h b/src/3rdparty/webkit/WebCore/rendering/RenderObject.h index d928521..593fa52 100644 --- a/src/3rdparty/webkit/WebCore/rendering/RenderObject.h +++ b/src/3rdparty/webkit/WebCore/rendering/RenderObject.h @@ -322,6 +322,8 @@ public: bool cellWidthChanged() const { return m_cellWidthChanged; } void setCellWidthChanged(bool b = true) { m_cellWidthChanged = b; } + virtual bool requiresForcedStyleRecalcPropagation() const { return false; } + #if ENABLE(MATHML) virtual bool isRenderMathMLBlock() const { return false; } #endif // ENABLE(MATHML) @@ -412,7 +414,6 @@ public: void drawArcForBoxSide(GraphicsContext*, int x, int y, float thickness, IntSize radius, int angleStart, int angleSpan, BoxSide, Color, const Color& textcolor, EBorderStyle, bool firstCorner); -public: // The pseudo element style can be cached or uncached. Use the cached method if the pseudo element doesn't respect // any pseudo classes (and therefore has no concept of changing state). RenderStyle* getCachedPseudoStyle(PseudoId, RenderStyle* parentStyle = 0) const; diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderProgress.h b/src/3rdparty/webkit/WebCore/rendering/RenderProgress.h index 0a90fde..7aa1efe 100644 --- a/src/3rdparty/webkit/WebCore/rendering/RenderProgress.h +++ b/src/3rdparty/webkit/WebCore/rendering/RenderProgress.h @@ -40,6 +40,8 @@ private: virtual void calcPrefWidths(); virtual void layout(); virtual void updateFromElement(); + virtual bool requiresForcedStyleRecalcPropagation() const { return true; } + int m_position; }; diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSlider.h b/src/3rdparty/webkit/WebCore/rendering/RenderSlider.h index 92ad73b..fc8ce24 100644 --- a/src/3rdparty/webkit/WebCore/rendering/RenderSlider.h +++ b/src/3rdparty/webkit/WebCore/rendering/RenderSlider.h @@ -58,6 +58,8 @@ namespace WebCore { virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); + virtual bool requiresForcedStyleRecalcPropagation() const { return true; } + PassRefPtr createThumbStyle(const RenderStyle* parentStyle); int trackSize(); diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderText.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderText.cpp index 307db64..c08adc2 100644 --- a/src/3rdparty/webkit/WebCore/rendering/RenderText.cpp +++ b/src/3rdparty/webkit/WebCore/rendering/RenderText.cpp @@ -203,7 +203,7 @@ void RenderText::deleteTextBoxes() PassRefPtr RenderText::originalText() const { Node* e = node(); - return e ? static_cast(e)->dataImpl() : 0; + return (e && e->isTextNode()) ? static_cast(e)->dataImpl() : 0; } void RenderText::absoluteRects(Vector& rects, int tx, int ty) diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTextControl.h b/src/3rdparty/webkit/WebCore/rendering/RenderTextControl.h index 2fc8edc..984f41d 100644 --- a/src/3rdparty/webkit/WebCore/rendering/RenderTextControl.h +++ b/src/3rdparty/webkit/WebCore/rendering/RenderTextControl.h @@ -107,6 +107,8 @@ private: virtual bool canBeProgramaticallyScrolled(bool) const { return true; } + virtual bool requiresForcedStyleRecalcPropagation() const { return true; } + String finishText(Vector&) const; bool m_wasChangedSinceLastChangeEvent; diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTextFragment.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderTextFragment.cpp index f3398a3..1e15d66 100644 --- a/src/3rdparty/webkit/WebCore/rendering/RenderTextFragment.cpp +++ b/src/3rdparty/webkit/WebCore/rendering/RenderTextFragment.cpp @@ -47,7 +47,7 @@ RenderTextFragment::RenderTextFragment(Node* node, StringImpl* str) PassRefPtr RenderTextFragment::originalText() const { Node* e = node(); - RefPtr result = (e ? static_cast(e)->dataImpl() : contentString()); + RefPtr result = ((e && e->isTextNode()) ? static_cast(e)->dataImpl() : contentString()); if (result && (start() > 0 || start() < result->length())) result = result->substring(start(), end()); return result.release(); @@ -80,7 +80,7 @@ UChar RenderTextFragment::previousCharacter() { if (start()) { Node* e = node(); - StringImpl* original = (e ? static_cast(e)->dataImpl() : contentString()); + StringImpl* original = ((e && e->isTextNode()) ? static_cast(e)->dataImpl() : contentString()); if (original) return (*original)[start() - 1]; } diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.cpp b/src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.cpp index 47b4f3b..d907d86 100644 --- a/src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.cpp +++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.cpp @@ -187,6 +187,7 @@ void QWebSettingsPrivate::apply() value = attributes.value(QWebSettings::JavascriptCanAccessClipboard, global->attributes.value(QWebSettings::JavascriptCanAccessClipboard)); settings->setDOMPasteAllowed(value); + settings->setJavaScriptCanAccessClipboard(value); value = attributes.value(QWebSettings::DeveloperExtrasEnabled, global->attributes.value(QWebSettings::DeveloperExtrasEnabled)); @@ -235,8 +236,8 @@ void QWebSettingsPrivate::apply() global->attributes.value(QWebSettings::LocalContentCanAccessFileUrls)); settings->setAllowFileAccessFromFileURLs(value); - value = attributes.value(QWebSettings::XSSAuditorEnabled, - global->attributes.value(QWebSettings::XSSAuditorEnabled)); + value = attributes.value(QWebSettings::XSSAuditingEnabled, + global->attributes.value(QWebSettings::XSSAuditingEnabled)); settings->setXSSAuditorEnabled(value); #if ENABLE(TILED_BACKING_STORE) diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.h b/src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.h index 207a9b6..156f633 100644 --- a/src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.h +++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.h @@ -68,7 +68,7 @@ public: #endif LocalContentCanAccessRemoteUrls, DnsPrefetchEnabled, - XSSAuditorEnabled, + XSSAuditingEnabled, AcceleratedCompositingEnabled, SpatialNavigationEnabled, LocalContentCanAccessFileUrls, diff --git a/src/3rdparty/webkit/WebKit/qt/ChangeLog b/src/3rdparty/webkit/WebKit/qt/ChangeLog index 9dd129e..63d5568 100644 --- a/src/3rdparty/webkit/WebKit/qt/ChangeLog +++ b/src/3rdparty/webkit/WebKit/qt/ChangeLog @@ -1,3 +1,65 @@ +2010-07-09 Simon Hausmann + + Unreviewed trivial Symbian build fix. + + [Qt] Fix the Symbian build when compiling without S60 + + Use Q_OS_SYMBIAN instead of Q_WS_S60 for the user agent + determination. + + * Api/qwebpage.cpp: + (QWebPage::userAgentForUrl): + +2010-07-09 Kristian Amlie + + Reviewed by Simon Hausmann. + + [Qt] Fixed Qt symbian/linux-armcc mkspec when configured with -qtlibinfix. + + * declarative/declarative.pro: Use QT_LIBINFIX. + +2010-06-01 Raine Makelainen + + Reviewed by Simon Hausmann. + + [Qt]: REGRESSION(r58703): QWebSettings::JavascriptCanAccessClipboard has wrong case in "Javascript" part. + https://bugs.webkit.org/show_bug.cgi?id=39878 + + QWebSettings::JavaScriptCanAccessClipboard reverted back to + QWebSettings::JavascriptCanAccessClipboard. QWebSettings::DOMPasteAllowed enum removed. + + Value of QWebSettings::JavascriptCanAccessClipboard to setDOMPasteAllowed and + setJavaScriptCanAccessClipboard of WebCore::Settings. + + * Api/qwebsettings.cpp: + (QWebSettingsPrivate::apply): + * Api/qwebsettings.h: + +2010-05-03 Abhishek Arya + + Reviewed by Adam Barth. + + Add support for controlling clipboard access from javascript. + Clipboard access from javascript is disabled by default. + https://bugs.webkit.org/show_bug.cgi?id=27751 + + * Api/qwebsettings.cpp: + (QWebSettingsPrivate::apply): + * Api/qwebsettings.h: + +2010-03-24 Kent Hansen + + Reviewed by Simon Hausmann. + + [Qt] Rename QWebSettings::XSSAuditorEnabled to XSSAuditingEnabled + https://bugs.webkit.org/show_bug.cgi?id=36522 + + For consistency with other QWebSettings attributes. + + * Api/qwebsettings.cpp: + (QWebSettingsPrivate::apply): + * Api/qwebsettings.h: + 2010-05-19 Antti Koivisto Rubber-stamped by Kenneth Rohde Christiansen. -- cgit v0.12 From c950283638f05176f80b1fc6711a5340184e25e3 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 9 Jul 2010 12:01:07 +0200 Subject: Fix license headers on new files imported from Qt Creator Reviewed-by: Trust Me --- tools/runonphone/symbianutils/json.cpp | 40 ++++++++++++++++--------- tools/runonphone/symbianutils/json.h | 40 ++++++++++++++++--------- tools/runonphone/symbianutils/tcftrkdevice.cpp | 40 ++++++++++++++++--------- tools/runonphone/symbianutils/tcftrkdevice.h | 40 ++++++++++++++++--------- tools/runonphone/symbianutils/tcftrkmessage.cpp | 40 ++++++++++++++++--------- tools/runonphone/symbianutils/tcftrkmessage.h | 40 ++++++++++++++++--------- 6 files changed, 156 insertions(+), 84 deletions(-) diff --git a/tools/runonphone/symbianutils/json.cpp b/tools/runonphone/symbianutils/json.cpp index 4171125..2d58824 100644 --- a/tools/runonphone/symbianutils/json.cpp +++ b/tools/runonphone/symbianutils/json.cpp @@ -1,20 +1,19 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +/**************************************************************************** ** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** Commercial Usage +** This file is part of the tools applications of the Qt Toolkit. ** -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. ** ** 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 @@ -22,10 +21,23 @@ ** 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. ** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ ** -**************************************************************************/ +****************************************************************************/ #include "json.h" diff --git a/tools/runonphone/symbianutils/json.h b/tools/runonphone/symbianutils/json.h index ef574bd..ffcb7ab 100644 --- a/tools/runonphone/symbianutils/json.h +++ b/tools/runonphone/symbianutils/json.h @@ -1,20 +1,19 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +/**************************************************************************** ** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** Commercial Usage +** This file is part of the tools applications of the Qt Toolkit. ** -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. ** ** 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 @@ -22,10 +21,23 @@ ** 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. ** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ ** -**************************************************************************/ +****************************************************************************/ #ifndef SYMBIANUTILS_JSON_H #define SYMBIANUTILS_JSON_H diff --git a/tools/runonphone/symbianutils/tcftrkdevice.cpp b/tools/runonphone/symbianutils/tcftrkdevice.cpp index 723d5e9..50e3937 100644 --- a/tools/runonphone/symbianutils/tcftrkdevice.cpp +++ b/tools/runonphone/symbianutils/tcftrkdevice.cpp @@ -1,20 +1,19 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +/**************************************************************************** ** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** Commercial Usage +** This file is part of the tools applications of the Qt Toolkit. ** -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. ** ** 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 @@ -22,10 +21,23 @@ ** 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. ** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ ** -**************************************************************************/ +****************************************************************************/ #include "tcftrkdevice.h" #include "json.h" diff --git a/tools/runonphone/symbianutils/tcftrkdevice.h b/tools/runonphone/symbianutils/tcftrkdevice.h index bb4c184..67955e5 100644 --- a/tools/runonphone/symbianutils/tcftrkdevice.h +++ b/tools/runonphone/symbianutils/tcftrkdevice.h @@ -1,20 +1,19 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +/**************************************************************************** ** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** Commercial Usage +** This file is part of the tools applications of the Qt Toolkit. ** -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. ** ** 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 @@ -22,10 +21,23 @@ ** 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. ** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ ** -**************************************************************************/ +****************************************************************************/ #ifndef TCFTRKENGINE_H #define TCFTRKENGINE_H diff --git a/tools/runonphone/symbianutils/tcftrkmessage.cpp b/tools/runonphone/symbianutils/tcftrkmessage.cpp index 929bb8d..06035ab 100644 --- a/tools/runonphone/symbianutils/tcftrkmessage.cpp +++ b/tools/runonphone/symbianutils/tcftrkmessage.cpp @@ -1,20 +1,19 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +/**************************************************************************** ** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** Commercial Usage +** This file is part of the tools applications of the Qt Toolkit. ** -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. ** ** 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 @@ -22,10 +21,23 @@ ** 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. ** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ ** -**************************************************************************/ +****************************************************************************/ #include "tcftrkmessage.h" #include "json.h" diff --git a/tools/runonphone/symbianutils/tcftrkmessage.h b/tools/runonphone/symbianutils/tcftrkmessage.h index 8b073c8..510b485 100644 --- a/tools/runonphone/symbianutils/tcftrkmessage.h +++ b/tools/runonphone/symbianutils/tcftrkmessage.h @@ -1,20 +1,19 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +/**************************************************************************** ** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** Commercial Usage +** This file is part of the tools applications of the Qt Toolkit. ** -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. ** ** 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 @@ -22,10 +21,23 @@ ** 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. ** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ ** -**************************************************************************/ +****************************************************************************/ #ifndef TRCFTRKMESSAGE_H #define TRCFTRKMESSAGE_H -- cgit v0.12 From 767aa8d648bf81a3303da66a4fef98657ea5ece3 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 9 Jul 2010 12:16:35 +0200 Subject: Fix USB serial port detection of the Nokia N95 on linux The interface numbers in /dev/serial/by-id are hex rather than decimal. Also added code to read the manufacturer name and product name from string descriptors in order to get a better match. Unfortunately, root privilege is needed or the API returns an error. In this case, we still use the weak matching on interface number only. Task-Number: QTBUG-11794 Reviewed-By: Thomas Zander --- tools/runonphone/main.cpp | 2 +- tools/runonphone/serenum.h | 2 +- tools/runonphone/serenum_unix.cpp | 62 +++++++++++++++++++++++++++++++++++---- tools/runonphone/serenum_win.cpp | 2 +- 4 files changed, 59 insertions(+), 9 deletions(-) diff --git a/tools/runonphone/main.cpp b/tools/runonphone/main.cpp index dc83044..7767e4b 100644 --- a/tools/runonphone/main.cpp +++ b/tools/runonphone/main.cpp @@ -155,7 +155,7 @@ int main(int argc, char *argv[]) if (serialPortName.isEmpty()) { if (loglevel > 0) outstream << "Detecting serial ports" << endl; - foreach (const SerialPortId &id, enumerateSerialPorts()) { + foreach (const SerialPortId &id, enumerateSerialPorts(loglevel)) { if (loglevel > 0) outstream << "Port Name: " << id.portName << ", " << "Friendly Name:" << id.friendlyName << endl; diff --git a/tools/runonphone/serenum.h b/tools/runonphone/serenum.h index b794b97..a65c8cb 100644 --- a/tools/runonphone/serenum.h +++ b/tools/runonphone/serenum.h @@ -51,6 +51,6 @@ struct SerialPortId QString friendlyName; }; -QList enumerateSerialPorts(); +QList enumerateSerialPorts(int loglevel); #endif // WIN32SERENUM_H diff --git a/tools/runonphone/serenum_unix.cpp b/tools/runonphone/serenum_unix.cpp index b6f0293..4c90d7a 100644 --- a/tools/runonphone/serenum_unix.cpp +++ b/tools/runonphone/serenum_unix.cpp @@ -48,7 +48,7 @@ #include -QList enumerateSerialPorts() +QList enumerateSerialPorts(int loglevel) { QList eligableInterfaces; QList list; @@ -85,6 +85,41 @@ QList enumerateSerialPorts() } } } + + if (usableInterfaces.isEmpty()) + continue; + + QString manufacturerString; + QString productString; + + usb_dev_handle *devh = usb_open(device); + if (devh) { + QByteArray buf; + buf.resize(256); + int err = usb_get_string_simple(devh, device->descriptor.iManufacturer, buf.data(), buf.size()); + if (err < 0) { + if (loglevel > 1) + qDebug() << " can't read manufacturer name, error:" << err; + } else { + manufacturerString = QString::fromAscii(buf); + if (loglevel > 1) + qDebug() << " manufacturer:" << manufacturerString; + } + + buf.resize(256); + err = usb_get_string_simple(devh, device->descriptor.iProduct, buf.data(), buf.size()); + if (err < 0) { + if (loglevel > 1) + qDebug() << " can't read product name, error:" << err; + } else { + productString = QString::fromAscii(buf); + if (loglevel > 1) + qDebug() << " product:" << productString; + } + usb_close(devh); + } else if (loglevel > 0) { + qDebug() << " can't open usb device"; + } // second loop to find the actual data interface. foreach (int i, usableInterfaces) { @@ -94,11 +129,21 @@ QList enumerateSerialPorts() if (descriptor.bInterfaceNumber != i) continue; if (descriptor.bInterfaceClass == 10) { // "CDC Data" - // qDebug() << " found the data port" - // << "bus:" << bus->dirname - // << "device" << device->filename - // << "interface" << descriptor.bInterfaceNumber; - eligableInterfaces << QString("if%1").arg(QString::number(i), 2, QChar('0')); // fix! + if (loglevel > 1) { + qDebug() << " found the data port" + << "bus:" << bus->dirname + << "device" << device->filename + << "interface" << descriptor.bInterfaceNumber; + } + // ### manufacturer and product strings are only readable as root :( + if (!manufacturerString.isEmpty() && !productString.isEmpty()) { + eligableInterfaces << QString("usb-%1_%2-if%3") + .arg(manufacturerString.replace(QChar(' '), QChar('_'))) + .arg(productString.replace(QChar(' '), QChar('_'))) + .arg(i, 2, 16, QChar('0')); + } else { + eligableInterfaces << QString("if%1").arg(i, 2, 16, QChar('0')); // fix! + } } } } @@ -106,6 +151,9 @@ QList enumerateSerialPorts() } } } + + if (loglevel > 1) + qDebug() << " searching for interfaces:" << eligableInterfaces; QDir dir("/dev/serial/by-id/"); foreach (const QFileInfo &info, dir.entryInfoList()) { @@ -113,6 +161,8 @@ QList enumerateSerialPorts() bool usable = eligableInterfaces.isEmpty(); foreach (const QString &iface, eligableInterfaces) { if (info.fileName().contains(iface)) { + if (loglevel > 1) + qDebug() << " found device file:" << info.fileName() << endl; usable = true; break; } diff --git a/tools/runonphone/serenum_win.cpp b/tools/runonphone/serenum_win.cpp index 572161c..070cac2 100644 --- a/tools/runonphone/serenum_win.cpp +++ b/tools/runonphone/serenum_win.cpp @@ -53,7 +53,7 @@ //{4d36e978-e325-11ce-bfc1-08002be10318} //DEFINE_GUID(GUID_DEVCLASS_PORTS, 0x4D36E978, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 ); -QList enumerateSerialPorts() +QList enumerateSerialPorts(int) { DWORD index=0; SP_DEVINFO_DATA info; -- cgit v0.12 From 0efc71b7af2818f2f40438b2807efe361352f7a9 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 9 Jul 2010 14:31:04 +0200 Subject: Linux runonphone - tell the user which driver to load The linux usbserial driver doesn't attach to devices automatically, to avoid conflicts with the real driver (if there is one). So the user must run modprobe to load the driver before runonphone can be used. Since runonphone has found the correct device(s) using libusb, this patch will tell the user the modprobe command that is required to load the generic usbserial driver. Reviewed-By: Gareth Stockwell --- tools/runonphone/serenum_unix.cpp | 51 ++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/tools/runonphone/serenum_unix.cpp b/tools/runonphone/serenum_unix.cpp index 4c90d7a..db6375e 100644 --- a/tools/runonphone/serenum_unix.cpp +++ b/tools/runonphone/serenum_unix.cpp @@ -48,9 +48,32 @@ #include +class InterfaceInfo +{ +public: + InterfaceInfo(const QString &mf, const QString &pr, int mfid, int prid); + QString manufacturer; + QString product; + int manufacturerid; + int productid; +}; + +InterfaceInfo::InterfaceInfo(const QString &mf, const QString &pr, int mfid, int prid) : + manufacturer(mf), + product(pr), + manufacturerid(mfid), + productid(prid) +{ + if(mf.isEmpty()) + manufacturer = QString("[%1]").arg(mfid, 4, 16, QChar('0')); + if(pr.isEmpty()) + product = QString("[%1]").arg(prid, 4, 16, QChar('0')); +} + QList enumerateSerialPorts(int loglevel) { - QList eligableInterfaces; + QList eligibleInterfaces; + QList eligibleInterfacesInfo; QList list; usb_init(); @@ -137,13 +160,14 @@ QList enumerateSerialPorts(int loglevel) } // ### manufacturer and product strings are only readable as root :( if (!manufacturerString.isEmpty() && !productString.isEmpty()) { - eligableInterfaces << QString("usb-%1_%2-if%3") + eligibleInterfaces << QString("usb-%1_%2-if%3") .arg(manufacturerString.replace(QChar(' '), QChar('_'))) .arg(productString.replace(QChar(' '), QChar('_'))) .arg(i, 2, 16, QChar('0')); } else { - eligableInterfaces << QString("if%1").arg(i, 2, 16, QChar('0')); // fix! + eligibleInterfaces << QString("if%1").arg(i, 2, 16, QChar('0')); // fix! } + eligibleInterfacesInfo << InterfaceInfo(manufacturerString, productString, device->descriptor.idVendor, device->descriptor.idProduct); } } } @@ -153,13 +177,13 @@ QList enumerateSerialPorts(int loglevel) } if (loglevel > 1) - qDebug() << " searching for interfaces:" << eligableInterfaces; + qDebug() << " searching for interfaces:" << eligibleInterfaces; QDir dir("/dev/serial/by-id/"); foreach (const QFileInfo &info, dir.entryInfoList()) { if (!info.isDir()) { - bool usable = eligableInterfaces.isEmpty(); - foreach (const QString &iface, eligableInterfaces) { + bool usable = eligibleInterfaces.isEmpty(); + foreach (const QString &iface, eligibleInterfaces) { if (info.fileName().contains(iface)) { if (loglevel > 1) qDebug() << " found device file:" << info.fileName() << endl; @@ -176,6 +200,21 @@ QList enumerateSerialPorts(int loglevel) list << id; } } + + if (list.isEmpty() && !eligibleInterfacesInfo.isEmpty() && loglevel > 0) { + qDebug() << "Possible USB devices found, but without serial drivers:"; + foreach(const InterfaceInfo &iface, eligibleInterfacesInfo) { + qDebug() << " Manufacturer:" + << iface.manufacturer + << "Product:" + << iface.product + << endl + << " Load generic driver using:" + << QString("sudo modprobe usbserial vendor=0x%1 product=0x%2") + .arg(iface.manufacturerid, 4, 16, QChar('0')) + .arg(iface.productid, 4, 16, QChar('0')); + } + } return list; } -- cgit v0.12 From e45b8dceca9c424815c6b08355a95cb34382186c Mon Sep 17 00:00:00 2001 From: Jason McDonald Date: Mon, 12 Jul 2010 12:10:45 +1000 Subject: Fix qdoc error. Task-number: QTBUG-12078 Reviewed-By: Trust Me --- doc/src/external-resources.qdoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/external-resources.qdoc b/doc/src/external-resources.qdoc index cbd66ee..61c9da2 100644 --- a/doc/src/external-resources.qdoc +++ b/doc/src/external-resources.qdoc @@ -416,5 +416,5 @@ /*! \externalpage http://opensource.org/licenses/bsd-license.php - \title New and Modified BSD Licenses -*/ \ No newline at end of file + \title BSD License +*/ -- cgit v0.12