diff options
author | Olivier Goffart <olivier.goffart@nokia.com> | 2010-08-13 10:09:53 +0200 |
---|---|---|
committer | Olivier Goffart <olivier.goffart@nokia.com> | 2010-08-13 10:33:13 +0200 |
commit | 5114fcb45d584ea50da7397088f084dfd74922b9 (patch) | |
tree | 18cb40f048186ebf0eac568e2ae53ec092044c55 /src/gui | |
parent | 55e47566dd1ac83ff674401dfd6284f07490cd8b (diff) | |
parent | ee62807198a2525577c14f718b98d07ae0ec7bec (diff) | |
download | qt4-tools-5114fcb45d584ea50da7397088f084dfd74922b9.tar.gz |
Merge remote branch 'origin/4.7' into qt-master-from-4.7
Conflicts:
src/gui/painting/qpainter.cpp
src/gui/text/qtextengine.cpp
tests/auto/qimage/tst_qimage.cpp
tests/auto/qpainter/tst_qpainter.cpp
tools/qdoc3/test/assistant.qdocconf
tools/qdoc3/test/designer.qdocconf
tools/qdoc3/test/linguist.qdocconf
tools/qdoc3/test/qmake.qdocconf
tools/qdoc3/test/qt-build-docs.qdocconf
tools/qdoc3/test/qt-html-templates.qdocconf
tools/qdoc3/test/qt-html-templates_zh_CN.qdocconf
tools/qdoc3/test/qt.qdocconf
Diffstat (limited to 'src/gui')
80 files changed, 1680 insertions, 704 deletions
diff --git a/src/gui/dialogs/qfiledialog_mac.mm b/src/gui/dialogs/qfiledialog_mac.mm index f1afaa9874..64fc0ee0fa 100644 --- a/src/gui/dialogs/qfiledialog_mac.mm +++ b/src/gui/dialogs/qfiledialog_mac.mm @@ -782,9 +782,11 @@ void QFileDialogPrivate::qt_mac_filedialog_event_proc(const NavEventCallbackMess const QtMacFilterName &fn = fileDialogPrivate->filterInfo.filters.at( fileDialogPrivate->filterInfo.currentSelection); QStringList reg = fn.regexp.split(QLatin1String(";"), QString::SkipEmptyParts); - QString r = reg.first(); - r = r.right(r.length()-1); // Strip the * - base += r; //"." + QString::number(s->menuType); + if (reg.count()) { + QString r = reg.first(); + r = r.right(r.length()-1); // Strip the * + base += r; //"." + QString::number(s->menuType); + } NavDialogSetSaveFileName(p->context, QCFString::toCFStringRef(base)); } #ifdef DEBUG_FILEDIALOG_FILTERS diff --git a/src/gui/dialogs/qfontdialog_mac.mm b/src/gui/dialogs/qfontdialog_mac.mm index bb8ef3fd42..9c63dfab1c 100644 --- a/src/gui/dialogs/qfontdialog_mac.mm +++ b/src/gui/dialogs/qfontdialog_mac.mm @@ -131,6 +131,7 @@ const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWin - (QFont)qtFont; - (void)finishOffWithCode:(NSInteger)result; - (void)cleanUpAfterMyself; +- (void)setSubwindowStacking; @end static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont) @@ -187,6 +188,12 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont) [cancelButton setTarget:self]; } + mQtFont = new QFont(); + return self; +} + +- (void)setSubwindowStacking +{ #ifdef QT_MAC_USE_COCOA // Stack the native dialog in front of its parent, if any: QFontDialog *q = mPriv->fontDialog(); @@ -199,9 +206,6 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont) } } #endif - - mQtFont = new QFont(); - return self; } - (void)dealloc @@ -610,6 +614,7 @@ void QFontDialogPrivate::createNSFontPanelDelegate() [ourPanel setFrame:frameRect display:NO]; [ourPanel center]; } + [del setSubwindowStacking]; NSString *title = @"Select font"; [ourPanel setTitle:title]; } diff --git a/src/gui/embedded/qkbdlinuxinput_qws.cpp b/src/gui/embedded/qkbdlinuxinput_qws.cpp index 6c91a08498..f53c4445b8 100644 --- a/src/gui/embedded/qkbdlinuxinput_qws.cpp +++ b/src/gui/embedded/qkbdlinuxinput_qws.cpp @@ -138,7 +138,7 @@ QWSLinuxInputKbPrivate::QWSLinuxInputKbPrivate(QWSLinuxInputKeyboardHandler *h, // record the original mode so we can restore it again in the destructor. ::ioctl(m_tty_fd, KDGKBMODE, &m_orig_kbmode); - // setting this tranlation mode is even needed in INPUT mode to prevent + // setting this translation mode is even needed in INPUT mode to prevent // the shell from also interpreting codes, if the process has a tty // attached: e.g. Ctrl+C wouldn't copy, but kill the application. ::ioctl(m_tty_fd, KDSKBMODE, K_MEDIUMRAW); diff --git a/src/gui/embedded/qkbdqnx_qws.cpp b/src/gui/embedded/qkbdqnx_qws.cpp index fbc683ec27..72d1cb5727 100644 --- a/src/gui/embedded/qkbdqnx_qws.cpp +++ b/src/gui/embedded/qkbdqnx_qws.cpp @@ -150,7 +150,7 @@ void QWSQnxKeyboardHandler::socketActivated() // figure out whether it's a press bool isPress = packet.data.key_cap & KEY_DOWN; - // figure out wheter the key is still pressed and the key event is repeated + // figure out whether the key is still pressed and the key event is repeated bool isRepeat = packet.data.key_cap & KEY_REPEAT; Qt::Key key = Qt::Key_unknown; diff --git a/src/gui/graphicsview/qgraphicsgridlayout.cpp b/src/gui/graphicsview/qgraphicsgridlayout.cpp index 8a3f17a4e9..41048346a3 100644 --- a/src/gui/graphicsview/qgraphicsgridlayout.cpp +++ b/src/gui/graphicsview/qgraphicsgridlayout.cpp @@ -653,7 +653,8 @@ QSizeF QGraphicsGridLayout::sizeHint(Qt::SizeHint which, const QSizeF &constrain Q_D(const QGraphicsGridLayout); qreal left, top, right, bottom; getContentsMargins(&left, &top, &right, &bottom); - return d->engine.sizeHint(d->styleInfo(), which , constraint) + QSizeF(left + right, top + bottom); + const QSizeF extraMargins(left + right, top + bottom); + return d->engine.sizeHint(d->styleInfo(), which , constraint - extraMargins) + extraMargins; } diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index da69bee0df..fdc512e61a 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -3259,8 +3259,12 @@ void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool clim QGraphicsItem *p = parent; while (p) { if (p->flags() & QGraphicsItem::ItemIsFocusScope) { + QGraphicsItem *oldFocusScopeItem = p->d_ptr->focusScopeItem; p->d_ptr->focusScopeItem = q_ptr; if (!p->focusItem() && !focusFromShow) { + if (oldFocusScopeItem) + oldFocusScopeItem->d_ptr->focusScopeItemChange(false); + focusScopeItemChange(true); // If you call setFocus on a child of a focus scope that // doesn't currently have a focus item, then stop. return; @@ -3931,7 +3935,7 @@ void QGraphicsItem::setScale(qreal factor) Returns a list of graphics transforms that currently apply to this item. QGraphicsTransform is for applying and controlling a chain of individual - transformation operations on an item. It's particularily useful in + transformation operations on an item. It's particularly useful in animations, where each transform operation needs to be interpolated independently, or differently. @@ -3958,7 +3962,7 @@ QList<QGraphicsTransform *> QGraphicsItem::transformations() const an item, you can call setTransform(). QGraphicsTransform is for applying and controlling a chain of individual - transformation operations on an item. It's particularily useful in + transformation operations on an item. It's particularly useful in animations, where each transform operation needs to be interpolated independently, or differently. @@ -5152,7 +5156,7 @@ QPainterPath QGraphicsItem::opaqueArea() const The bounding region describes a coarse outline of the item's visual contents. Although it's expensive to calculate, it's also more precise than boundingRect(), and it can help to avoid unnecessary repainting when - an item is updated. This is particularily efficient for thin items (e.g., + an item is updated. This is particularly efficient for thin items (e.g., lines or simple polygons). You can tune the granularity for the bounding region by calling setBoundingRegionGranularity(). The default granularity is 0; in which the item's bounding region is the same as its bounding @@ -5595,6 +5599,7 @@ void QGraphicsItemPrivate::subFocusItemChange() */ void QGraphicsItemPrivate::focusScopeItemChange(bool isSubFocusItem) { + Q_UNUSED(isSubFocusItem); } /*! @@ -7753,6 +7758,21 @@ void QGraphicsItemPrivate::resetHeight() } /*! + \property QGraphicsObject::children + \internal +*/ + +/*! + \property QGraphicsObject::width + \internal +*/ + +/*! + \property QGraphicsObject::height + \internal +*/ + +/*! \property QGraphicsObject::parent \brief the parent of the item @@ -7965,6 +7985,24 @@ void QGraphicsItemPrivate::resetHeight() */ /*! + \property QGraphicsObject::children + \since 4.7 + \internal +*/ + +/*! + \property QGraphicsObject::width + \since 4.7 + \internal +*/ + +/*! + \property QGraphicsObject::height + \since 4.7 + \internal +*/ + +/*! \class QAbstractGraphicsShapeItem \brief The QAbstractGraphicsShapeItem class provides a common base for all path items. diff --git a/src/gui/graphicsview/qgraphicslayoutitem.cpp b/src/gui/graphicsview/qgraphicslayoutitem.cpp index f4d77f0ffd..bfe734af5e 100644 --- a/src/gui/graphicsview/qgraphicslayoutitem.cpp +++ b/src/gui/graphicsview/qgraphicslayoutitem.cpp @@ -48,6 +48,7 @@ #include "qgraphicslayoutitem.h" #include "qgraphicslayoutitem_p.h" #include "qwidget.h" +#include "qgraphicswidget.h" #include <QtDebug> @@ -139,9 +140,11 @@ QSizeF *QGraphicsLayoutItemPrivate::effectiveSizeHints(const QSizeF &constraint) if (!sizeHintCacheDirty && cachedConstraint == constraint) return cachedSizeHints; + const bool hasConstraint = constraint.width() >= 0 || constraint.height() >= 0; + for (int i = 0; i < Qt::NSizeHints; ++i) { cachedSizeHints[i] = constraint; - if (userSizeHints) + if (userSizeHints && !hasConstraint) combineSize(cachedSizeHints[i], userSizeHints[i]); } @@ -259,6 +262,52 @@ void QGraphicsLayoutItemPrivate::setSizeComponent( q->updateGeometry(); } + +bool QGraphicsLayoutItemPrivate::hasHeightForWidth() const +{ + Q_Q(const QGraphicsLayoutItem); + if (isLayout) { + const QGraphicsLayout *l = static_cast<const QGraphicsLayout *>(q); + for (int i = l->count() - 1; i >= 0; --i) { + if (QGraphicsLayoutItemPrivate::get(l->itemAt(i))->hasHeightForWidth()) + return true; + } + } else if (QGraphicsItem *item = q->graphicsItem()) { + if (item->isWidget()) { + QGraphicsWidget *w = static_cast<QGraphicsWidget *>(item); + if (w->layout()) { + return QGraphicsLayoutItemPrivate::get(w->layout())->hasHeightForWidth(); + } + } + } + return q->sizePolicy().hasHeightForWidth(); +} + +bool QGraphicsLayoutItemPrivate::hasWidthForHeight() const +{ + // enable this code when we add QSizePolicy::hasWidthForHeight() (For 4.8) +#if 1 + return false; +#else + Q_Q(const QGraphicsLayoutItem); + if (isLayout) { + const QGraphicsLayout *l = static_cast<const QGraphicsLayout *>(q); + for (int i = l->count() - 1; i >= 0; --i) { + if (QGraphicsLayoutItemPrivate::get(l->itemAt(i))->hasWidthForHeight()) + return true; + } + } else if (QGraphicsItem *item = q->graphicsItem()) { + if (item->isWidget()) { + QGraphicsWidget *w = static_cast<QGraphicsWidget *>(item); + if (w->layout()) { + return QGraphicsLayoutItemPrivate::get(w->layout())->hasWidthForHeight(); + } + } + } + return q->sizePolicy().hasWidthForHeight(); +#endif +} + /*! \class QGraphicsLayoutItem \brief The QGraphicsLayoutItem class can be inherited to allow your custom diff --git a/src/gui/graphicsview/qgraphicslayoutitem_p.h b/src/gui/graphicsview/qgraphicslayoutitem_p.h index 15cc7a59b2..b752e03ad2 100644 --- a/src/gui/graphicsview/qgraphicslayoutitem_p.h +++ b/src/gui/graphicsview/qgraphicslayoutitem_p.h @@ -65,6 +65,9 @@ class Q_AUTOTEST_EXPORT QGraphicsLayoutItemPrivate public: virtual ~QGraphicsLayoutItemPrivate(); QGraphicsLayoutItemPrivate(QGraphicsLayoutItem *parent, bool isLayout); + static QGraphicsLayoutItemPrivate *get(QGraphicsLayoutItem *q) { return q->d_func();} + static const QGraphicsLayoutItemPrivate *get(const QGraphicsLayoutItem *q) { return q->d_func();} + void init(); QSizeF *effectiveSizeHints(const QSizeF &constraint) const; QGraphicsItem *parentItem() const; @@ -73,6 +76,9 @@ public: enum SizeComponent { Width, Height }; void setSizeComponent(Qt::SizeHint which, SizeComponent component, qreal value); + bool hasHeightForWidth() const; + bool hasWidthForHeight() const; + QSizePolicy sizePolicy; QGraphicsLayoutItem *parent; diff --git a/src/gui/graphicsview/qgraphicslinearlayout.cpp b/src/gui/graphicsview/qgraphicslinearlayout.cpp index 37408efc69..1588364e97 100644 --- a/src/gui/graphicsview/qgraphicslinearlayout.cpp +++ b/src/gui/graphicsview/qgraphicslinearlayout.cpp @@ -528,7 +528,8 @@ QSizeF QGraphicsLinearLayout::sizeHint(Qt::SizeHint which, const QSizeF &constra Q_D(const QGraphicsLinearLayout); qreal left, top, right, bottom; getContentsMargins(&left, &top, &right, &bottom); - return d->engine.sizeHint(d->styleInfo(), which , constraint) + QSizeF(left + right, top + bottom); + const QSizeF extraMargins(left + right, top + bottom); + return d->engine.sizeHint(d->styleInfo(), which , constraint - extraMargins) + extraMargins; } /*! diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 654f60ffc7..6d1bb447cd 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -831,6 +831,11 @@ void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item, #endif //QT_NO_IM } + // This handles the case that the item has been removed from the + // scene in response to the FocusOut event. + if (item && item->scene() != q) + item = 0; + if (item) focusItem = item; updateInputMethodSensitivityInViews(); diff --git a/src/gui/graphicsview/qgraphicstransform.cpp b/src/gui/graphicsview/qgraphicstransform.cpp index 4ab69750b9..bd3f2efd32 100644 --- a/src/gui/graphicsview/qgraphicstransform.cpp +++ b/src/gui/graphicsview/qgraphicstransform.cpp @@ -267,6 +267,7 @@ void QGraphicsScale::setXScale(qreal scale) return; d->xScale = scale; update(); + emit xScaleChanged(); emit scaleChanged(); } @@ -293,6 +294,7 @@ void QGraphicsScale::setYScale(qreal scale) return; d->yScale = scale; update(); + emit yScaleChanged(); emit scaleChanged(); } @@ -319,6 +321,7 @@ void QGraphicsScale::setZScale(qreal scale) return; d->zScale = scale; update(); + emit zScaleChanged(); emit scaleChanged(); } @@ -342,6 +345,24 @@ void QGraphicsScale::applyTo(QMatrix4x4 *matrix) const */ /*! + \fn QGraphicsScale::xScaleChanged() + + QGraphicsScale emits this signal when its xScale changes. +*/ + +/*! + \fn QGraphicsScale::yScaleChanged() + + QGraphicsScale emits this signal when its yScale changes. +*/ + +/*! + \fn QGraphicsScale::zScaleChanged() + + QGraphicsScale emits this signal when its zScale changes. +*/ + +/*! \fn QGraphicsScale::scaleChanged() This signal is emitted whenever the xScale, yScale, or zScale @@ -562,6 +583,27 @@ void QGraphicsRotation::applyTo(QMatrix4x4 *matrix) const \sa QGraphicsRotation::axis */ +/*! + \fn QGraphicsScale::xScaleChanged() + \since 4.7 + + This signal is emitted whenever the \l xScale property changes. +*/ + +/*! + \fn QGraphicsScale::yScaleChanged() + \since 4.7 + + This signal is emitted whenever the \l yScale property changes. +*/ + +/*! + \fn QGraphicsScale::zScaleChanged() + \since 4.7 + + This signal is emitted whenever the \l zScale property changes. +*/ + #include "moc_qgraphicstransform.cpp" QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicstransform.h b/src/gui/graphicsview/qgraphicstransform.h index 58b201a79a..d8c9654f19 100644 --- a/src/gui/graphicsview/qgraphicstransform.h +++ b/src/gui/graphicsview/qgraphicstransform.h @@ -85,9 +85,9 @@ class Q_GUI_EXPORT QGraphicsScale : public QGraphicsTransform Q_OBJECT Q_PROPERTY(QVector3D origin READ origin WRITE setOrigin NOTIFY originChanged) - Q_PROPERTY(qreal xScale READ xScale WRITE setXScale NOTIFY scaleChanged) - Q_PROPERTY(qreal yScale READ yScale WRITE setYScale NOTIFY scaleChanged) - Q_PROPERTY(qreal zScale READ zScale WRITE setZScale NOTIFY scaleChanged) + Q_PROPERTY(qreal xScale READ xScale WRITE setXScale NOTIFY xScaleChanged) + Q_PROPERTY(qreal yScale READ yScale WRITE setYScale NOTIFY yScaleChanged) + Q_PROPERTY(qreal zScale READ zScale WRITE setZScale NOTIFY zScaleChanged) public: QGraphicsScale(QObject *parent = 0); ~QGraphicsScale(); @@ -108,6 +108,9 @@ public: Q_SIGNALS: void originChanged(); + void xScaleChanged(); + void yScaleChanged(); + void zScaleChanged(); void scaleChanged(); private: diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index c486c451a8..0fabd18bda 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -385,12 +385,12 @@ void QGraphicsWidget::setGeometry(const QRectF &rect) if (wd->inSetPos) { //set the new pos d->geom.moveTopLeft(pos()); + emit geometryChanged(); return; } } QSizeF oldSize = size(); QGraphicsLayoutItem::setGeometry(newGeom); - emit geometryChanged(); // Send resize event bool resized = newGeom.size() != oldSize; if (resized) { @@ -403,6 +403,7 @@ void QGraphicsWidget::setGeometry(const QRectF &rect) emit heightChanged(); QApplication::sendEvent(this, &re); } + emit geometryChanged(); } /*! diff --git a/src/gui/graphicsview/qgridlayoutengine.cpp b/src/gui/graphicsview/qgridlayoutengine.cpp index 8b65282a08..98e67811f6 100644 --- a/src/gui/graphicsview/qgridlayoutengine.cpp +++ b/src/gui/graphicsview/qgridlayoutengine.cpp @@ -250,6 +250,7 @@ void QGridLayoutRowData::calculateGeometries(int start, int end, qreal targetSiz sumAvailable = targetSize - totalBox.q_preferredSize; if (sumAvailable > 0.0) { + qreal sumCurrentAvailable = sumAvailable; bool somethingHasAMaximumSize = false; qreal sumPreferredSizes = 0.0; @@ -308,12 +309,12 @@ void QGridLayoutRowData::calculateGeometries(int start, int end, qreal targetSiz qreal ultimateFactor = (stretch * ultimateSumPreferredSizes / sumStretches) - (box.q_preferredSize); - qreal transitionalFactor = sumAvailable + qreal transitionalFactor = sumCurrentAvailable * (ultimatePreferredSize - box.q_preferredSize) / (ultimateSumPreferredSizes - sumPreferredSizes); - qreal alpha = qMin(sumAvailable, + qreal alpha = qMin(sumCurrentAvailable, ultimateSumPreferredSizes - sumPreferredSizes); qreal beta = ultimateSumPreferredSizes - sumPreferredSizes; @@ -321,7 +322,7 @@ void QGridLayoutRowData::calculateGeometries(int start, int end, qreal targetSiz + ((beta - alpha) * transitionalFactor)) / beta; } sumFactors += factors[i]; - if (desired < sumAvailable) + if (desired < sumCurrentAvailable) somethingHasAMaximumSize = true; newSizes[i] = -1.0; @@ -337,12 +338,12 @@ void QGridLayoutRowData::calculateGeometries(int start, int end, qreal targetSiz continue; const QGridLayoutBox &box = boxes.at(start + i); - qreal avail = sumAvailable * factors[i] / sumFactors; + qreal avail = sumCurrentAvailable * factors[i] / sumFactors; if (sizes[i] + avail >= box.q_maximumSize) { newSizes[i] = box.q_maximumSize; - sumAvailable -= box.q_maximumSize - sizes[i]; + sumCurrentAvailable -= box.q_maximumSize - sizes[i]; sumFactors -= factors[i]; - keepGoing = (sumAvailable > 0.0); + keepGoing = (sumCurrentAvailable > 0.0); if (!keepGoing) break; } @@ -352,7 +353,7 @@ void QGridLayoutRowData::calculateGeometries(int start, int end, qreal targetSiz for (int i = 0; i < n; ++i) { if (newSizes[i] < 0.0) { qreal delta = (sumFactors == 0.0) ? 0.0 - : sumAvailable * factors[i] / sumFactors; + : sumCurrentAvailable * factors[i] / sumFactors; newSizes[i] = sizes[i] + delta; } } @@ -545,6 +546,24 @@ QSizePolicy::Policy QGridLayoutItem::sizePolicy(Qt::Orientation orientation) con : sizePolicy.verticalPolicy(); } +/* + returns true if the size policy returns true for either hasHeightForWidth() + or hasWidthForHeight() + */ +bool QGridLayoutItem::hasDynamicConstraint() const +{ + return QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasHeightForWidth() + || QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasWidthForHeight(); +} + +Qt::Orientation QGridLayoutItem::dynamicConstraintOrientation() const +{ + if (QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasHeightForWidth()) + return Qt::Vertical; + else //if (QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasWidthForHeight()) + return Qt::Horizontal; +} + QSizePolicy::ControlTypes QGridLayoutItem::controlTypes(LayoutSide /* side */) const { return q_layoutItem->sizePolicy().controlType(); @@ -613,7 +632,14 @@ QRectF QGridLayoutItem::geometryWithin(qreal x, qreal y, qreal width, qreal heig qreal cellWidth = width; qreal cellHeight = height; - QSizeF size = effectiveMaxSize().boundedTo(QSizeF(cellWidth, cellHeight)); + QSize constraint; + if (hasDynamicConstraint()) { + if (dynamicConstraintOrientation() == Qt::Vertical) + constraint.setWidth(cellWidth); + else + constraint.setHeight(cellHeight); + } + QSizeF size = effectiveMaxSize(constraint).boundedTo(QSizeF(cellWidth, cellHeight)); width = size.width(); height = size.height(); @@ -675,13 +701,13 @@ void QGridLayoutItem::insertOrRemoveRows(int row, int delta, Qt::Orientation ori Note that effectiveSizeHint does not take sizePolicy into consideration, (since it only evaluates the hints, as the name implies) */ -QSizeF QGridLayoutItem::effectiveMaxSize() const +QSizeF QGridLayoutItem::effectiveMaxSize(const QSizeF &constraint) const { - QSizeF size; + QSizeF size = constraint; bool vGrow = (sizePolicy(Qt::Vertical) & QSizePolicy::GrowFlag) == QSizePolicy::GrowFlag; bool hGrow = (sizePolicy(Qt::Horizontal) & QSizePolicy::GrowFlag) == QSizePolicy::GrowFlag; if (!vGrow || !hGrow) { - QSizeF pref = layoutItem()->effectiveSizeHint(Qt::PreferredSize); + QSizeF pref = layoutItem()->effectiveSizeHint(Qt::PreferredSize, constraint); if (!vGrow) size.setHeight(pref.height()); if (!hGrow) @@ -689,7 +715,7 @@ QSizeF QGridLayoutItem::effectiveMaxSize() const } if (!size.isValid()) { - QSizeF maxSize = layoutItem()->effectiveSizeHint(Qt::MaximumSize); + QSizeF maxSize = layoutItem()->effectiveSizeHint(Qt::MaximumSize, constraint); if (size.width() == -1) size.setWidth(maxSize.width()); if (size.height() == -1) @@ -1019,6 +1045,7 @@ void QGridLayoutEngine::invalidate() q_cachedEffectiveLastRows[Ver] = -1; q_cachedDataForStyleInfo.invalidate(); q_cachedSize = QSizeF(); + q_cachedConstraintOrientation = UnknownConstraint; } static void visualRect(QRectF *geom, Qt::LayoutDirection dir, const QRectF &contentsRect) @@ -1083,10 +1110,13 @@ QRectF QGridLayoutEngine::cellRect(const QLayoutStyleInfo &styleInfo, } QSizeF QGridLayoutEngine::sizeHint(const QLayoutStyleInfo &styleInfo, Qt::SizeHint which, - const QSizeF & /* constraint */) const + const QSizeF &constraint) const { ensureColumnAndRowData(styleInfo); + if (hasDynamicConstraint()) + return dynamicallyConstrainedSizeHint(which, constraint); + switch (which) { case Qt::MinimumSize: return QSizeF(q_totalBoxes[Hor].q_minimumSize, q_totalBoxes[Ver].q_minimumSize); @@ -1384,7 +1414,11 @@ void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, const QLayoutSt box = &multiCell.q_box; multiCell.q_stretch = itemStretch; } - box->combine(item->box(orientation)); + // Items with constraints are not included in the orientation that + // they are constrained (since it depends on the hfw/constraint function). + // They must be combined at a later stage. + if (!item->hasDynamicConstraint() || orientation != item->dynamicConstraintOrientation()) + box->combine(item->box(orientation)); if (effectiveRowSpan == 1) { QSizePolicy::ControlTypes controls = item->controlTypes(top); @@ -1541,6 +1575,138 @@ void QGridLayoutEngine::ensureColumnAndRowData(const QLayoutStyleInfo &styleInfo q_cachedDataForStyleInfo = styleInfo; } +QSizeF QGridLayoutEngine::dynamicallyConstrainedSizeHint(Qt::SizeHint which, + const QSizeF &constraint) const +{ + Q_ASSERT(hasDynamicConstraint()); + if (constraint.width() < 0 && constraint.height() < 0) { + // Process the hfw / wfh items that we did not process in fillRowData() + const Qt::Orientation constraintOrient = constraintOrientation(); + + QGridLayoutRowData rowData = constraintOrient == Qt::Vertical ? q_rowData : q_columnData; + for (int i = q_items.count() - 1; i >= 0; --i) { + QGridLayoutItem *item = q_items.at(i); + if (item->hasDynamicConstraint()) { + QGridLayoutBox box = item->box(constraintOrient); + QGridLayoutBox &rowBox = rowData.boxes[item->firstRow(constraintOrient)]; + rowBox.combine(box); + } + } + + QGridLayoutBox totalBoxes[2]; + if (constraintOrient == Qt::Vertical) { + totalBoxes[Hor] = q_columnData.totalBox(0, columnCount()); + totalBoxes[Ver] = rowData.totalBox(0, rowCount()); + } else { + totalBoxes[Hor] = rowData.totalBox(0, columnCount()); + totalBoxes[Ver] = q_rowData.totalBox(0, rowCount()); + } + return QSizeF(totalBoxes[Hor].q_sizes(which), totalBoxes[Ver].q_sizes(which)); + } + + + Q_ASSERT(constraint.width() >= 0 || constraint.height() >= 0); + q_xx.resize(columnCount()); + q_yy.resize(rowCount()); + q_widths.resize(columnCount()); + q_heights.resize(rowCount()); + q_descents.resize(rowCount()); + + + const Qt::Orientation orientation = constraintOrientation(); + QGridLayoutRowData *colData; + QGridLayoutRowData constrainedRowData; + QGridLayoutBox *totalBox; + qreal *sizes; + qreal *pos; + qreal *descents; + qreal targetSize; + qreal cCount; + qreal rCount; + + if (orientation == Qt::Vertical) { + // height for width + colData = &q_columnData; + totalBox = &q_totalBoxes[Hor]; + sizes = q_widths.data(); + pos = q_xx.data(); + descents = 0; + targetSize = constraint.width(); + cCount = columnCount(); + rCount = rowCount(); + constrainedRowData = q_rowData; + } else { + // width for height + colData = &q_rowData; + totalBox = &q_totalBoxes[Ver]; + sizes = q_heights.data(); + pos = q_yy.data(); + descents = q_descents.data(); + targetSize = constraint.height(); + cCount = rowCount(); + rCount = columnCount(); + constrainedRowData = q_columnData; + } + colData->calculateGeometries(0, cCount, targetSize, pos, sizes, descents, *totalBox); + for (int i = q_items.count() - 1; i >= 0; --i) { + QGridLayoutItem *item = q_items.at(i); + + if (item->hasDynamicConstraint()) { + const qreal size = sizes[item->firstColumn(orientation)]; + QGridLayoutBox box = item->box(orientation, size); + QGridLayoutBox &rowBox = constrainedRowData.boxes[item->firstRow(orientation)]; + rowBox.combine(box); + } + } + const qreal newSize = constrainedRowData.totalBox(0, rCount).q_sizes(which); + + return (orientation == Qt::Vertical) ? QSizeF(targetSize, newSize) : QSizeF(newSize, targetSize); +} + + +/** + returns false if the layout has contradicting constraints (i.e. some items with a horizontal + constraint and other items with a vertical constraint) + */ +bool QGridLayoutEngine::ensureDynamicConstraint() const +{ + if (q_cachedConstraintOrientation == UnknownConstraint) { + for (int i = q_items.count() - 1; i >= 0; --i) { + QGridLayoutItem *item = q_items.at(i); + if (item->hasDynamicConstraint()) { + Qt::Orientation itemConstraintOrientation = item->dynamicConstraintOrientation(); + if (q_cachedConstraintOrientation == UnknownConstraint) { + q_cachedConstraintOrientation = itemConstraintOrientation; + } else if (q_cachedConstraintOrientation != itemConstraintOrientation) { + q_cachedConstraintOrientation = UnfeasibleConstraint; + qWarning("QGridLayoutEngine: Unfeasible, cannot mix horizontal and" + " vertical constraint in the same layout"); + return false; + } + } + } + if (q_cachedConstraintOrientation == UnknownConstraint) + q_cachedConstraintOrientation = NoConstraint; + } + return true; +} + +bool QGridLayoutEngine::hasDynamicConstraint() const +{ + if (!ensureDynamicConstraint()) + return false; + return q_cachedConstraintOrientation != NoConstraint; +} + +/* + * return value is only valid if hasConstraint() returns true + */ +Qt::Orientation QGridLayoutEngine::constraintOrientation() const +{ + (void)ensureDynamicConstraint(); + return (Qt::Orientation)q_cachedConstraintOrientation; +} + void QGridLayoutEngine::ensureGeometries(const QLayoutStyleInfo &styleInfo, const QSizeF &size) const { @@ -1553,10 +1719,74 @@ void QGridLayoutEngine::ensureGeometries(const QLayoutStyleInfo &styleInfo, q_widths.resize(columnCount()); q_heights.resize(rowCount()); q_descents.resize(rowCount()); - q_columnData.calculateGeometries(0, columnCount(), size.width(), q_xx.data(), q_widths.data(), - 0, q_totalBoxes[Hor]); - q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(), - q_descents.data(), q_totalBoxes[Ver]); + + + Qt::Orientation orientation = Qt::Vertical; + if (hasDynamicConstraint()) + orientation = constraintOrientation(); + + /* + In order to do hfw we need to first distribute the columns, then the rows. + In order to do wfh we need to first distribute the rows, then the columns. + + If there is no constraint, the order of distributing the rows or columns first is irrelevant. + We choose horizontal just to keep the same behaviour as before (however, there shouldn't + be any behaviour difference). + */ + + QGridLayoutRowData *colData; + QGridLayoutRowData rowData; + qreal *widths; + qreal *heights; + qreal *xx; + qreal *yy; + qreal *xdescents = 0; + qreal *ydescents = 0; + qreal cCount; + qreal rCount; + QSizeF oSize = size; + if (orientation == Qt::Vertical) { + // height for width + colData = &q_columnData; + rowData = q_rowData; + widths = q_widths.data(); + heights = q_heights.data(); + xx = q_xx.data(); + yy = q_yy.data(); + cCount = columnCount(); + rCount = rowCount(); + ydescents = q_descents.data(); + } else { + // width for height + colData = &q_rowData; + rowData = q_columnData; + widths = q_heights.data(); + heights = q_widths.data(); + xx = q_yy.data(); + yy = q_xx.data(); + cCount = rowCount(); + rCount = columnCount(); + xdescents = q_descents.data(); + oSize.transpose(); + } + + colData->calculateGeometries(0, cCount, oSize.width(), xx, widths, + xdescents, q_totalBoxes[orientation == Qt::Horizontal]); + for (int i = q_items.count() - 1; i >= 0; --i) { + QGridLayoutItem *item = q_items.at(i); + const int col = item->firstColumn(orientation); + const int row = item->firstRow(orientation); + if (item->hasDynamicConstraint()) { + const qreal sz = widths[col]; + QGridLayoutBox box = item->box(orientation, sz); + rowData.boxes[row].combine(box); + } + } + + QGridLayoutBox &totalBox = q_totalBoxes[orientation == Qt::Vertical]; + totalBox = rowData.totalBox(0, rCount); + rowData.calculateGeometries(0, rCount, oSize.height(), yy, heights, + ydescents, totalBox); q_cachedSize = size; } diff --git a/src/gui/graphicsview/qgridlayoutengine_p.h b/src/gui/graphicsview/qgridlayoutengine_p.h index a4ef21d924..55451d758b 100644 --- a/src/gui/graphicsview/qgridlayoutengine_p.h +++ b/src/gui/graphicsview/qgridlayoutengine_p.h @@ -91,6 +91,14 @@ enum LayoutSide { Bottom }; +enum { + NoConstraint, + HorizontalConstraint, + VerticalConstraint, + UnknownConstraint, // need to update cache + UnfeasibleConstraint // not feasible, it be has some items with Vertical and others with Horizontal constraints +}; + template <typename T> class QLayoutParameter { @@ -270,6 +278,10 @@ public: inline void setAlignment(Qt::Alignment alignment) { q_alignment = alignment; } QSizePolicy::Policy sizePolicy(Qt::Orientation orientation) const; + + bool hasDynamicConstraint() const; + Qt::Orientation dynamicConstraintOrientation() const; + QSizePolicy::ControlTypes controlTypes(LayoutSide side) const; QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; QGridLayoutBox box(Qt::Orientation orientation, qreal constraint = -1.0) const; @@ -280,7 +292,7 @@ public: void setGeometry(const QRectF &rect); void transpose(); void insertOrRemoveRows(int row, int delta, Qt::Orientation orientation = Qt::Vertical); - QSizeF effectiveMaxSize() const; + QSizeF effectiveMaxSize(const QSizeF &constraint) const; #ifdef QT_DEBUG void dump(int indent = 0) const; @@ -373,6 +385,14 @@ public: int column, int rowSpan, int columnSpan) const; QSizeF sizeHint(const QLayoutStyleInfo &styleInfo, Qt::SizeHint which, const QSizeF &constraint) const; + + // heightForWidth / widthForHeight support + QSizeF dynamicallyConstrainedSizeHint(Qt::SizeHint which, const QSizeF &constraint) const; + bool ensureDynamicConstraint() const; + bool hasDynamicConstraint() const; + Qt::Orientation constraintOrientation() const; + + QSizePolicy::ControlTypes controlTypes(LayoutSide side) const; void transpose(); void setVisualDirection(Qt::LayoutDirection direction); @@ -406,6 +426,7 @@ private: // Lazily computed from the above user input mutable int q_cachedEffectiveFirstRows[NOrientations]; mutable int q_cachedEffectiveLastRows[NOrientations]; + mutable quint8 q_cachedConstraintOrientation : 2; // Layout item input mutable QLayoutStyleInfo q_cachedDataForStyleInfo; diff --git a/src/gui/gui.pro b/src/gui/gui.pro index 1b43ef2036..3943e261c1 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -77,20 +77,28 @@ symbian { DEPLOYMENT = partial_upgrade $$DEPLOYMENT } +neon:*-g++* { + DEFINES += QT_HAVE_NEON + QMAKE_CXXFLAGS *= -mfpu=neon + HEADERS += $$NEON_HEADERS + SOURCES += $$NEON_SOURCES + + DRAWHELPER_NEON_ASM_FILES = $$NEON_ASM + + neon_compiler.commands = $$QMAKE_CXX -c + neon_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} + neon_compiler.dependency_type = TYPE_C + neon_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} + neon_compiler.input = DRAWHELPER_NEON_ASM_FILES + neon_compiler.variable_out = OBJECTS + neon_compiler.name = compiling[neon] ${QMAKE_FILE_IN} + silent:neon_compiler.commands = @echo compiling[neon] ${QMAKE_FILE_IN} && $$neon_compiler.commands + QMAKE_EXTRA_COMPILERS += neon_compiler +} + 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 - sse3:DEFINES += QT_HAVE_SSE3 - ssse3:DEFINES += QT_HAVE_SSSE3 - sse4_1:DEFINES += QT_HAVE_SSE4_1 - sse4_2:DEFINES += QT_HAVE_SSE4_2 - avx:DEFINES += QT_HAVE_AVX - iwmmxt:DEFINES += QT_HAVE_IWMMXT - win32-g++*|!win32:!*-icc* { mmx { mmx_compiler.commands = $$QMAKE_CXX -c -Winline diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri index b20a04f104..f89706cc7c 100644 --- a/src/gui/image/image.pri +++ b/src/gui/image/image.pri @@ -94,5 +94,6 @@ contains(QT_CONFIG, tiff):include($$PWD/qtiffhandler.pri) contains(QT_CONFIG, gif):include($$PWD/qgifhandler.pri) # SIMD +NEON_SOURCES += image/qimage_neon.cpp SSE2_SOURCES += image/qimage_sse2.cpp SSSE3_SOURCES += image/qimage_ssse3.cpp diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 0e7ced83e1..300e04b4ee 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -3851,6 +3851,14 @@ void qInitImageConversions() converter_map[QImage::Format_RGB888][QImage::Format_ARGB32_Premultiplied] = convert_RGB888_to_RGB32_ssse3; } #endif +#ifdef QT_HAVE_NEON + if (features & NEON) { + extern void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags); + converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_neon; + converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_neon; + converter_map[QImage::Format_RGB888][QImage::Format_ARGB32_Premultiplied] = convert_RGB888_to_RGB32_neon; + } +#endif } /*! @@ -4911,7 +4919,7 @@ QImage QImage::rgbSwapped() const QIMAGE_SANITYCHECK_MEMORY(res); for (int i = 0; i < d->height; i++) { uint *q = (uint*)res.scanLine(i); - uint *p = (uint*)scanLine(i); + uint *p = (uint*)constScanLine(i); uint *end = p + d->width; while (p < end) { *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00); @@ -4925,7 +4933,7 @@ QImage QImage::rgbSwapped() const QIMAGE_SANITYCHECK_MEMORY(res); for (int i = 0; i < d->height; i++) { ushort *q = (ushort*)res.scanLine(i); - const ushort *p = (const ushort*)scanLine(i); + const ushort *p = (const ushort*)constScanLine(i); const ushort *end = p + d->width; while (p < end) { *q = ((*p << 11) & 0xf800) | ((*p >> 11) & 0x1f) | (*p & 0x07e0); @@ -4938,12 +4946,15 @@ QImage QImage::rgbSwapped() const res = QImage(d->width, d->height, d->format); QIMAGE_SANITYCHECK_MEMORY(res); for (int i = 0; i < d->height; i++) { - quint8 *p = (quint8*)scanLine(i); + const quint8 *p = constScanLine(i); + quint8 *q = res.scanLine(i); const quint8 *end = p + d->width * sizeof(qargb8565); while (p < end) { - quint16 *q = reinterpret_cast<quint16*>(p + 1); - *q = ((*q << 11) & 0xf800) | ((*q >> 11) & 0x1f) | (*q & 0x07e0); + q[0] = p[0]; + q[1] = (p[1] & 0xe0) | (p[2] >> 3); + q[2] = (p[2] & 0x07) | (p[1] << 3); p += sizeof(qargb8565); + q += sizeof(qargb8565); } } break; @@ -4952,7 +4963,7 @@ QImage QImage::rgbSwapped() const QIMAGE_SANITYCHECK_MEMORY(res); for (int i = 0; i < d->height; i++) { qrgb666 *q = reinterpret_cast<qrgb666*>(res.scanLine(i)); - const qrgb666 *p = reinterpret_cast<const qrgb666*>(scanLine(i)); + const qrgb666 *p = reinterpret_cast<const qrgb666*>(constScanLine(i)); const qrgb666 *end = p + d->width; while (p < end) { const QRgb rgb = quint32(*p++); @@ -4964,12 +4975,15 @@ QImage QImage::rgbSwapped() const res = QImage(d->width, d->height, d->format); QIMAGE_SANITYCHECK_MEMORY(res); for (int i = 0; i < d->height; i++) { - qargb6666 *q = reinterpret_cast<qargb6666*>(res.scanLine(i)); - const qargb6666 *p = reinterpret_cast<const qargb6666*>(scanLine(i)); - const qargb6666 *end = p + d->width; + const quint8 *p = constScanLine(i); + const quint8 *end = p + d->width * sizeof(qargb6666); + quint8 *q = res.scanLine(i); while (p < end) { - const QRgb rgb = quint32(*p++); - *q++ = qRgba(qBlue(rgb), qGreen(rgb), qRed(rgb), qAlpha(rgb)); + q[0] = (p[1] >> 4) | ((p[2] & 0x3) << 4) | (p[0] & 0xc0); + q[1] = (p[1] & 0xf) | (p[0] << 4); + q[2] = (p[2] & 0xfc) | ((p[0] >> 4) & 0x3); + p += sizeof(qargb6666); + q += sizeof(qargb6666); } } break; @@ -4977,11 +4991,11 @@ QImage QImage::rgbSwapped() const res = QImage(d->width, d->height, d->format); QIMAGE_SANITYCHECK_MEMORY(res); for (int i = 0; i < d->height; i++) { - ushort *q = (ushort*)res.scanLine(i); - const ushort *p = (const ushort*)scanLine(i); - const ushort *end = p + d->width; + quint16 *q = (quint16*)res.scanLine(i); + const quint16 *p = (const quint16*)constScanLine(i); + const quint16 *end = p + d->width; while (p < end) { - *q = ((*p << 10) & 0x7800) | ((*p >> 10) & 0x1f) | (*p & 0x83e0); + *q = ((*p << 10) & 0x7c00) | ((*p >> 10) & 0x1f) | (*p & 0x3e0); p++; q++; } @@ -4991,12 +5005,15 @@ QImage QImage::rgbSwapped() const res = QImage(d->width, d->height, d->format); QIMAGE_SANITYCHECK_MEMORY(res); for (int i = 0; i < d->height; i++) { - quint8 *p = (quint8*)scanLine(i); + const quint8 *p = constScanLine(i); + quint8 *q = res.scanLine(i); const quint8 *end = p + d->width * sizeof(qargb8555); while (p < end) { - quint16 *q = reinterpret_cast<quint16*>(p + 1); - *q = ((*q << 10) & 0x7800) | ((*q >> 10) & 0x1f) | (*q & 0x83e0); + q[0] = p[0]; + q[1] = (p[1] & 0xe0) | (p[2] >> 2); + q[2] = (p[2] & 0x03) | ((p[1] << 2) & 0x7f); p += sizeof(qargb8555); + q += sizeof(qargb8555); } } break; @@ -5004,8 +5021,8 @@ QImage QImage::rgbSwapped() const res = QImage(d->width, d->height, d->format); QIMAGE_SANITYCHECK_MEMORY(res); for (int i = 0; i < d->height; i++) { - quint8 *q = reinterpret_cast<quint8*>(res.scanLine(i)); - const quint8 *p = reinterpret_cast<const quint8*>(scanLine(i)); + quint8 *q = res.scanLine(i); + const quint8 *p = constScanLine(i); const quint8 *end = p + d->width * sizeof(qrgb888); while (p < end) { q[0] = p[2]; @@ -5017,32 +5034,17 @@ QImage QImage::rgbSwapped() const } break; case Format_RGB444: - res = QImage(d->width, d->height, d->format); - QIMAGE_SANITYCHECK_MEMORY(res); - for (int i = 0; i < d->height; i++) { - quint8 *q = reinterpret_cast<quint8*>(res.scanLine(i)); - const quint8 *p = reinterpret_cast<const quint8*>(scanLine(i)); - const quint8 *end = p + d->width * sizeof(qrgb444); - while (p < end) { - q[0] = (p[0] & 0xf0) | ((p[1] & 0x0f) << 8); - q[1] = ((p[0] & 0x0f) >> 8) | (p[1] & 0xf0); - q += sizeof(qrgb444); - p += sizeof(qrgb444); - } - } - break; case Format_ARGB4444_Premultiplied: res = QImage(d->width, d->height, d->format); QIMAGE_SANITYCHECK_MEMORY(res); for (int i = 0; i < d->height; i++) { - quint8 *q = reinterpret_cast<quint8*>(res.scanLine(i)); - const quint8 *p = reinterpret_cast<const quint8*>(scanLine(i)); - const quint8 *end = p + d->width * sizeof(qargb4444); + quint16 *q = reinterpret_cast<quint16*>(res.scanLine(i)); + const quint16 *p = reinterpret_cast<const quint16*>(constScanLine(i)); + const quint16 *end = p + d->width; while (p < end) { - q[0] = (p[0] & 0xf0) | ((p[1] & 0x0f) << 8); - q[1] = ((p[0] & 0x0f) >> 8) | (p[1] & 0xf0); - q += sizeof(qargb4444); - p += sizeof(qargb4444); + *q = (*p & 0xf0f0) | ((*p & 0x0f) << 8) | ((*p & 0xf00) >> 8); + p++; + q++; } } break; diff --git a/src/gui/image/qimage_neon.cpp b/src/gui/image/qimage_neon.cpp new file mode 100644 index 0000000000..15bf4721e8 --- /dev/null +++ b/src/gui/image/qimage_neon.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** 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 <private/qimage_p.h> +#include <private/qsimd_p.h> + +#ifdef QT_HAVE_NEON + +QT_BEGIN_NAMESPACE + +Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_neon(quint32 *dst, const uchar *src, int len) +{ + if (!len) + return; + + const quint32 *const end = dst + len; + + // align dst on 64 bits + const int offsetToAlignOn8Bytes = (reinterpret_cast<quintptr>(dst) >> 2) & 0x1; + for (int i = 0; i < offsetToAlignOn8Bytes; ++i) { + *dst++ = qRgb(src[0], src[1], src[2]); + src += 3; + } + + if ((len - offsetToAlignOn8Bytes) >= 8) { + const quint32 *const simdEnd = end - 7; + register uint8x8_t fullVector asm ("d3") = vdup_n_u8(0xff); + do { +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + asm volatile ( + "vld3.8 { d4, d5, d6 }, [%[SRC]] !\n\t" + "vst4.8 { d3, d4, d5, d6 }, [%[DST],:64] !\n\t" + : [DST]"+r" (dst), [SRC]"+r" (src) + : "w"(fullVector) + : "memory", "d4", "d5", "d6" + ); +#else + asm volatile ( + "vld3.8 { d0, d1, d2 }, [%[SRC]] !\n\t" + "vswp d0, d2\n\t" + "vst4.8 { d0, d1, d2, d3 }, [%[DST],:64] !\n\t" + : [DST]"+r" (dst), [SRC]"+r" (src) + : "w"(fullVector) + : "memory", "d0", "d1", "d2" + ); +#endif + } while (dst < simdEnd); + } + + while (dst != end) { + *dst++ = qRgb(src[0], src[1], src[2]); + src += 3; + } +} + +void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + Q_ASSERT(src->format == QImage::Format_RGB888); + Q_ASSERT(dest->format == QImage::Format_RGB32 || dest->format == QImage::Format_ARGB32 || dest->format == QImage::Format_ARGB32_Premultiplied); + Q_ASSERT(src->width == dest->width); + Q_ASSERT(src->height == dest->height); + + const uchar *src_data = (uchar *) src->data; + quint32 *dest_data = (quint32 *) dest->data; + + for (int i = 0; i < src->height; ++i) { + qt_convert_rgb888_to_rgb32_neon(dest_data, src_data, src->width); + src_data += src->bytes_per_line; + dest_data = (quint32 *)((uchar*)dest_data + dest->bytes_per_line); + } +} + +QT_END_NAMESPACE + +#endif // QT_HAVE_NEON diff --git a/src/gui/image/qimage_ssse3.cpp b/src/gui/image/qimage_ssse3.cpp index 1c664f236d..9aed0112f0 100644 --- a/src/gui/image/qimage_ssse3.cpp +++ b/src/gui/image/qimage_ssse3.cpp @@ -45,13 +45,12 @@ #ifdef QT_HAVE_SSSE3 -#include <stdio.h> QT_BEGIN_NAMESPACE // Convert a scanline of RGB888 (src) to RGB32 (dst) // src must be at least len * 3 bytes // dst must be at least len * 4 bytes -inline void convert_rgb888_to_rgb32_ssse3(quint32 *dst, const uchar *src, int len) +Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_ssse3(quint32 *dst, const uchar *src, int len) { quint32 *const end = dst + len; @@ -139,7 +138,7 @@ void convert_RGB888_to_RGB32_ssse3(QImageData *dest, const QImageData *src, Qt:: quint32 *dest_data = (quint32 *) dest->data; for (int i = 0; i < src->height; ++i) { - convert_rgb888_to_rgb32_ssse3(dest_data, src_data, src->width); + qt_convert_rgb888_to_rgb32_ssse3(dest_data, src_data, src->width); src_data += src->bytes_per_line; dest_data = (quint32 *)((uchar*)dest_data + dest->bytes_per_line); } diff --git a/src/gui/image/qjpeghandler.cpp b/src/gui/image/qjpeghandler.cpp index 972dd65744..eda5efb9a1 100644 --- a/src/gui/image/qjpeghandler.cpp +++ b/src/gui/image/qjpeghandler.cpp @@ -45,6 +45,7 @@ #include <qvariant.h> #include <qvector.h> #include <qbuffer.h> +#include <private/qsimd_p.h> #include <stdio.h> // jpeglib needs this to be pre-included #include <setjmp.h> @@ -75,6 +76,19 @@ extern "C" { QT_BEGIN_NAMESPACE +void QT_FASTCALL convert_rgb888_to_rgb32_C(quint32 *dst, const uchar *src, int len) +{ + // Expand 24->32 bpp. + for (int i = 0; i < len; ++i) { + *dst++ = qRgb(src[0], src[1], src[2]); + src += 3; + } +} + +typedef void (QT_FASTCALL *Rgb888ToRgb32Converter)(quint32 *dst, const uchar *src, int len); + +static Rgb888ToRgb32Converter rgb888ToRgb32ConverterPtr = convert_rgb888_to_rgb32_C; + struct my_error_mgr : public jpeg_error_mgr { jmp_buf setjmp_buffer; }; @@ -393,13 +407,9 @@ static bool read_jpeg_image(QImage *outImage, continue; // Haven't reached the starting line yet. if (info->output_components == 3) { - // Expand 24->32 bpp. uchar *in = rows[0] + clip.x() * 3; QRgb *out = (QRgb*)outImage->scanLine(y); - for (int i = 0; i < clip.width(); ++i) { - *out++ = qRgb(in[0], in[1], in[2]); - in += 3; - } + rgb888ToRgb32ConverterPtr(out, in, clip.width()); } else if (info->out_color_space == JCS_CMYK) { // Convert CMYK->RGB. uchar *in = rows[0] + clip.x() * 4; @@ -793,6 +803,22 @@ bool QJpegHandlerPrivate::read(QImage *image) QJpegHandler::QJpegHandler() : d(new QJpegHandlerPrivate(this)) { + const uint features = qDetectCPUFeatures(); + Q_UNUSED(features); +#if defined(QT_HAVE_NEON) + // from qimage_neon.cpp + Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_neon(quint32 *dst, const uchar *src, int len); + + if (features & NEON) + rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_neon; +#endif // QT_HAVE_NEON +#if defined(QT_HAVE_SSSE3) + // from qimage_ssse3.cpp + Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_ssse3(quint32 *dst, const uchar *src, int len); + + if (features & SSSE3) + rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_ssse3; +#endif // QT_HAVE_SSSE3 } QJpegHandler::~QJpegHandler() diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index 2cf8222de5..dc5431367c 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -389,7 +389,7 @@ bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngHeader() while (num_text--) { QString key, value; -#if defined(PNG_iTXt_SUPPORTED) +#if defined(PNG_iTXt_SUPPORTED) && !defined(QT_NO_TEXTCODEC) if (text_ptr->lang) { QTextCodec *codec = QTextCodec::codecForName(text_ptr->lang); if (codec) { diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index 394d3748f3..c4d60a526b 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -364,10 +364,10 @@ void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints) commitTemporaryPreeditString(); - bool numbersOnly = hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly - || hints & ImhDialableCharactersOnly; - bool noOnlys = !(numbersOnly || hints & ImhUppercaseOnly - || hints & ImhLowercaseOnly); + const bool anynumbermodes = hints & (ImhDigitsOnly | ImhFormattedNumbersOnly | ImhDialableCharactersOnly); + const bool anytextmodes = hints & (ImhUppercaseOnly | ImhLowercaseOnly | ImhEmailCharactersOnly | ImhUrlCharactersOnly); + const bool numbersOnly = anynumbermodes && !anytextmodes; + const bool noOnlys = !(hints & ImhExclusiveInputMask); TInt flags; Qt::InputMethodHints oldHints = hints; @@ -379,8 +379,7 @@ void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints) } if (!noOnlys) { // Make sure that the preference is within the permitted set. - if (hints & ImhPreferNumbers && !(hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly - || hints & ImhDialableCharactersOnly)) { + if (hints & ImhPreferNumbers && !anynumbermodes) { hints &= ~ImhPreferNumbers; } else if (hints & ImhPreferUppercase && !(hints & ImhUppercaseOnly)) { hints &= ~ImhPreferUppercase; @@ -393,8 +392,7 @@ void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints) hints |= ImhPreferLowercase; } else if (hints & ImhUppercaseOnly) { hints |= ImhPreferUppercase; - } else if (hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly - || hints & ImhDialableCharactersOnly) { + } else if (numbersOnly) { hints |= ImhPreferNumbers; } } @@ -408,13 +406,21 @@ void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints) m_fepState->SetCurrentInputMode(EAknEditorTextInputMode); } flags = 0; - if (numbersOnly) { + if (noOnlys || (anynumbermodes && anytextmodes)) { + flags = EAknEditorAllInputModes; + } + else if (anynumbermodes) { flags |= EAknEditorNumericInputMode; + if (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0 + && ((hints & ImhFormattedNumbersOnly) || (hints & ImhDialableCharactersOnly))) { + //workaround - the * key does not launch the symbols menu, making it impossible to use these modes unless text mode is enabled. + flags |= EAknEditorTextInputMode; + } } - if (hints & ImhUppercaseOnly || hints & ImhLowercaseOnly) { + else if (anytextmodes) { flags |= EAknEditorTextInputMode; } - if (flags == 0) { + else { flags = EAknEditorAllInputModes; } m_fepState->SetPermittedInputModes(flags); @@ -461,24 +467,33 @@ void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints) if (hints & ImhNoPredictiveText || hints & ImhHiddenText) { flags |= EAknEditorFlagNoT9; } + // if alphanumeric input, or if multiple incompatible number modes are selected; + // then make all symbols available in numeric mode too. + if (!numbersOnly || ((hints & ImhFormattedNumbersOnly) && (hints & ImhDialableCharactersOnly))) + flags |= EAknEditorFlagUseSCTNumericCharmap; m_fepState->SetFlags(flags); ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateFlagsUpdate); - if (hints & ImhFormattedNumbersOnly) { + if (hints & ImhDialableCharactersOnly) { + // This is first, because if (ImhDialableCharactersOnly | ImhFormattedNumbersOnly) + // is specified, this one is more natural (# key enters a #) + flags = EAknEditorStandardNumberModeKeymap; + } else if (hints & ImhFormattedNumbersOnly) { + // # key enters decimal point flags = EAknEditorCalculatorNumberModeKeymap; } else if (hints & ImhDigitsOnly) { + // This is last, because it is most restrictive (# key is inactive) flags = EAknEditorPlainNumberModeKeymap; } else { - // ImhDialableCharactersOnly is the fallback as well, so we don't need to check for - // that flag. flags = EAknEditorStandardNumberModeKeymap; } m_fepState->SetNumericKeymap(static_cast<TAknEditorNumericKeymap>(flags)); - if (hints & ImhEmailCharactersOnly) { - m_fepState->SetSpecialCharacterTableResourceId(R_AVKON_EMAIL_ADDR_SPECIAL_CHARACTER_TABLE_DIALOG); - } else if (hints & ImhUrlCharactersOnly) { + if (hints & ImhUrlCharactersOnly) { + // URL characters is everything except space, so a superset of the other restrictions m_fepState->SetSpecialCharacterTableResourceId(R_AVKON_URL_SPECIAL_CHARACTER_TABLE_DIALOG); + } else if (hints & ImhEmailCharactersOnly) { + m_fepState->SetSpecialCharacterTableResourceId(R_AVKON_EMAIL_ADDR_SPECIAL_CHARACTER_TABLE_DIALOG); } else { m_fepState->SetSpecialCharacterTableResourceId(R_AVKON_SPECIAL_CHARACTER_TABLE_DIALOG); } diff --git a/src/gui/inputmethod/qinputcontextfactory.cpp b/src/gui/inputmethod/qinputcontextfactory.cpp index ec8d8e2502..865c1b2440 100644 --- a/src/gui/inputmethod/qinputcontextfactory.cpp +++ b/src/gui/inputmethod/qinputcontextfactory.cpp @@ -73,7 +73,7 @@ #endif #ifdef Q_WS_S60 #include "qcoefepinputcontext_p.h" -#include "akninputlanguageinfo.h" +#include "AknInputLanguageInfo.h" #endif #include "private/qfactoryloader_p.h" diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index 5e70a6acc5..ce1f0e53e7 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -2855,7 +2855,10 @@ QPoint QIconModeViewBase::initDynamicLayout(const QListViewLayoutInfo &info) y = info.bounds.y() + info.spacing; items.reserve(rowCount() - hiddenCount()); } else { - const QListViewItem item = items.at(info.first - 1); + int idx = info.first - 1; + while (idx > 0 && !items.at(idx).isValid()) + --idx; + const QListViewItem &item = items.at(idx); x = item.x; y = item.y; if (info.flow == QListView::LeftToRight) @@ -2986,6 +2989,8 @@ void QIconModeViewBase::doDynamicLayout(const QListViewLayoutInfo &info) else contentsSize.rwidth() += info.spacing; } + if (rect.size().isEmpty()) + return; // resize tree int insertFrom = info.first; if (done || info.first == 0) { diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp index f9b6b94868..953a7f1774 100644 --- a/src/gui/itemviews/qsortfilterproxymodel.cpp +++ b/src/gui/itemviews/qsortfilterproxymodel.cpp @@ -774,7 +774,7 @@ void QSortFilterProxyModelPrivate::source_items_inserted( if (model->rowCount(source_parent) == delta_item_count) { // Items were inserted where there were none before. // If it was new rows make sure to create mappings for columns so that a - // valid mapping can be retreived later and vice-versa. + // valid mapping can be retrieved later and vice-versa. QVector<int> &orthogonal_proxy_to_source = (orient == Qt::Horizontal) ? m->source_rows : m->source_columns; QVector<int> &orthogonal_source_to_proxy = (orient == Qt::Horizontal) ? m->proxy_rows : m->proxy_columns; diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index cdcdfe2c10..028e3aaba7 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -472,7 +472,7 @@ int qt_antialiasing_threshold = -1; static int drag_time = 500; #ifdef Q_OS_SYMBIAN // The screens are a bit too small to for your thumb when using only 4 pixels drag distance. -static int drag_distance = 8; +static int drag_distance = 12; #else static int drag_distance = 4; #endif @@ -2538,6 +2538,13 @@ void QApplication::setActiveWindow(QWidget* act) sendSpontaneousEvent(w, &activationChange); } +#ifdef QT_MAC_USE_COCOA + // In case the user clicked on a child window, we need to + // reestablish the stacking order of the window so + // it pops in front of other child windows in cocoa: + qt_cocoaStackChildWindowOnTopOfOtherChildren(window); +#endif + for(int i = 0; i < toBeDeactivated.size(); ++i) { QWidget *w = toBeDeactivated.at(i); sendSpontaneousEvent(w, &windowDeactivate); diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h index 404059e448..a790c6944d 100644 --- a/src/gui/kernel/qapplication.h +++ b/src/gui/kernel/qapplication.h @@ -412,6 +412,9 @@ private: #if defined(QT_RX71_MULTITOUCH) Q_PRIVATE_SLOT(d_func(), void _q_readRX71MultiTouchEvents()) #endif +#if defined(Q_OS_SYMBIAN) + Q_PRIVATE_SLOT(d_func(), void _q_aboutToQuit()) +#endif }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 97ceea9d60..5f200c0763 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -517,6 +517,7 @@ public: int symbianHandleCommand(const QSymbianEvent *symbianEvent); int symbianResourceChange(const QSymbianEvent *symbianEvent); + void _q_aboutToQuit(); #endif #if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) void sendSyntheticEnterLeave(QWidget *widget); @@ -601,7 +602,7 @@ private: #endif #ifdef Q_OS_SYMBIAN - static QHash<TInt, TUint> scanCodeCache; + QHash<TInt, TUint> scanCodeCache; #endif static QApplicationPrivate *self; diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index c51329a2bf..4ed00f8cec 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -87,6 +87,10 @@ #include <hal.h> #include <hal_data.h> +#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS +#include <graphics/wstfxconst.h> +#endif + QT_BEGIN_NAMESPACE // Goom Events through Window Server @@ -112,6 +116,25 @@ QS60Data* qGlobalS60Data() return qt_s60Data(); } +#ifdef Q_WS_S60 +void QS60Data::setStatusPaneAndButtonGroupVisibility(bool statusPaneVisible, bool buttonGroupVisible) +{ + bool buttonGroupVisibilityChanged = false; + if (CEikButtonGroupContainer *const b = buttonGroupContainer()) { + buttonGroupVisibilityChanged = (b->IsVisible() != buttonGroupVisible); + b->MakeVisible(buttonGroupVisible); + } + bool statusPaneVisibilityChanged = false; + if (CEikStatusPane *const s = statusPane()) { + statusPaneVisibilityChanged = (s->IsVisible() != statusPaneVisible); + s->MakeVisible(statusPaneVisible); + } + if (buttonGroupVisibilityChanged && !statusPaneVisibilityChanged) + // Ensure that control rectangle is updated + static_cast<QSymbianControl *>(QApplication::activeWindow()->winId())->handleClientAreaChange(); +} +#endif + bool qt_nograb() // application no-grab option { #if defined(QT_DEBUG) @@ -207,8 +230,6 @@ void QS60Beep::MatoPlayComplete(TInt aError) } -QHash<TInt, TUint> QApplicationPrivate::scanCodeCache; - static Qt::KeyboardModifiers mapToQtModifiers(TUint s60Modifiers) { Qt::KeyboardModifiers result = Qt::NoModifier; @@ -355,7 +376,7 @@ void QSymbianControl::ConstructL(bool isWindowOwning, bool desktop) { if (!desktop) { - if (isWindowOwning or !qwidget->parentWidget()) + if (isWindowOwning || !qwidget->parentWidget()) CreateWindowL(S60->windowGroup()); else /** @@ -378,6 +399,34 @@ void QSymbianControl::ConstructL(bool isWindowOwning, bool desktop) DrawableWindow()->SetPointerGrab(ETrue); } + +#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS + if (OwnsWindow()) { + TTfxWindowPurpose windowPurpose(ETfxPurposeNone); + switch (qwidget->windowType()) { + case Qt::Dialog: + windowPurpose = ETfxPurposeDialogWindow; + break; + case Qt::Popup: + windowPurpose = ETfxPurposePopupWindow; + break; + case Qt::Tool: + windowPurpose = ETfxPurposeToolWindow; + break; + case Qt::ToolTip: + windowPurpose = ETfxPurposeToolTipWindow; + break; + case Qt::SplashScreen: + windowPurpose = ETfxPurposeSplashScreenWindow; + break; + default: + windowPurpose = (isWindowOwning || !qwidget->parentWidget()) + ? ETfxPurposeWindow : ETfxPurposeChildWindow; + break; + } + Window().SetPurpose(windowPurpose); + } +#endif } QSymbianControl::~QSymbianControl() @@ -625,251 +674,302 @@ TKeyResponse QSymbianControl::OfferKeyEventL(const TKeyEvent& keyEvent, TEventCo TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCode type) { - switch (type) { - //case EEventKeyDown: // <-- Intentionally left out. See below. - case EEventKeyUp: - case EEventKey: - { + /* + S60 has a confusing way of delivering key events. There are three types of + events: EEventKey, EEventKeyDown and EEventKeyUp. When a key is pressed, + EEventKeyDown is first generated, followed by EEventKey. Then, when the key is + released, EEventKeyUp is generated. + However, it is possible that only the EEventKey is generated alone, typically + in relation to virtual keyboards. In that case we need to take care to + generate both press and release events in Qt, since applications expect that. + We do this by having three states for each used scan code, depending on the + events received. See the switch below for what happens in each state + transition. + */ + + if (type != EEventKeyDown) + if (handleVirtualMouse(keyEvent, type) == EKeyWasConsumed) + return EKeyWasConsumed; + + TKeyResponse ret = EKeyWasNotConsumed; +#define GET_RETURN(x) (ret = ((x) == EKeyWasConsumed) ? EKeyWasConsumed : ret) + + // This top level switch corresponds to the states, and the inner switches + // correspond to the transitions. + QS60Data::ScanCodeState &scanCodeState = S60->scanCodeStates[keyEvent.iScanCode]; + switch (scanCodeState) { + case QS60Data::Unpressed: + switch (type) { + case EEventKeyDown: + scanCodeState = QS60Data::KeyDown; + break; + case EEventKey: + GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyPress)); + GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyRelease)); + break; + case EEventKeyUp: + // No action. + break; + } + break; + case QS60Data::KeyDown: + switch (type) { + case EEventKeyDown: + // This should never happen, just stay in this state to be safe. + break; + case EEventKey: + GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyPress)); + scanCodeState = QS60Data::KeyDownAndKey; + break; + case EEventKeyUp: + scanCodeState = QS60Data::Unpressed; + break; + } + break; + case QS60Data::KeyDownAndKey: + switch (type) { + case EEventKeyDown: + // This should never happen, just stay in this state to be safe. + break; + case EEventKey: + GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyRelease)); + GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyPress)); + break; + case EEventKeyUp: + GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyRelease)); + scanCodeState = QS60Data::Unpressed; + break; + } + break; + } + return ret; + +#undef GET_RETURN +} + +TKeyResponse QSymbianControl::sendSymbianKeyEvent(const TKeyEvent &keyEvent, QEvent::Type type) +{ + // Because S60 does not generate keysyms for EKeyEventDown and EKeyEventUp + // events, we need to cache the keysyms from the EKeyEvent events. This is what + // resolveS60ScanCode does. + TUint s60Keysym = QApplicationPrivate::resolveS60ScanCode(keyEvent.iScanCode, + keyEvent.iCode); + int keyCode; + if (s60Keysym == EKeyNull){ //some key events have 0 in iCode, for them iScanCode should be used + keyCode = qt_keymapper_private()->mapS60ScanCodesToQt(keyEvent.iScanCode); + } else if (s60Keysym >= 0x20 && s60Keysym < ENonCharacterKeyBase) { + // Normal characters keys. + keyCode = s60Keysym; + } else { + // Special S60 keys. + keyCode = qt_keymapper_private()->mapS60KeyToQt(s60Keysym); + } + + Qt::KeyboardModifiers mods = mapToQtModifiers(keyEvent.iModifiers); + QKeyEventEx qKeyEvent(type, keyCode, mods, qt_keymapper_private()->translateKeyEvent(keyCode, mods), + (keyEvent.iRepeats != 0), 1, keyEvent.iScanCode, s60Keysym, keyEvent.iModifiers); + QWidget *widget; + widget = QWidget::keyboardGrabber(); + if (!widget) { + if (QApplicationPrivate::popupWidgets != 0) { + widget = QApplication::activePopupWidget()->focusWidget(); + if (!widget) { + widget = QApplication::activePopupWidget(); + } + } else { + widget = QApplicationPrivate::focus_widget; + if (!widget) { + widget = qwidget; + } + } + } + + QEventDispatcherS60 *dispatcher; + // It is theoretically possible for someone to install a different event dispatcher. + if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(widget->d_func()->threadData->eventDispatcher)) != 0) { + if (dispatcher->excludeUserInputEvents()) { + dispatcher->saveInputEvent(this, widget, new QKeyEventEx(qKeyEvent)); + return EKeyWasConsumed; + } + } + return sendKeyEvent(widget, &qKeyEvent); +} + +TKeyResponse QSymbianControl::handleVirtualMouse(const TKeyEvent& keyEvent,TEventCode type) +{ #ifndef QT_NO_CURSOR - if (S60->mouseInteractionEnabled && S60->virtualMouseRequired) { - //translate keys to pointer - if ((keyEvent.iScanCode >= EStdKeyLeftArrow && keyEvent.iScanCode <= EStdKeyDownArrow) || + if (S60->mouseInteractionEnabled && S60->virtualMouseRequired) { + //translate keys to pointer + if ((keyEvent.iScanCode >= EStdKeyLeftArrow && keyEvent.iScanCode <= EStdKeyDownArrow) || (keyEvent.iScanCode >= EStdKeyDevice10 && keyEvent.iScanCode <= EStdKeyDevice13) || keyEvent.iScanCode == EStdKeyDevice3) { - QPoint pos = QCursor::pos(); - TPointerEvent fakeEvent; - fakeEvent.iType = (TPointerEvent::TType)(-1); - fakeEvent.iModifiers = keyEvent.iModifiers; - TInt x = pos.x(); - TInt y = pos.y(); - if (type == EEventKeyUp) { - S60->virtualMouseAccelTimeout.start(); - switch (keyEvent.iScanCode) { - case EStdKeyLeftArrow: - S60->virtualMousePressedKeys &= ~QS60Data::Left; - break; - case EStdKeyRightArrow: - S60->virtualMousePressedKeys &= ~QS60Data::Right; - break; - case EStdKeyUpArrow: - S60->virtualMousePressedKeys &= ~QS60Data::Up; - break; - case EStdKeyDownArrow: - S60->virtualMousePressedKeys &= ~QS60Data::Down; - break; - // diagonal keys (named aliases don't exist in 3.1 SDK) - case EStdKeyDevice10: - S60->virtualMousePressedKeys &= ~QS60Data::LeftUp; - break; - case EStdKeyDevice11: - S60->virtualMousePressedKeys &= ~QS60Data::RightUp; - break; - case EStdKeyDevice12: - S60->virtualMousePressedKeys &= ~QS60Data::RightDown; - break; - case EStdKeyDevice13: - S60->virtualMousePressedKeys &= ~QS60Data::LeftDown; - break; - case EStdKeyDevice3: //select - if (S60->virtualMousePressedKeys & QS60Data::Select) - fakeEvent.iType = TPointerEvent::EButton1Up; - S60->virtualMousePressedKeys &= ~QS60Data::Select; - break; - } + QPoint pos = QCursor::pos(); + TPointerEvent fakeEvent; + fakeEvent.iType = (TPointerEvent::TType)(-1); + fakeEvent.iModifiers = keyEvent.iModifiers; + TInt x = pos.x(); + TInt y = pos.y(); + if (type == EEventKeyUp) { + S60->virtualMouseAccelTimeout.start(); + switch (keyEvent.iScanCode) { + case EStdKeyLeftArrow: + S60->virtualMousePressedKeys &= ~QS60Data::Left; + break; + case EStdKeyRightArrow: + S60->virtualMousePressedKeys &= ~QS60Data::Right; + break; + case EStdKeyUpArrow: + S60->virtualMousePressedKeys &= ~QS60Data::Up; + break; + case EStdKeyDownArrow: + S60->virtualMousePressedKeys &= ~QS60Data::Down; + break; + // diagonal keys (named aliases don't exist in 3.1 SDK) + case EStdKeyDevice10: + S60->virtualMousePressedKeys &= ~QS60Data::LeftUp; + break; + case EStdKeyDevice11: + S60->virtualMousePressedKeys &= ~QS60Data::RightUp; + break; + case EStdKeyDevice12: + S60->virtualMousePressedKeys &= ~QS60Data::RightDown; + break; + case EStdKeyDevice13: + S60->virtualMousePressedKeys &= ~QS60Data::LeftDown; + break; + case EStdKeyDevice3: //select + if (S60->virtualMousePressedKeys & QS60Data::Select) + fakeEvent.iType = TPointerEvent::EButton1Up; + S60->virtualMousePressedKeys &= ~QS60Data::Select; + break; } - else if (type == EEventKey) { - int dx = 0; - int dy = 0; - if (keyEvent.iScanCode != EStdKeyDevice3) { - m_doubleClickTimer.invalidate(); - //reset mouse accelleration after a short time with no moves - const int maxTimeBetweenKeyEventsMs = 500; - if (S60->virtualMouseAccelTimeout.isValid() && + } + else if (type == EEventKey) { + int dx = 0; + int dy = 0; + if (keyEvent.iScanCode != EStdKeyDevice3) { + m_doubleClickTimer.invalidate(); + //reset mouse accelleration after a short time with no moves + const int maxTimeBetweenKeyEventsMs = 500; + if (S60->virtualMouseAccelTimeout.isValid() && S60->virtualMouseAccelTimeout.hasExpired(maxTimeBetweenKeyEventsMs)) { - S60->virtualMouseAccelDX = 0; - S60->virtualMouseAccelDY = 0; - } - S60->virtualMouseAccelTimeout.invalidate(); + S60->virtualMouseAccelDX = 0; + S60->virtualMouseAccelDY = 0; } - switch (keyEvent.iScanCode) { - case EStdKeyLeftArrow: - S60->virtualMousePressedKeys |= QS60Data::Left; - dx = -1; - fakeEvent.iType = TPointerEvent::EMove; - break; - case EStdKeyRightArrow: - S60->virtualMousePressedKeys |= QS60Data::Right; - dx = 1; - fakeEvent.iType = TPointerEvent::EMove; - break; - case EStdKeyUpArrow: - S60->virtualMousePressedKeys |= QS60Data::Up; - dy = -1; - fakeEvent.iType = TPointerEvent::EMove; - break; - case EStdKeyDownArrow: - S60->virtualMousePressedKeys |= QS60Data::Down; - dy = 1; - fakeEvent.iType = TPointerEvent::EMove; - break; - case EStdKeyDevice10: - S60->virtualMousePressedKeys |= QS60Data::LeftUp; - dx = -1; - dy = -1; - fakeEvent.iType = TPointerEvent::EMove; - break; - case EStdKeyDevice11: - S60->virtualMousePressedKeys |= QS60Data::RightUp; - dx = 1; - dy = -1; - fakeEvent.iType = TPointerEvent::EMove; - break; - case EStdKeyDevice12: - S60->virtualMousePressedKeys |= QS60Data::RightDown; - dx = 1; - dy = 1; - fakeEvent.iType = TPointerEvent::EMove; - break; - case EStdKeyDevice13: - S60->virtualMousePressedKeys |= QS60Data::LeftDown; - dx = -1; - dy = 1; - fakeEvent.iType = TPointerEvent::EMove; - break; - case EStdKeyDevice3: - // Platform bug. If you start pressing several keys simultaneously (for - // example for drag'n'drop), Symbian starts producing spurious up and - // down messages for some keys. Therefore, make sure we have a clean slate - // of pressed keys before starting a new button press. - if (S60->virtualMousePressedKeys & QS60Data::Select) { - return EKeyWasConsumed; - } else { - S60->virtualMousePressedKeys |= QS60Data::Select; - fakeEvent.iType = TPointerEvent::EButton1Down; - if (m_doubleClickTimer.isValid() + S60->virtualMouseAccelTimeout.invalidate(); + } + switch (keyEvent.iScanCode) { + case EStdKeyLeftArrow: + S60->virtualMousePressedKeys |= QS60Data::Left; + dx = -1; + fakeEvent.iType = TPointerEvent::EMove; + break; + case EStdKeyRightArrow: + S60->virtualMousePressedKeys |= QS60Data::Right; + dx = 1; + fakeEvent.iType = TPointerEvent::EMove; + break; + case EStdKeyUpArrow: + S60->virtualMousePressedKeys |= QS60Data::Up; + dy = -1; + fakeEvent.iType = TPointerEvent::EMove; + break; + case EStdKeyDownArrow: + S60->virtualMousePressedKeys |= QS60Data::Down; + dy = 1; + fakeEvent.iType = TPointerEvent::EMove; + break; + case EStdKeyDevice10: + S60->virtualMousePressedKeys |= QS60Data::LeftUp; + dx = -1; + dy = -1; + fakeEvent.iType = TPointerEvent::EMove; + break; + case EStdKeyDevice11: + S60->virtualMousePressedKeys |= QS60Data::RightUp; + dx = 1; + dy = -1; + fakeEvent.iType = TPointerEvent::EMove; + break; + case EStdKeyDevice12: + S60->virtualMousePressedKeys |= QS60Data::RightDown; + dx = 1; + dy = 1; + fakeEvent.iType = TPointerEvent::EMove; + break; + case EStdKeyDevice13: + S60->virtualMousePressedKeys |= QS60Data::LeftDown; + dx = -1; + dy = 1; + fakeEvent.iType = TPointerEvent::EMove; + break; + case EStdKeyDevice3: + // Platform bug. If you start pressing several keys simultaneously (for + // example for drag'n'drop), Symbian starts producing spurious up and + // down messages for some keys. Therefore, make sure we have a clean slate + // of pressed keys before starting a new button press. + if (S60->virtualMousePressedKeys & QS60Data::Select) { + return EKeyWasConsumed; + } else { + S60->virtualMousePressedKeys |= QS60Data::Select; + fakeEvent.iType = TPointerEvent::EButton1Down; + if (m_doubleClickTimer.isValid() && !m_doubleClickTimer.hasExpired(QApplication::doubleClickInterval())) { - fakeEvent.iModifiers |= EModifierDoubleClick; - m_doubleClickTimer.invalidate(); - } else { - m_doubleClickTimer.start(); - } + fakeEvent.iModifiers |= EModifierDoubleClick; + m_doubleClickTimer.invalidate(); + } else { + m_doubleClickTimer.start(); } - break; } - if (dx) { - int cdx = S60->virtualMouseAccelDX; - //reset accel on change of sign, else double accel - if (dx * cdx <= 0) - cdx = dx; - else - cdx *= 4; - //cap accelleration - if (dx * cdx > S60->virtualMouseMaxAccel) - cdx = dx * S60->virtualMouseMaxAccel; - //move mouse position - x += cdx; - S60->virtualMouseAccelDX = cdx; - } - - if (dy) { - int cdy = S60->virtualMouseAccelDY; - if (dy * cdy <= 0) - cdy = dy; - else - cdy *= 4; - if (dy * cdy > S60->virtualMouseMaxAccel) - cdy = dy * S60->virtualMouseMaxAccel; - y += cdy; - S60->virtualMouseAccelDY = cdy; - } - } - //clip to screen size (window server allows a sprite hotspot to be outside the screen) - if (x < 0) - x = 0; - else if (x >= S60->screenWidthInPixels) - x = S60->screenWidthInPixels - 1; - if (y < 0) - y = 0; - else if (y >= S60->screenHeightInPixels) - y = S60->screenHeightInPixels - 1; - TPoint epos(x, y); - TPoint cpos = epos - PositionRelativeToScreen(); - fakeEvent.iPosition = cpos; - fakeEvent.iParentPosition = epos; - if(fakeEvent.iType != -1) - HandlePointerEvent(fakeEvent); - return EKeyWasConsumed; - } - } -#endif - // S60 has a confusing way of delivering key events. There are three types of - // events: EKeyEvent, EKeyEventDown and EKeyEventUp. When a key is pressed, the - // two first events are generated. When releasing the key, the last one is - // generated. - // Because S60 does not generate keysyms for EKeyEventDown and EKeyEventUp events, - // we need to do some special tricks to map it to the Qt way. First, we completely - // discard EKeyEventDown events, since they are redundant. Second, since - // EKeyEventUp does not give us a keysym, we need to cache the keysyms from - // the EKeyEvent events. This is what resolveS60ScanCode does. - - - // ### hackish way to send Qt application to background when pressing right softkey - /* - if( keyEvent.iScanCode == EStdKeyDevice1 ) { - S60->window_group->SetOrdinalPosition(-1); - qApp->setActiveWindow(0); - return EKeyWasNotConsumed; - } - */ - - TUint s60Keysym = QApplicationPrivate::resolveS60ScanCode(keyEvent.iScanCode, - keyEvent.iCode); - int keyCode; - if (s60Keysym == EKeyNull){ //some key events have 0 in iCode, for them iScanCode should be used - keyCode = qt_keymapper_private()->mapS60ScanCodesToQt(keyEvent.iScanCode); - } else if (s60Keysym >= 0x20 && s60Keysym < ENonCharacterKeyBase) { - // Normal characters keys. - keyCode = s60Keysym; - } else { - // Special S60 keys. - keyCode = qt_keymapper_private()->mapS60KeyToQt(s60Keysym); - } - - Qt::KeyboardModifiers mods = mapToQtModifiers(keyEvent.iModifiers); - QKeyEventEx qKeyEvent(type == EEventKeyUp ? QEvent::KeyRelease : QEvent::KeyPress, keyCode, - mods, qt_keymapper_private()->translateKeyEvent(keyCode, mods), - (keyEvent.iRepeats != 0), 1, keyEvent.iScanCode, s60Keysym, keyEvent.iModifiers); -// WId wid = reinterpret_cast<RWindowGroup *>(keyEvent.Handle())->Child(); -// if (!wid) -// Could happen if window isn't shown yet. -// return EKeyWasNotConsumed; - QWidget *widget; - widget = QWidget::keyboardGrabber(); - if (!widget) { - if (QApplicationPrivate::popupWidgets != 0) { - widget = QApplication::activePopupWidget()->focusWidget(); - if (!widget) { - widget = QApplication::activePopupWidget(); + break; } - } else { - widget = QApplicationPrivate::focus_widget; - if (!widget) { - widget = qwidget; + if (dx) { + int cdx = S60->virtualMouseAccelDX; + //reset accel on change of sign, else double accel + if (dx * cdx <= 0) + cdx = dx; + else + cdx *= 4; + //cap accelleration + if (dx * cdx > S60->virtualMouseMaxAccel) + cdx = dx * S60->virtualMouseMaxAccel; + //move mouse position + x += cdx; + S60->virtualMouseAccelDX = cdx; } - } - } - QEventDispatcherS60 *dispatcher; - // It is theoretically possible for someone to install a different event dispatcher. - if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(widget->d_func()->threadData->eventDispatcher)) != 0) { - if (dispatcher->excludeUserInputEvents()) { - dispatcher->saveInputEvent(this, widget, new QKeyEventEx(qKeyEvent)); - return EKeyWasConsumed; + if (dy) { + int cdy = S60->virtualMouseAccelDY; + if (dy * cdy <= 0) + cdy = dy; + else + cdy *= 4; + if (dy * cdy > S60->virtualMouseMaxAccel) + cdy = dy * S60->virtualMouseMaxAccel; + y += cdy; + S60->virtualMouseAccelDY = cdy; + } } + //clip to screen size (window server allows a sprite hotspot to be outside the screen) + if (x < 0) + x = 0; + else if (x >= S60->screenWidthInPixels) + x = S60->screenWidthInPixels - 1; + if (y < 0) + y = 0; + else if (y >= S60->screenHeightInPixels) + y = S60->screenHeightInPixels - 1; + TPoint epos(x, y); + TPoint cpos = epos - PositionRelativeToScreen(); + fakeEvent.iPosition = cpos; + fakeEvent.iParentPosition = epos; + if(fakeEvent.iType != -1) + HandlePointerEvent(fakeEvent); + return EKeyWasConsumed; } - return sendKeyEvent(widget, &qKeyEvent); - } } +#endif + return EKeyWasNotConsumed; } @@ -967,7 +1067,7 @@ void QSymbianControl::Draw(const TRect& controlRect) const if (QApplicationPrivate::runtime_graphics_system) { QRuntimeWindowSurface *rtSurface = static_cast<QRuntimeWindowSurface*>(qwidget->windowSurface()); - s60Surface = static_cast<QS60WindowSurface *>(rtSurface->m_windowSurface); + s60Surface = static_cast<QS60WindowSurface *>(rtSurface->m_windowSurface.data()); } else #endif s60Surface = static_cast<QS60WindowSurface *>(qwidget->windowSurface()); @@ -987,7 +1087,8 @@ void QSymbianControl::Draw(const TRect& controlRect) const break; case QWExtra::ZeroFill: - if (Window().DisplayMode() == EColor16MA) { + if (Window().DisplayMode() == EColor16MA + || Window().DisplayMode() == Q_SYMBIAN_ECOLOR16MAP) { gc.SetBrushStyle(CGraphicsContext::ESolidBrush); gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha); gc.SetBrushColor(TRgb::Color16MA(0)); @@ -1100,17 +1201,12 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle()); #ifdef Q_WS_S60 // If widget is fullscreen/minimized, hide status pane and button container otherwise show them. - CEikStatusPane *statusPane = S60->statusPane(); - CEikButtonGroupContainer *buttonGroup = S60->buttonGroupContainer(); - TBool visible = !(qwidget->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized)); - if (statusPane) - statusPane->MakeVisible(visible); - if (buttonGroup) { - // Visibility - const TBool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen; - const TBool cbaVisibilityHint = qwidget->windowFlags() & Qt::WindowSoftkeysVisibleHint; - buttonGroup->MakeVisible(visible || (isFullscreen && cbaVisibilityHint)); - } + const bool visible = !(qwidget->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized)); + const bool statusPaneVisibility = visible; + const bool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen; + const bool cbaVisibilityHint = qwidget->windowFlags() & Qt::WindowSoftkeysVisibleHint; + const bool buttonGroupVisibility = (visible || (isFullscreen && cbaVisibilityHint)); + S60->setStatusPaneAndButtonGroupVisibility(statusPaneVisibility, buttonGroupVisibility); #endif } else if (QApplication::activeWindow() == qwidget->window()) { if (CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog() || S60->menuBeingConstructed) { @@ -1265,7 +1361,7 @@ void qt_init(QApplicationPrivate * /* priv */, int) // framework destruction. TTrapHandler *origTrapHandler = User::TrapHandler(); - // The S60 framework has not been initalized. We need to do it. + // The S60 framework has not been initialized. We need to do it. TApaApplicationFactory factory(S60->s60ApplicationFactory ? S60->s60ApplicationFactory : newS60Application); CApaCommandLine* commandLine = 0; @@ -1420,6 +1516,10 @@ void qt_init(QApplicationPrivate * /* priv */, int) systemFont.setFamily(systemFont.defaultFamily()); QApplicationPrivate::setSystemFont(systemFont); +#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS + QObject::connect(qApp, SIGNAL(aboutToQuit()), qApp, SLOT(_q_aboutToQuit())); +#endif + /* ### Commented out for now as parameter handling not needed in SOS(yet). Code below will break testlib with -o flag int argc = priv->argc; @@ -1443,7 +1543,7 @@ void qt_init(QApplicationPrivate * /* priv */, int) */ // Register WId with the metatype system. This is to enable - // QWidgetPrivate::create_sys to used delayed slot invokation in order + // QWidgetPrivate::create_sys to used delayed slot invocation in order // to destroy WId objects during reparenting. qRegisterMetaType<WId>("WId"); } @@ -1509,6 +1609,9 @@ bool QApplicationPrivate::modalState() void QApplicationPrivate::enterModal_sys(QWidget *widget) { +#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS + S60->wsSession().SendEffectCommand(ETfxCmdAppModalModeEnter); +#endif if (widget) { static_cast<QSymbianControl *>(widget->effectiveWinId())->FadeBehindPopup(ETrue); // Modal partial screen dialogs (like queries) capture pointer events. @@ -1524,6 +1627,9 @@ void QApplicationPrivate::enterModal_sys(QWidget *widget) void QApplicationPrivate::leaveModal_sys(QWidget *widget) { +#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS + S60->wsSession().SendEffectCommand(ETfxCmdAppModalModeExit); +#endif if (widget) { static_cast<QSymbianControl *>(widget->effectiveWinId())->FadeBehindPopup(EFalse); // ### FixMe: Add specialized behaviour for fullscreen modal dialogs @@ -1820,6 +1926,9 @@ int QApplicationPrivate::symbianProcessWsEvent(const QSymbianEvent *symbianEvent break; QRefCountedWidgetBackingStore &backingStore = window->d_func()->maybeTopData()->backingStore; if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::ENotVisible) { +#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS + S60->wsSession().SendEffectCommand(ETfxCmdDeallocateLayer); +#endif // Decrement backing store reference count backingStore.deref(); // In order to ensure that any resources used by the window surface @@ -1830,6 +1939,9 @@ int QApplicationPrivate::symbianProcessWsEvent(const QSymbianEvent *symbianEvent // Increment backing store reference count backingStore.ref(); } else { +#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS + S60->wsSession().SendEffectCommand(ETfxCmdRestoreLayer); +#endif // Create backing store with an initial reference count of 1 backingStore.create(window); backingStore.ref(); @@ -1890,13 +2002,6 @@ int QApplicationPrivate::symbianProcessWsEvent(const QSymbianEvent *symbianEvent if (switchToSwRendering) { QRuntimeGraphicsSystem *gs = static_cast<QRuntimeGraphicsSystem*>(QApplicationPrivate::graphics_system); - - uint memoryUsage = gs->memoryUsage(); - uint memoryForFullscreen = ( S60->screenDepth / 8 ) - * S60->screenWidthInPixels - * S60->screenHeightInPixels; - - S60->memoryLimitForHwRendering = memoryUsage - memoryForFullscreen; gs->setGraphicsSystem(QLatin1String("raster")); } } @@ -1912,8 +2017,7 @@ int QApplicationPrivate::symbianProcessWsEvent(const QSymbianEvent *symbianEvent if(QApplicationPrivate::runtime_graphics_system) { QRuntimeGraphicsSystem *gs = static_cast<QRuntimeGraphicsSystem*>(QApplicationPrivate::graphics_system); - gs->setGraphicsSystem(QLatin1String("openvg"), S60->memoryLimitForHwRendering); - S60->memoryLimitForHwRendering = 0; + gs->setGraphicsSystem(QLatin1String("openvg")); } #endif break; @@ -2082,13 +2186,18 @@ void QApplication::setEffectEnabled(Qt::UIEffect /* effect */, bool /* enable */ TUint QApplicationPrivate::resolveS60ScanCode(TInt scanCode, TUint keysym) { + if (!scanCode) + return keysym; + + QApplicationPrivate *d = QApplicationPrivate::instance(); + if (keysym) { // If keysym is specified, cache it. - scanCodeCache.insert(scanCode, keysym); + d->scanCodeCache.insert(scanCode, keysym); return keysym; } else { // If not, retrieve the cached version. - return scanCodeCache[scanCode]; + return d->scanCodeCache[scanCode]; } } @@ -2208,6 +2317,14 @@ void QApplication::restoreOverrideCursor() #endif // QT_NO_CURSOR +void QApplicationPrivate::_q_aboutToQuit() +{ +#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS + // Send the shutdown tfx command + S60->wsSession().SendEffectCommand(ETfxCmdAppShutDown); +#endif +} + QS60ThreadLocalData::QS60ThreadLocalData() { CCoeEnv *env = CCoeEnv::Static(); diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 628a041812..11db75b460 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -714,8 +714,10 @@ static void qt_set_windows_updateScrollBar(QWidget *widget) if (QWidget *w = static_cast<QWidget *>(o)) qt_set_windows_updateScrollBar(w); } +#ifndef QT_NO_SCROLLBAR if (qobject_cast<QScrollBar*>(widget)) widget->updateGeometry(); +#endif } @@ -1506,6 +1508,7 @@ extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wPa switch (message) { #ifndef Q_WS_WINCE +#ifndef QT_NO_SESSIONMANAGER case WM_QUERYENDSESSION: { if (sm_smActive) // bogus message from windows RETURN(true); @@ -1538,6 +1541,7 @@ extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wPa RETURN(0); } +#endif case WM_DISPLAYCHANGE: if (QApplication::type() == QApplication::Tty) break; @@ -2243,6 +2247,7 @@ extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wPa } break; +#ifndef QT_NO_CONTEXTMENU case WM_CONTEXTMENU: { // it's not VK_APPS or Shift+F10, but a click in the NC area @@ -2271,6 +2276,7 @@ extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wPa } break; #endif +#endif case WM_IME_STARTCOMPOSITION: case WM_IME_ENDCOMPOSITION: diff --git a/src/gui/kernel/qcocoawindowdelegate_mac.mm b/src/gui/kernel/qcocoawindowdelegate_mac.mm index 2b9cf8517b..ffba6c2569 100644 --- a/src/gui/kernel/qcocoawindowdelegate_mac.mm +++ b/src/gui/kernel/qcocoawindowdelegate_mac.mm @@ -394,5 +394,25 @@ static void cleanupCocoaWindowDelegate() } return NO; } + +- (void)syncContentViewFrame: (NSNotification *)notification +{ + NSView *cView = [notification object]; + if (cView) { + NSWindow *window = [cView window]; + QWidget *qwidget = m_windowHash->value(window); + if (qwidget) { + QWidgetData *widgetData = qt_qwidget_data(qwidget); + NSRect rect = [cView frame]; + const QSize newSize(rect.size.width, rect.size.height); + const QSize &oldSize = widgetData->crect.size(); + if (newSize != oldSize) { + [self syncSizeForWidget:qwidget toSize:newSize fromSize:oldSize]; + } + } + + } +} + @end #endif// QT_MAC_USE_COCOA diff --git a/src/gui/kernel/qcocoawindowdelegate_mac_p.h b/src/gui/kernel/qcocoawindowdelegate_mac_p.h index de9c946169..2ca9b13e84 100644 --- a/src/gui/kernel/qcocoawindowdelegate_mac_p.h +++ b/src/gui/kernel/qcocoawindowdelegate_mac_p.h @@ -105,5 +105,6 @@ QT_FORWARD_DECLARE_CLASS(QWidgetData) - (NSSize)closestAcceptableSizeForWidget:(QWidget *)qwidget window:(NSWindow *)window withNewSize:(NSSize)proposedSize; - (QWidget *)qt_qwidgetForWindow:(NSWindow *)window; +- (void)syncContentViewFrame: (NSNotification *)notification; @end #endif diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index fc2c995a67..d2b2098444 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -4281,6 +4281,11 @@ QTouchEvent::TouchPoint &QTouchEvent::TouchPoint::operator=(const QTouchEvent::T QGestureEvent::accept() for each of them, or an event filter consumes the event. + \section1 Further Reading + + For an overview of gesture handling in Qt and information on using gestures + in your applications, see the \l{Gestures Programming} document. + \sa QGesture, QGestureRecognizer, QWidget::grabGesture(), QGraphicsObject::grabGesture() */ diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp index 4a4452ab07..13274c4630 100644 --- a/src/gui/kernel/qgesture.cpp +++ b/src/gui/kernel/qgesture.cpp @@ -59,6 +59,9 @@ QT_BEGIN_NAMESPACE the QGestureRecognizer object that is registered with the application; see QGestureRecognizer::registerRecognizer(). + For an overview of gesture handling in Qt and information on using gestures + in your applications, see the \l{Gestures Programming} document. + \section1 Gesture Properties The class has a list of properties that can be queried by the user to get @@ -219,7 +222,10 @@ QGesture::GestureCancelPolicy QGesture::gestureCancelPolicy() const \image pangesture.png - \sa {Gestures Programming}, QPinchGesture, QSwipeGesture + For an overview of gesture handling in Qt and information on using gestures + in your applications, see the \l{Gestures Programming} document. + + \sa QPinchGesture, QSwipeGesture */ /*! @@ -314,6 +320,9 @@ void QPanGesture::setAcceleration(qreal value) them closer together or further apart to change the scale factor, zoom, or level of detail of the user interface. + For an overview of gesture handling in Qt and information on using gestures + in your applications, see the \l{Gestures Programming} document. + \image pinchgesture.png Instead of repeatedly applying the same pinching gesture, the user may @@ -322,7 +331,7 @@ void QPanGesture::setAcceleration(qreal value) will continue to be delivered to the target object, containing an instance of QPinchGesture in the Qt::GestureUpdated state. - \sa {Gestures Programming}, QPanGesture, QSwipeGesture + \sa QPanGesture, QSwipeGesture */ /*! @@ -572,7 +581,10 @@ void QPinchGesture::setRotationAngle(qreal value) \image swipegesture.png - \sa {Gestures Programming}, QPanGesture, QPinchGesture + For an overview of gesture handling in Qt and information on using gestures + in your applications, see the \l{Gestures Programming} document. + + \sa QPanGesture, QPinchGesture */ /*! @@ -667,7 +679,10 @@ void QSwipeGesture::setSwipeAngle(qreal value) \brief The QTapGesture class describes a tap gesture made by the user. \ingroup gestures - \sa {Gestures Programming}, QPanGesture, QPinchGesture + For an overview of gesture handling in Qt and information on using gestures + in your applications, see the \l{Gestures Programming} document. + + \sa QPanGesture, QPinchGesture */ /*! @@ -700,7 +715,10 @@ void QTapGesture::setPosition(const QPointF &value) gesture made by the user. \ingroup gestures - \sa {Gestures Programming}, QPanGesture, QPinchGesture + For an overview of gesture handling in Qt and information on using gestures + in your applications, see the \l{Gestures Programming} document. + + \sa QPanGesture, QPinchGesture */ /*! diff --git a/src/gui/kernel/qgesturerecognizer.cpp b/src/gui/kernel/qgesturerecognizer.cpp index 3e23bbf05f..e0e778446e 100644 --- a/src/gui/kernel/qgesturerecognizer.cpp +++ b/src/gui/kernel/qgesturerecognizer.cpp @@ -62,6 +62,9 @@ QT_BEGIN_NAMESPACE need to use this class directly. Instances will be created behind the scenes by the framework. + For an overview of gesture handling in Qt and information on using gestures + in your applications, see the \l{Gestures Programming} document. + \section1 Recognizing Gestures The process of recognizing gestures involves filtering input events sent to specific diff --git a/src/gui/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp index 38ec806327..55d57276d9 100644 --- a/src/gui/kernel/qpalette.cpp +++ b/src/gui/kernel/qpalette.cpp @@ -872,7 +872,7 @@ void QPalette::detach() \note The current ColorGroup is not taken into account when comparing palettes - \sa operator== + \sa operator==() */ /*! @@ -882,7 +882,7 @@ void QPalette::detach() \note The current ColorGroup is not taken into account when comparing palettes - \sa operator!= + \sa operator!=() */ bool QPalette::operator==(const QPalette &p) const { diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index 2eee4347b9..88ff1e6730 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -722,9 +722,11 @@ bool qt_dispatchKeyEvent(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEve unsigned int info = 0; if ([event type] == NSKeyDown) { NSString *characters = [event characters]; - unichar value = [characters characterAtIndex:0]; - qt_keymapper_private()->updateKeyMap(0, key_event, (void *)&value); - info = value; + if ([characters length]) { + unichar value = [characters characterAtIndex:0]; + qt_keymapper_private()->updateKeyMap(0, key_event, (void *)&value); + info = value; + } } // Redirect keys to alien widgets. @@ -1542,6 +1544,22 @@ void macSyncDrawingOnFirstInvocation(void * /*OSWindowRef */window) [theWindow display]; } } + +void qt_cocoaStackChildWindowOnTopOfOtherChildren(QWidget *childWidget) +{ + if (!childWidget) + return; + + QWidget *parent = childWidget->parentWidget(); + if (childWidget->isWindow() && parent) { + if ([[qt_mac_window_for(parent) childWindows] containsObject:qt_mac_window_for(childWidget)]) { + QWidgetPrivate *d = qt_widget_private(childWidget); + d->setSubWindowStacking(false); + d->setSubWindowStacking(true); + } + } +} + #endif // QT_MAC_USE_COCOA QT_END_NAMESPACE diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h index 57d2c90fc5..5c233928f4 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h +++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h @@ -148,6 +148,7 @@ void qt_cocoaChangeOverrideCursor(const QCursor &cursor); // These methods exists only for supporting unified mode. void macDrawRectOnTop(void * /*OSWindowRef */ window); void macSyncDrawingOnFirstInvocation(void * /*OSWindowRef */window); +void qt_cocoaStackChildWindowOnTopOfOtherChildren(QWidget *widget); #endif void qt_mac_menu_collapseSeparators(void * /*NSMenu */ menu, bool collapse); bool qt_dispatchKeyEvent(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEvent); diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index d8ef67d387..a18ea072ff 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -141,8 +141,15 @@ public: int supportsPremultipliedAlpha : 1; int avkonComponentsSupportTransparency : 1; int menuBeingConstructed : 1; - int memoryLimitForHwRendering; QApplication::QS60MainApplicationFactory s60ApplicationFactory; // typedef'ed pointer type + + enum ScanCodeState { + Unpressed, + KeyDown, + KeyDownAndKey + }; + QHash<TInt, ScanCodeState> scanCodeStates; + static inline void updateScreenSize(); inline RWsSession& wsSession(); static inline RWindowGroup& windowGroup(); @@ -155,6 +162,7 @@ public: static inline CAknTitlePane* titlePane(); static inline CAknContextPane* contextPane(); static inline CEikButtonGroupContainer* buttonGroupContainer(); + static void setStatusPaneAndButtonGroupVisibility(bool statusPaneVisible, bool buttonGroupVisible); #endif #ifdef Q_OS_SYMBIAN @@ -223,7 +231,9 @@ protected: private: void HandlePointerEvent(const TPointerEvent& aPointerEvent); TKeyResponse OfferKeyEvent(const TKeyEvent& aKeyEvent,TEventCode aType); + TKeyResponse sendSymbianKeyEvent(const TKeyEvent &keyEvent, QEvent::Type type); TKeyResponse sendKeyEvent(QWidget *widget, QKeyEvent *keyEvent); + TKeyResponse handleVirtualMouse(const TKeyEvent& keyEvent,TEventCode type); bool sendMouseEvent(QWidget *widget, QMouseEvent *mEvent); void sendMouseEvent( QWidget *receiver, @@ -236,6 +246,8 @@ private: #ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER void translateAdvancedPointerEvent(const TAdvancedPointerEvent *event); #endif + +public: void handleClientAreaChange(); private: @@ -278,7 +290,6 @@ inline QS60Data::QS60Data() supportsPremultipliedAlpha(0), avkonComponentsSupportTransparency(0), menuBeingConstructed(0), - memoryLimitForHwRendering(0), s60ApplicationFactory(0) #ifdef Q_OS_SYMBIAN ,s60InstalledTrapHandler(0) diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 2818d8827c..56349ad6d5 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -1113,15 +1113,10 @@ void QWidget::setWindowState(Qt::WindowStates newstate) // The window decoration visibility has to be changed before doing actual window state // change since in that order the availableGeometry will return directly the right size and // we will avoid unnecessarty redraws - CEikStatusPane *statusPane = S60->statusPane(); - CEikButtonGroupContainer *buttonGroup = S60->buttonGroupContainer(); - TBool visible = !(newstate & (Qt::WindowFullScreen | Qt::WindowMinimized)); - if (statusPane) - statusPane->MakeVisible(visible); - if (buttonGroup) { - // Visibility - buttonGroup->MakeVisible(visible || (isFullscreen && cbaRequested)); - } + const bool visible = !(newstate & (Qt::WindowFullScreen | Qt::WindowMinimized)); + const bool statusPaneVisibility = visible; + const bool buttonGroupVisibility = (visible || (isFullscreen && cbaRequested)); + S60->setStatusPaneAndButtonGroupVisibility(statusPaneVisibility, buttonGroupVisibility); #endif // Q_WS_S60 // Ensure the initial size is valid, since we store it as normalGeometry below. @@ -1133,8 +1128,10 @@ void QWidget::setWindowState(Qt::WindowStates newstate) const bool cbaVisibilityHint = windowFlags() & Qt::WindowSoftkeysVisibleHint; if (newstate & Qt::WindowFullScreen && !cbaVisibilityHint) { + setAttribute(Qt::WA_OutsideWSRange, false); window->SetExtentToWholeScreen(); } else if (newstate & Qt::WindowMaximized || ((newstate & Qt::WindowFullScreen) && cbaVisibilityHint)) { + setAttribute(Qt::WA_OutsideWSRange, false); TRect maxExtent = qt_QRect2TRect(qApp->desktop()->availableGeometry(this)); window->SetExtent(maxExtent.iTl, maxExtent.Size()); } else { @@ -1143,7 +1140,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) // accurate because it did not consider the status pane. This means that when returning // normal mode after showing the status pane, the geometry would overlap so we should // move it if it never had an explicit position. - if (!wasMoved && statusPane && visible) { + if (!wasMoved && S60->statusPane() && visible) { TPoint tl = static_cast<CEikAppUi*>(S60->appUi())->ClientRect().iTl; normalGeometry.setTopLeft(QPoint(tl.iX, tl.iY)); } diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index 91521a8479..05d9a5ff5c 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -166,7 +166,7 @@ static void qt_tablet_init() qt_tablet_widget = new QWidget(0); qt_tablet_widget->createWinId(); qt_tablet_widget->setObjectName(QLatin1String("Qt internal tablet widget")); - // We dont need this internal widget to appear in QApplication::topLevelWidgets() + // We don't need this internal widget to appear in QApplication::topLevelWidgets() if (QWidgetPrivate::allWidgets) QWidgetPrivate::allWidgets->remove(qt_tablet_widget); LOGCONTEXT lcMine; @@ -1547,7 +1547,7 @@ bool QWidgetPrivate::shouldShowMaximizeButton() { if (data.window_flags & Qt::MSWindowsFixedSizeDialogHint) return false; - // if the user explicitely asked for the maximize button, we try to add + // if the user explicitly asked for the maximize button, we try to add // it even if the window has fixed size. if (data.window_flags & Qt::CustomizeWindowHint && data.window_flags & Qt::WindowMaximizeButtonHint) diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 4023f65a7f..dfa4a48b36 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -246,23 +246,8 @@ symbian { QMAKE_CXXFLAGS.ARMCC *= -O3 } -neon:*-g++* { - DEFINES += QT_HAVE_NEON - HEADERS += painting/qdrawhelper_neon_p.h - SOURCES += painting/qdrawhelper_neon.cpp - QMAKE_CXXFLAGS *= -mfpu=neon - - DRAWHELPER_NEON_ASM_FILES = ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S - - neon_compiler.commands = $$QMAKE_CXX -c - neon_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} - neon_compiler.dependency_type = TYPE_C - neon_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} - neon_compiler.input = DRAWHELPER_NEON_ASM_FILES - neon_compiler.variable_out = OBJECTS - neon_compiler.name = compiling[neon] ${QMAKE_FILE_IN} - silent:neon_compiler.commands = @echo compiling[neon] ${QMAKE_FILE_IN} && $$neon_compiler.commands - QMAKE_EXTRA_COMPILERS += neon_compiler -} +NEON_SOURCES += painting/qdrawhelper_neon.cpp +NEON_HEADERS += painting/qdrawhelper_neon_p.h +NEON_ASM += ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S include($$PWD/../../3rdparty/zlib_dependency.pri) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index f5641a44a2..eb92d3fe8f 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -7938,8 +7938,10 @@ void qInitDrawhelperAsm() uint const_alpha); extern void QT_FASTCALL comp_func_solid_SourceOver_sse2(uint *destPixels, int length, uint color, uint const_alpha); extern void QT_FASTCALL comp_func_Plus_sse2(uint *dst, const uint *src, int length, uint const_alpha); + extern void QT_FASTCALL comp_func_Source_sse2(uint *dst, const uint *src, int length, uint const_alpha); functionForModeAsm[0] = comp_func_SourceOver_sse2; + functionForModeAsm[QPainter::CompositionMode_Source] = comp_func_Source_sse2; functionForModeAsm[QPainter::CompositionMode_Plus] = comp_func_Plus_sse2; functionForModeSolidAsm[0] = comp_func_solid_SourceOver_sse2; diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index 1a87127f38..d04c70d451 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -314,18 +314,61 @@ struct QSpanData void adjustSpanMethods(); }; +#if defined(Q_CC_RVCT) +# pragma push +# pragma arm +#endif +Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) { + uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; + t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; + t &= 0xff00ff; -Q_STATIC_INLINE_FUNCTION uint BYTE_MUL_RGB16(uint x, uint a) { - a += 1; - uint t = (((x & 0x07e0)*a) >> 8) & 0x07e0; - t |= (((x & 0xf81f)*(a>>2)) >> 6) & 0xf81f; - return t; + x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b; + x = (x + ((x >> 8) & 0xff00ff) + 0x800080); + x &= 0xff00ff00; + x |= t; + return x; } +#if defined(Q_CC_RVCT) +# pragma pop +#endif -Q_STATIC_INLINE_FUNCTION uint BYTE_MUL_RGB16_32(uint x, uint a) { - uint t = (((x & 0xf81f07e0) >> 5)*a) & 0xf81f07e0; - t |= (((x & 0x07e0f81f)*a) >> 5) & 0x07e0f81f; - return t; +#if QT_POINTER_SIZE == 8 // 64-bit versions + +Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) { + quint64 t = (((quint64(x)) | ((quint64(x)) << 24)) & 0x00ff00ff00ff00ff) * a; + t += (((quint64(y)) | ((quint64(y)) << 24)) & 0x00ff00ff00ff00ff) * b; + t >>= 8; + t &= 0x00ff00ff00ff00ff; + return (uint(t)) | (uint(t >> 24)); +} + +Q_STATIC_INLINE_FUNCTION uint BYTE_MUL(uint x, uint a) { + quint64 t = (((quint64(x)) | ((quint64(x)) << 24)) & 0x00ff00ff00ff00ff) * a; + t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080) >> 8; + t &= 0x00ff00ff00ff00ff; + return (uint(t)) | (uint(t >> 24)); +} + +Q_STATIC_INLINE_FUNCTION uint PREMUL(uint x) { + uint a = x >> 24; + quint64 t = (((quint64(x)) | ((quint64(x)) << 24)) & 0x00ff00ff00ff00ff) * a; + t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080) >> 8; + t &= 0x000000ff00ff00ff; + return (uint(t)) | (uint(t >> 24)) | (a << 24); +} + +#else // 32-bit versions + +Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) { + uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; + t >>= 8; + t &= 0xff00ff; + + x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b; + x &= 0xff00ff00; + x |= t; + return x; } #if defined(Q_CC_RVCT) @@ -359,6 +402,21 @@ Q_STATIC_INLINE_FUNCTION uint PREMUL(uint x) { x |= t | (a << 24); return x; } +#endif + + +Q_STATIC_INLINE_FUNCTION uint BYTE_MUL_RGB16(uint x, uint a) { + a += 1; + uint t = (((x & 0x07e0)*a) >> 8) & 0x07e0; + t |= (((x & 0xf81f)*(a>>2)) >> 6) & 0xf81f; + return t; +} + +Q_STATIC_INLINE_FUNCTION uint BYTE_MUL_RGB16_32(uint x, uint a) { + uint t = (((x & 0xf81f07e0) >> 5)*a) & 0xf81f07e0; + t |= (((x & 0x07e0f81f)*a) >> 5) & 0x07e0f81f; + return t; +} #define INV_PREMUL(p) \ (qAlpha(p) == 0 ? 0 : \ @@ -1847,70 +1905,6 @@ inline int qBlue565(quint16 rgb) { return (b << 3) | (b >> 2); } -#if 1 -Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) { - uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; - t >>= 8; - t &= 0xff00ff; - - x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b; - x &= 0xff00ff00; - x |= t; - return x; -} - -#if defined(Q_CC_RVCT) -# pragma push -# pragma arm -#endif -Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) { - uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; - t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; - t &= 0xff00ff; - - x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b; - x = (x + ((x >> 8) & 0xff00ff) + 0x800080); - x &= 0xff00ff00; - x |= t; - return x; -} -#if defined(Q_CC_RVCT) -# pragma pop -#endif -#else -// possible implementation for 64 bit -Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) { - ulong t = (((ulong(x)) | ((ulong(x)) << 24)) & 0x00ff00ff00ff00ff) * a; - t += (((ulong(y)) | ((ulong(y)) << 24)) & 0x00ff00ff00ff00ff) * b; - t >>= 8; - t &= 0x00ff00ff00ff00ff; - return (uint(t)) | (uint(t >> 24)); -} - -Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) { - ulong t = (((ulong(x)) | ((ulong(x)) << 24)) & 0x00ff00ff00ff00ff) * a; - t += (((ulong(y)) | ((ulong(y)) << 24)) & 0x00ff00ff00ff00ff) * b; - t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080); - t &= 0x00ff00ff00ff00ff; - return (uint(t)) | (uint(t >> 24)); -} - -Q_STATIC_INLINE_FUNCTION uint BYTE_MUL(uint x, uint a) { - ulong t = (((ulong(x)) | ((ulong(x)) << 24)) & 0x00ff00ff00ff00ff) * a; - t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080); - t &= 0x00ff00ff00ff00ff; - return (uint(t)) | (uint(t >> 24)); -} - -Q_STATIC_INLINE_FUNCTION uint PREMUL(uint x) { - uint a = x >> 24; - ulong t = (((ulong(x)) | ((ulong(x)) << 24)) & 0x00ff00ff00ff00ff) * a; - t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080); - t &= 0x00ff00ff00ff00ff; - return (uint(t)) | (uint(t >> 24)) | 0xff000000; -} -#endif - const uint qt_bayer_matrix[16][16] = { { 0x1, 0xc0, 0x30, 0xf0, 0xc, 0xcc, 0x3c, 0xfc, 0x3, 0xc3, 0x33, 0xf3, 0xf, 0xcf, 0x3f, 0xff}, diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp index e090ae5f8c..22c0384c08 100644 --- a/src/gui/painting/qdrawhelper_sse2.cpp +++ b/src/gui/painting/qdrawhelper_sse2.cpp @@ -112,9 +112,7 @@ void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl, int x = 0; // First, align dest to 16 bytes: - const int offsetToAlignOn16Bytes = (4 - ((reinterpret_cast<quintptr>(dst) >> 2) & 0x3)) & 0x3; - const int prologLength = qMin(w, offsetToAlignOn16Bytes); - for (; x < prologLength; ++x) { + ALIGNMENT_PROLOGUE_16BYTES(dst, x, w) { quint32 s = src[x]; s = BYTE_MUL(s, const_alpha); dst[x] = INTERPOLATE_PIXEL_255(src[x], const_alpha, dst[x], one_minus_const_alpha); @@ -182,12 +180,10 @@ inline int comp_func_Plus_one_pixel(uint d, const uint s) void QT_FASTCALL comp_func_Plus_sse2(uint *dst, const uint *src, int length, uint const_alpha) { int x = 0; - const int offsetToAlignOn16Bytes = (4 - ((reinterpret_cast<quintptr>(dst) >> 2) & 0x3)) & 0x3; - const int prologLength = qMin(length, offsetToAlignOn16Bytes); if (const_alpha == 255) { // 1) Prologue: align destination on 16 bytes - for (; x < prologLength; ++x) + ALIGNMENT_PROLOGUE_16BYTES(dst, x, length) dst[x] = comp_func_Plus_one_pixel(dst[x], src[x]); // 2) composition with SSE2 @@ -208,7 +204,7 @@ void QT_FASTCALL comp_func_Plus_sse2(uint *dst, const uint *src, int length, uin const __m128i oneMinusConstAlpha = _mm_set1_epi16(one_minus_const_alpha); // 1) Prologue: align destination on 16 bytes - for (; x < prologLength; ++x) + ALIGNMENT_PROLOGUE_16BYTES(dst, x, length) dst[x] = comp_func_Plus_one_pixel_const_alpha(dst[x], src[x], const_alpha, one_minus_const_alpha); const __m128i half = _mm_set1_epi16(0x80); @@ -229,6 +225,37 @@ void QT_FASTCALL comp_func_Plus_sse2(uint *dst, const uint *src, int length, uin } } +void QT_FASTCALL comp_func_Source_sse2(uint *dst, const uint *src, int length, uint const_alpha) +{ + if (const_alpha == 255) { + ::memcpy(dst, src, length * sizeof(uint)); + } else { + const int ialpha = 255 - const_alpha; + + int x = 0; + + // 1) prologue, align on 16 bytes + ALIGNMENT_PROLOGUE_16BYTES(dst, x, length) + dst[x] = INTERPOLATE_PIXEL_255(src[x], const_alpha, dst[x], ialpha); + + // 2) interpolate pixels with SSE2 + const __m128i half = _mm_set1_epi16(0x80); + const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); + const __m128i constAlphaVector = _mm_set1_epi16(const_alpha); + const __m128i oneMinusConstAlpha = _mm_set1_epi16(ialpha); + for (; x < length - 3; x += 4) { + const __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); + __m128i dstVector = _mm_load_si128((__m128i *)&dst[x]); + INTERPOLATE_PIXEL_255_SSE2(dstVector, srcVector, dstVector, constAlphaVector, oneMinusConstAlpha, colorMask, half) + _mm_store_si128((__m128i *)&dst[x], dstVector); + } + + // 3) Epilogue + for (; x < length; ++x) + dst[x] = INTERPOLATE_PIXEL_255(src[x], const_alpha, dst[x], ialpha); + } +} + void qt_memfill32_sse2(quint32 *dest, quint32 value, int count) { if (count < 7) { diff --git a/src/gui/painting/qdrawingprimitive_sse2_p.h b/src/gui/painting/qdrawingprimitive_sse2_p.h index 18355c278b..d8f6bf55e8 100644 --- a/src/gui/painting/qdrawingprimitive_sse2_p.h +++ b/src/gui/painting/qdrawingprimitive_sse2_p.h @@ -143,9 +143,7 @@ QT_BEGIN_NAMESPACE int x = 0; \ \ /* First, get dst aligned. */ \ - const int offsetToAlignOn16Bytes = (4 - ((reinterpret_cast<quintptr>(dst) >> 2) & 0x3)) & 0x3;\ - const int prologLength = qMin(length, offsetToAlignOn16Bytes);\ - for (; x < prologLength; ++x) { \ + ALIGNMENT_PROLOGUE_16BYTES(dst, x, length) { \ uint s = src[x]; \ if (s >= 0xff000000) \ dst[x] = s; \ @@ -202,9 +200,7 @@ QT_BEGIN_NAMESPACE { \ int x = 0; \ \ - const int offsetToAlignOn16Bytes = (4 - ((reinterpret_cast<quintptr>(dst) >> 2) & 0x3)) & 0x3;\ - const int prologLength = qMin(length, offsetToAlignOn16Bytes);\ - for (; x < prologLength; ++x) { \ + ALIGNMENT_PROLOGUE_16BYTES(dst, x, length) { \ quint32 s = src[x]; \ if (s != 0) { \ s = BYTE_MUL(s, const_alpha); \ diff --git a/src/gui/painting/qgraphicssystem_runtime.cpp b/src/gui/painting/qgraphicssystem_runtime.cpp index 34381378cb..2828e9db61 100644 --- a/src/gui/painting/qgraphicssystem_runtime.cpp +++ b/src/gui/painting/qgraphicssystem_runtime.cpp @@ -53,10 +53,8 @@ QT_BEGIN_NAMESPACE static int qt_pixmap_serial = 0; #define READBACK(f) \ - m_graphicsSystem->decreaseMemoryUsage(memoryUsage()); \ f \ - readBackInfo(); \ - m_graphicsSystem->increaseMemoryUsage(memoryUsage()); \ + readBackInfo(); class QDeferredGraphicsSystemChange : public QObject @@ -252,16 +250,8 @@ QPixmapData* QRuntimePixmapData::runtimeData() const return m_data; } -uint QRuntimePixmapData::memoryUsage() const -{ - if(is_null || d == 0) - return 0; - return w * h * (d / 8); -} - - QRuntimeWindowSurface::QRuntimeWindowSurface(const QRuntimeGraphicsSystem *gs, QWidget *window) - : QWindowSurface(window), m_windowSurface(0), m_pendingWindowSurface(0), m_graphicsSystem(gs) + : QWindowSurface(window), m_graphicsSystem(gs) { } @@ -269,7 +259,6 @@ QRuntimeWindowSurface::QRuntimeWindowSurface(const QRuntimeGraphicsSystem *gs, Q QRuntimeWindowSurface::~QRuntimeWindowSurface() { m_graphicsSystem->removeWindowSurface(this); - delete m_windowSurface; } QPaintDevice *QRuntimeWindowSurface::paintDevice() @@ -288,16 +277,13 @@ void QRuntimeWindowSurface::flush(QWidget *widget, const QRegion ®ion, #ifdef QT_DEBUG qDebug() << "QRuntimeWindowSurface::flush() - destroy pending window surface"; #endif - delete m_pendingWindowSurface; - m_pendingWindowSurface = 0; + m_pendingWindowSurface.reset(); } } void QRuntimeWindowSurface::setGeometry(const QRect &rect) { - m_graphicsSystem->decreaseMemoryUsage(memoryUsage()); m_windowSurface->setGeometry(rect); - m_graphicsSystem->increaseMemoryUsage(memoryUsage()); } bool QRuntimeWindowSurface::scroll(const QRegion &area, int dx, int dy) @@ -330,27 +316,21 @@ QPoint QRuntimeWindowSurface::offset(const QWidget *widget) const return m_windowSurface->offset(widget); } -uint QRuntimeWindowSurface::memoryUsage() const -{ - QPaintDevice *pdev = m_windowSurface->paintDevice(); - if (pdev && pdev->depth() != 0) - return pdev->width() * pdev->height() * (pdev->depth()/8); - - return 0; -} - QRuntimeGraphicsSystem::QRuntimeGraphicsSystem() - : m_memoryUsage(0), m_windowSurfaceDestroyPolicy(DestroyImmediately), - m_graphicsSystem(0), m_graphicsSystemChangeMemoryLimit(0) + : m_windowSurfaceDestroyPolicy(DestroyImmediately), + m_graphicsSystem(0) { QApplicationPrivate::graphics_system_name = QLatin1String("runtime"); QApplicationPrivate::runtime_graphics_system = true; +#ifdef QT_DEFAULT_RUNTIME_SYSTEM + m_graphicsSystemName = QLatin1String(QT_DEFAULT_RUNTIME_SYSTEM); + if (m_graphicsSystemName.isNull()) +#endif + m_graphicsSystemName = QLatin1String("raster"); + #ifdef Q_OS_SYMBIAN - m_graphicsSystemName = QLatin1String("openvg"); m_windowSurfaceDestroyPolicy = DestroyAfterFirstFlush; -#else - m_graphicsSystemName = QLatin1String("raster"); #endif m_graphicsSystem = QGraphicsSystemFactory::create(m_graphicsSystemName); @@ -373,51 +353,30 @@ QWindowSurface *QRuntimeGraphicsSystem::createWindowSurface(QWidget *widget) con { Q_ASSERT(m_graphicsSystem); QRuntimeWindowSurface *rtSurface = new QRuntimeWindowSurface(this, widget); - rtSurface->m_windowSurface = m_graphicsSystem->createWindowSurface(widget); + rtSurface->m_windowSurface.reset(m_graphicsSystem->createWindowSurface(widget)); widget->setWindowSurface(rtSurface); m_windowSurfaces << rtSurface; - increaseMemoryUsage(rtSurface->memoryUsage()); return rtSurface; } -/*! - Sets graphics system when resource memory consumption is under /a memoryUsageLimit. -*/ -void QRuntimeGraphicsSystem::setGraphicsSystem(const QString &name, uint memoryUsageLimit) -{ -#ifdef QT_DEBUG - qDebug() << "QRuntimeGraphicsSystem::setGraphicsSystem( "<< name <<", " << memoryUsageLimit << ")"; - qDebug() << " current approximated graphics system memory usage " << memoryUsage() << " bytes"; -#endif - if (memoryUsage() >= memoryUsageLimit) { - m_graphicsSystemChangeMemoryLimit = memoryUsageLimit; - m_pendingGraphicsSystemName = name; - } else { - setGraphicsSystem(name); - } -} - void QRuntimeGraphicsSystem::setGraphicsSystem(const QString &name) { if (m_graphicsSystemName == name) return; #ifdef QT_DEBUG qDebug() << "QRuntimeGraphicsSystem::setGraphicsSystem( " << name << " )"; - qDebug() << " current approximated graphics system memory usage "<< memoryUsage() << " bytes"; #endif - delete m_graphicsSystem; + QGraphicsSystem *oldSystem = m_graphicsSystem; m_graphicsSystem = QGraphicsSystemFactory::create(name); m_graphicsSystemName = name; Q_ASSERT(m_graphicsSystem); - m_graphicsSystemChangeMemoryLimit = 0; m_pendingGraphicsSystemName = QString(); for (int i = 0; i < m_pixmapDatas.size(); ++i) { QRuntimePixmapData *proxy = m_pixmapDatas.at(i); QPixmapData *newData = m_graphicsSystem->createPixmapData(proxy->m_data); - // ### TODO Optimize. Openvg and s60raster graphics systems could switch internal ARGB32_PRE QImage buffers. newData->fromImage(proxy->m_data->toImage(), Qt::NoOpaqueDetection); delete proxy->m_data; proxy->m_data = newData; @@ -428,58 +387,26 @@ void QRuntimeGraphicsSystem::setGraphicsSystem(const QString &name) QRuntimeWindowSurface *proxy = m_windowSurfaces.at(i); QWidget *widget = proxy->m_windowSurface->window(); - if(m_windowSurfaceDestroyPolicy == DestroyImmediately) { - delete proxy->m_windowSurface; - proxy->m_pendingWindowSurface = 0; - } else { - proxy->m_pendingWindowSurface = proxy->m_windowSurface; - } + if(m_windowSurfaceDestroyPolicy == DestroyAfterFirstFlush) + proxy->m_pendingWindowSurface.reset(proxy->m_windowSurface.take()); - proxy->m_windowSurface = m_graphicsSystem->createWindowSurface(widget); + proxy->m_windowSurface.reset(m_graphicsSystem->createWindowSurface(widget)); qt_widget_private(widget)->invalidateBuffer(widget->rect()); } + + delete oldSystem; } void QRuntimeGraphicsSystem::removePixmapData(QRuntimePixmapData *pixmapData) const { int index = m_pixmapDatas.lastIndexOf(pixmapData); m_pixmapDatas.removeAt(index); - decreaseMemoryUsage(pixmapData->memoryUsage(), true); } void QRuntimeGraphicsSystem::removeWindowSurface(QRuntimeWindowSurface *windowSurface) const { int index = m_windowSurfaces.lastIndexOf(windowSurface); m_windowSurfaces.removeAt(index); - decreaseMemoryUsage(windowSurface->memoryUsage(), true); -} - -void QRuntimeGraphicsSystem::increaseMemoryUsage(uint amount) const -{ - m_memoryUsage += amount; - - if (m_graphicsSystemChangeMemoryLimit && - m_memoryUsage < m_graphicsSystemChangeMemoryLimit) { - - QRuntimeGraphicsSystem *gs = const_cast<QRuntimeGraphicsSystem*>(this); - QDeferredGraphicsSystemChange *deferredChange = - new QDeferredGraphicsSystemChange(gs, m_pendingGraphicsSystemName); - deferredChange->launch(); - } -} - -void QRuntimeGraphicsSystem::decreaseMemoryUsage(uint amount, bool persistent) const -{ - m_memoryUsage -= amount; - - if (persistent && m_graphicsSystemChangeMemoryLimit && - m_memoryUsage < m_graphicsSystemChangeMemoryLimit) { - - QRuntimeGraphicsSystem *gs = const_cast<QRuntimeGraphicsSystem*>(this); - QDeferredGraphicsSystemChange *deferredChange = - new QDeferredGraphicsSystemChange(gs, m_pendingGraphicsSystemName); - deferredChange->launch(); - } } #include "qgraphicssystem_runtime.moc" diff --git a/src/gui/painting/qgraphicssystem_runtime_p.h b/src/gui/painting/qgraphicssystem_runtime_p.h index 7aab89c988..02322418fe 100644 --- a/src/gui/painting/qgraphicssystem_runtime_p.h +++ b/src/gui/painting/qgraphicssystem_runtime_p.h @@ -104,8 +104,6 @@ public: virtual QPixmapData *runtimeData() const; - virtual uint memoryUsage() const; - private: const QRuntimeGraphicsSystem *m_graphicsSystem; @@ -131,10 +129,8 @@ public: virtual QPoint offset(const QWidget *widget) const; - virtual uint memoryUsage() const; - - QWindowSurface *m_windowSurface; - QWindowSurface *m_pendingWindowSurface; + QScopedPointer<QWindowSurface> m_windowSurface; + QScopedPointer<QWindowSurface> m_pendingWindowSurface; private: const QRuntimeGraphicsSystem *m_graphicsSystem; @@ -159,7 +155,6 @@ public: void removePixmapData(QRuntimePixmapData *pixmapData) const; void removeWindowSurface(QRuntimeWindowSurface *windowSurface) const; - void setGraphicsSystem(const QString &name, uint memoryUsageLimit); void setGraphicsSystem(const QString &name); QString graphicsSystemName() const { return m_graphicsSystemName; } @@ -170,22 +165,14 @@ public: int windowSurfaceDestroyPolicy() const { return m_windowSurfaceDestroyPolicy; } - uint memoryUsage() const { return m_memoryUsage; } - -private: - - void increaseMemoryUsage(uint amount) const; - void decreaseMemoryUsage(uint amount, bool persistent = false) const; private: - mutable uint m_memoryUsage; int m_windowSurfaceDestroyPolicy; QGraphicsSystem *m_graphicsSystem; mutable QList<QRuntimePixmapData *> m_pixmapDatas; mutable QList<QRuntimeWindowSurface *> m_windowSurfaces; QString m_graphicsSystemName; - uint m_graphicsSystemChangeMemoryLimit; QString m_pendingGraphicsSystemName; friend class QRuntimePixmapData; diff --git a/src/gui/painting/qpaintengine_x11.cpp b/src/gui/painting/qpaintengine_x11.cpp index 910b2df3d7..e521e018c3 100644 --- a/src/gui/painting/qpaintengine_x11.cpp +++ b/src/gui/painting/qpaintengine_x11.cpp @@ -696,11 +696,10 @@ void QX11PaintEngine::drawLines(const QLine *lines, int lineCount) linef = d->matrix.map(QLineF(lines[i])); } if (clipLine(&linef, d->polygonClipper.boundingRect())) { - int x1 = qRound(linef.x1() + aliasedCoordinateDelta); - int y1 = qRound(linef.y1() + aliasedCoordinateDelta); - int x2 = qRound(linef.x2() + aliasedCoordinateDelta); - int y2 = qRound(linef.y2() + aliasedCoordinateDelta); - + int x1 = qFloor(linef.x1() + aliasedCoordinateDelta); + int y1 = qFloor(linef.y1() + aliasedCoordinateDelta); + int x2 = qFloor(linef.x2() + aliasedCoordinateDelta); + int y2 = qFloor(linef.y2() + aliasedCoordinateDelta); XDrawLine(d->dpy, d->hd, d->gc, x1, y1, x2, y2); } } @@ -730,11 +729,10 @@ void QX11PaintEngine::drawLines(const QLineF *lines, int lineCount) for (int i = 0; i < lineCount; ++i) { QLineF linef = d->matrix.map(lines[i]); if (clipLine(&linef, d->polygonClipper.boundingRect())) { - int x1 = qRound(linef.x1() + aliasedCoordinateDelta); - int y1 = qRound(linef.y1() + aliasedCoordinateDelta); - int x2 = qRound(linef.x2() + aliasedCoordinateDelta); - int y2 = qRound(linef.y2() + aliasedCoordinateDelta); - + int x1 = qFloor(linef.x1() + aliasedCoordinateDelta); + int y1 = qFloor(linef.y1() + aliasedCoordinateDelta); + int x2 = qFloor(linef.x2() + aliasedCoordinateDelta); + int y2 = qFloor(linef.y2() + aliasedCoordinateDelta); XDrawLine(d->dpy, d->hd, d->gc, x1, y1, x2, y2); } } @@ -1690,8 +1688,8 @@ void QX11PaintEnginePrivate::strokePolygon_dev(const QPointF *polygonPoints, int if (clippedCount > 0) { QVarLengthArray<XPoint> xpoints(clippedCount); for (int i = 0; i < clippedCount; ++i) { - xpoints[i].x = qRound(clippedPoints[i].x + aliasedCoordinateDelta); - xpoints[i].y = qRound(clippedPoints[i].y + aliasedCoordinateDelta); + xpoints[i].x = qFloor(clippedPoints[i].x + aliasedCoordinateDelta); + xpoints[i].y = qFloor(clippedPoints[i].y + aliasedCoordinateDelta); } uint numberPoints = qMin(clippedCount, xlibMaxLinePoints); XPoint *pts = xpoints.data(); diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index e0746fbb5a..881bd6e145 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -831,7 +831,7 @@ void QPaintEngineEx::drawEllipse(const QRectF &r) int point_count = 0; x.points[0] = qt_curves_for_arc(r, 0, -360, x.points + 1, &point_count); - QVectorPath vp((qreal *) pts, 13, qpaintengineex_ellipse_types, QVectorPath::EllipseHint); + QVectorPath vp((qreal *) pts, point_count, qpaintengineex_ellipse_types, QVectorPath::EllipseHint); draw(vp); } diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index c4de7f01c4..314f34995a 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -88,14 +88,19 @@ bool qt_show_painter_debug_output = true; extern QPixmap qt_pixmapForBrush(int style, bool invert); -static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, QFontEngine *fe, - QTextCharFormat::UnderlineStyle underlineStyle, - QTextItemInt::RenderFlags flags, qreal width, - const QTextCharFormat &charFormat); void qt_format_text(const QFont &font, const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect, int tabstops, int* tabarray, int tabarraylen, QPainter *painter); +static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, + QTextCharFormat::UnderlineStyle underlineStyle, + QTextItem::RenderFlags flags, qreal width, + const QTextCharFormat &charFormat); +// Helper function to calculate left most position, width and flags for decoration drawing +static void drawDecorationForGlyphs(QPainter *painter, const glyph_t *glyphArray, + const QFixedPoint *positions, int glyphCount, + QFontEngine *fontEngine, const QFont &font, + const QTextCharFormat &charFormat); static inline QGradient::CoordinateMode coordinateMode(const QBrush &brush) { @@ -6051,6 +6056,10 @@ void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText currentColor = item->color; } d->extended->drawStaticTextItem(item); + + drawDecorationForGlyphs(this, item->glyphs, item->glyphPositions, + item->numGlyphs, item->fontEngine, staticText_d->font, + QTextCharFormat()); } if (currentColor != oldPen.color()) setPen(oldPen); @@ -6418,9 +6427,9 @@ static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen) return pixmap; } -static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, QFontEngine *fe, +static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextCharFormat::UnderlineStyle underlineStyle, - QTextItemInt::RenderFlags flags, qreal width, + QTextItem::RenderFlags flags, qreal width, const QTextCharFormat &charFormat) { if (underlineStyle == QTextCharFormat::NoUnderline @@ -6494,6 +6503,50 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, QFontE painter->setBrush(oldBrush); } +static void drawDecorationForGlyphs(QPainter *painter, const glyph_t *glyphArray, + const QFixedPoint *positions, int glyphCount, + QFontEngine *fontEngine, const QFont &font, + const QTextCharFormat &charFormat) +{ + if (!(font.underline() || font.strikeOut() || font.overline())) + return; + + QFixed leftMost; + QFixed rightMost; + QFixed baseLine; + for (int i=0; i<glyphCount; ++i) { + glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]); + if (i == 0 || leftMost > positions[i].x) + leftMost = positions[i].x; + + // We don't support glyphs that do not share a common baseline. If this turns out to + // be a relevant use case, then we need to find clusters of glyphs that share a baseline + // and do a drawTextItemDecorations call per cluster. + if (i == 0 || baseLine < positions[i].y) + baseLine = positions[i].y; + + // We use the advance rather than the actual bounds to match the algorithm in drawText() + if (i == 0 || rightMost < positions[i].x + gm.xoff) + rightMost = positions[i].x + gm.xoff; + } + + QFixed width = rightMost - leftMost; + QTextItem::RenderFlags flags = 0; + + if (font.underline()) + flags |= QTextItem::Underline; + if (font.overline()) + flags |= QTextItem::Overline; + if (font.strikeOut()) + flags |= QTextItem::StrikeOut; + + drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()), + fontEngine, + font.underline() ? QTextCharFormat::SingleUnderline + : QTextCharFormat::NoUnderline, flags, + width.toReal(), charFormat); +} + void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti) { #ifdef QT_DEBUG_DRAW diff --git a/src/gui/painting/qwindowsurface_s60.cpp b/src/gui/painting/qwindowsurface_s60.cpp index 477bd93d08..8bac1f5f69 100644 --- a/src/gui/painting/qwindowsurface_s60.cpp +++ b/src/gui/painting/qwindowsurface_s60.cpp @@ -67,10 +67,14 @@ QS60WindowSurface::QS60WindowSurface(QWidget* widget) TDisplayMode mode = S60->screenDevice()->DisplayMode(); bool isOpaque = qt_widget_private(widget)->isOpaque; - if (mode == EColor16MA && isOpaque) - mode = EColor16MU; // Faster since 16MU -> 16MA is typically accelerated - else if (mode == EColor16MU && !isOpaque) - mode = EColor16MA; // Try for transparency anyway + if (isOpaque) { + mode = EColor16MU; + } else { + if (QSysInfo::symbianVersion() >= QSysInfo::SV_SF_3) + mode = Q_SYMBIAN_ECOLOR16MAP; // Symbian^3 WServ has support for ARGB32_PRE + else + mode = EColor16MA; // Symbian prior to Symbian^3 sw accelerates EColor16MA + } // We create empty CFbsBitmap here -> it will be resized in setGeometry CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap); // CBase derived object needs check on new diff --git a/src/gui/s60framework/qs60mainapplication.cpp b/src/gui/s60framework/qs60mainapplication.cpp index 0f9367ec97..5d4c54e337 100644 --- a/src/gui/s60framework/qs60mainapplication.cpp +++ b/src/gui/s60framework/qs60mainapplication.cpp @@ -136,16 +136,25 @@ TFileName QS60MainApplication::ResourceFileName() const return KNullDesC(); } +/*! + \internal +*/ void QS60MainApplication::PreDocConstructL() { QS60MainApplicationBase::PreDocConstructL(); } +/*! + \internal +*/ CDictionaryStore *QS60MainApplication::OpenIniFileLC(RFs &aFs) const { return QS60MainApplicationBase::OpenIniFileLC(aFs); } +/*! + \internal +*/ void QS60MainApplication::NewAppServerL(CApaAppServer *&aAppServer) { QS60MainApplicationBase::NewAppServerL(aAppServer); diff --git a/src/gui/s60framework/qs60mainappui.cpp b/src/gui/s60framework/qs60mainappui.cpp index 40c2d0327e..ea9dbb3227 100644 --- a/src/gui/s60framework/qs60mainappui.cpp +++ b/src/gui/s60framework/qs60mainappui.cpp @@ -281,76 +281,121 @@ void QS60MainAppUi::RestoreMenuL(CCoeControl *menuWindow, TInt resourceId, TMenu } } +/*! + \internal +*/ void QS60MainAppUi::Exit() { QS60MainAppUiBase::Exit(); } +/*! + \internal +*/ void QS60MainAppUi::SetFadedL(TBool aFaded) { QS60MainAppUiBase::SetFadedL(aFaded); } +/*! + \internal +*/ TRect QS60MainAppUi::ApplicationRect() const { return QS60MainAppUiBase::ApplicationRect(); } +/*! + \internal +*/ void QS60MainAppUi::HandleScreenDeviceChangedL() { QS60MainAppUiBase::HandleScreenDeviceChangedL(); } +/*! + \internal +*/ void QS60MainAppUi::HandleApplicationSpecificEventL(TInt aType, const TWsEvent &aEvent) { QS60MainAppUiBase::HandleApplicationSpecificEventL(aType, aEvent); } +/*! + \internal +*/ TTypeUid::Ptr QS60MainAppUi::MopSupplyObject(TTypeUid aId) { return QS60MainAppUiBase::MopSupplyObject(aId); } +/*! + \internal +*/ void QS60MainAppUi::ProcessCommandL(TInt aCommand) { QS60MainAppUiBase::ProcessCommandL(aCommand); } +/*! + \internal +*/ TErrorHandlerResponse QS60MainAppUi::HandleError (TInt aError, const SExtendedError &aExtErr, TDes &aErrorText, TDes &aContextText) { return QS60MainAppUiBase::HandleError(aError, aExtErr, aErrorText, aContextText); } +/*! + \internal +*/ void QS60MainAppUi::HandleViewDeactivation(const TVwsViewId &aViewIdToBeDeactivated, const TVwsViewId &aNewlyActivatedViewId) { QS60MainAppUiBase::HandleViewDeactivation(aViewIdToBeDeactivated, aNewlyActivatedViewId); } +/*! + \internal +*/ void QS60MainAppUi::PrepareToExit() { QS60MainAppUiBase::PrepareToExit(); } +/*! + \internal +*/ void QS60MainAppUi::HandleTouchPaneSizeChange() { QS60MainAppUiBase::HandleTouchPaneSizeChange(); } +/*! + \internal +*/ void QS60MainAppUi::HandleSystemEventL(const TWsEvent &aEvent) { QS60MainAppUiBase::HandleSystemEventL(aEvent); } +/*! + \internal +*/ void QS60MainAppUi::Reserved_MtsmPosition() { QS60MainAppUiBase::Reserved_MtsmPosition(); } +/*! + \internal +*/ void QS60MainAppUi::Reserved_MtsmObject() { QS60MainAppUiBase::Reserved_MtsmObject(); } +/*! + \internal +*/ void QS60MainAppUi::HandleForegroundEventL(TBool aForeground) { QS60MainAppUiBase::HandleForegroundEventL(aForeground); diff --git a/src/gui/s60framework/qs60maindocument.cpp b/src/gui/s60framework/qs60maindocument.cpp index ed33a4165b..26e2d007a7 100644 --- a/src/gui/s60framework/qs60maindocument.cpp +++ b/src/gui/s60framework/qs60maindocument.cpp @@ -105,11 +105,17 @@ CEikAppUi *QS60MainDocument::CreateAppUiL() return (static_cast <CEikAppUi*>(new(ELeave)QS60MainAppUi)); } +/*! + \internal + */ CFileStore *QS60MainDocument::OpenFileL(TBool aDoOpen, const TDesC &aFilename, RFs &aFs) { return QS60MainDocumentBase::OpenFileL(aDoOpen, aFilename, aFs); } +/*! + \internal + */ void QS60MainDocument::OpenFileL(CFileStore *&aFileStore, RFile &aFile) { QS60MainDocumentBase::OpenFileL(aFileStore, aFile); diff --git a/src/gui/s60framework/qs60maindocument.h b/src/gui/s60framework/qs60maindocument.h index 2f0564fb4b..fc32d8bf39 100644 --- a/src/gui/s60framework/qs60maindocument.h +++ b/src/gui/s60framework/qs60maindocument.h @@ -47,7 +47,7 @@ #ifdef Q_OS_SYMBIAN #ifdef Q_WS_S60 -#include <akndoc.h> +#include <AknDoc.h> typedef CAknDocument QS60MainDocumentBase; #else #include <eikdoc.h> diff --git a/src/gui/styles/qmacstyle_mac.h b/src/gui/styles/qmacstyle_mac.h index bcebb1dd33..d5fcdaef7e 100644 --- a/src/gui/styles/qmacstyle_mac.h +++ b/src/gui/styles/qmacstyle_mac.h @@ -60,6 +60,8 @@ class QPalette; #define Q_GUI_EXPORT_STYLE_MAC Q_GUI_EXPORT #endif +class QPushButton; +class QStyleOptionButton; class QMacStylePrivate; class Q_GUI_EXPORT_STYLE_MAC QMacStyle : public QWindowsStyle { @@ -133,6 +135,8 @@ private: Q_DISABLE_COPY(QMacStyle) QMacStylePrivate *d; + + friend bool qt_mac_buttonIsRenderedFlat(const QPushButton *pushButton, const QStyleOptionButton *option); }; #endif // Q_WS_MAC diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm index bdcf5d6f85..556e0f303e 100644 --- a/src/gui/styles/qmacstyle_mac.mm +++ b/src/gui/styles/qmacstyle_mac.mm @@ -1059,6 +1059,16 @@ void QMacStylePrivate::initHIThemePushButton(const QStyleOptionButton *btn, } } +bool qt_mac_buttonIsRenderedFlat(const QPushButton *pushButton, const QStyleOptionButton *option) +{ + QMacStyle *macStyle = qobject_cast<QMacStyle *>(pushButton->style()); + if (!macStyle) + return false; + HIThemeButtonDrawInfo bdi; + macStyle->d->initHIThemePushButton(option, pushButton, kThemeStateActive, &bdi); + return bdi.kind == kThemeBevelButton; +} + /** Creates a HIThemeButtonDrawInfo structure that specifies the correct button kind and other details to use for drawing the given combobox. Which button @@ -1430,6 +1440,9 @@ QMacStylePrivate::QMacStylePrivate(QMacStyle *style) bool QMacStylePrivate::animatable(QMacStylePrivate::Animates as, const QWidget *w) const { + if (!w) + return false; + if (as == AquaPushButton) { QPushButton *pb = const_cast<QPushButton *>(static_cast<const QPushButton *>(w)); if (w->window()->isActiveWindow() && pb && !mouseDown) { diff --git a/src/gui/styles/qmacstyle_mac_p.h b/src/gui/styles/qmacstyle_mac_p.h index 5a0ba4cba3..f9b9d30bc7 100644 --- a/src/gui/styles/qmacstyle_mac_p.h +++ b/src/gui/styles/qmacstyle_mac_p.h @@ -150,6 +150,8 @@ enum QAquaWidgetSize { QAquaSizeLarge = 0, QAquaSizeSmall = 1, QAquaSizeMini = 2 return sizes[controlSize]; \ } while (0) +bool qt_mac_buttonIsRenderedFlat(const QPushButton *pushButton, const QStyleOptionButton *option); + class QMacStylePrivate : public QObject { Q_OBJECT diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp index 252766296f..f44b85e7d6 100644 --- a/src/gui/styles/qs60style_s60.cpp +++ b/src/gui/styles/qs60style_s60.cpp @@ -58,12 +58,12 @@ #include <AknsSkinInstance.h> #include <AknsBasicBackgroundControlContext.h> #include <avkon.mbg> -#include <aknfontaccess.h> -#include <aknlayoutfont.h> +#include <AknFontAccess.h> +#include <AknLayoutFont.h> #include <AknUtils.h> #include <aknnavi.h> #include <gulicon.h> -#include <aknbitmapanimation.h> +#include <AknBitmapAnimation.h> #if !defined(QT_NO_STYLE_S60) || defined(QT_PLUGIN) diff --git a/src/gui/styles/qstyle.cpp b/src/gui/styles/qstyle.cpp index 687e587365..0a75492b8c 100644 --- a/src/gui/styles/qstyle.cpp +++ b/src/gui/styles/qstyle.cpp @@ -325,7 +325,7 @@ static int unpackControlTypes(QSizePolicy::ControlTypes controls, QSizePolicy::C control over size of header items and row and column sizes. \sa QStyleOption, QStylePainter, {Styles Example}, - {Styles & Style Aware Widgets}, QStyledItemDelegate + {Styles and Style Aware Widgets}, QStyledItemDelegate */ /*! diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index 272fb26a92..7351a7da6a 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -4094,7 +4094,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q if (pe1 != PseudoElement_None) { QRenderRule subRule = renderRule(w, opt, pe1); if (subRule.bg != 0 || subRule.hasDrawable()) { - //We test subRule.bg dirrectly because hasBackground() would return false for background:none. + //We test subRule.bg directly because hasBackground() would return false for background:none. //But we still don't want the default drawning in that case (example for QScrollBar::add-page) (task 198926) subRule.drawRule(p, opt->rect); } else if (fallback) { @@ -4283,6 +4283,13 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op } break; + case PE_FrameMenu: + if (rule.hasDrawable()) { + // Drawn by PE_PanelMenu + return; + } + break; + case PE_PanelMenuBar: if (rule.hasDrawable()) { // Drawn by PE_Widget diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm index f6b875819e..f898fb836a 100644 --- a/src/gui/text/qfontengine_mac.mm +++ b/src/gui/text/qfontengine_mac.mm @@ -349,11 +349,32 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay int *nglyphs, QTextEngine::ShaperFlags flags) const { *nglyphs = len; + QCFType<CFStringRef> cfstring; + QVarLengthArray<CGGlyph> cgGlyphs(len); CTFontGetGlyphsForCharacters(ctfont, (const UniChar*)str, cgGlyphs.data(), len); - for (int i = 0; i < len; ++i) - glyphs->glyphs[i] = cgGlyphs[i]; + for (int i = 0; i < len; ++i) { + if (cgGlyphs[i]) { + glyphs->glyphs[i] = cgGlyphs[i]; + } else { + if (!cfstring) + cfstring = CFStringCreateWithCharactersNoCopy(0, reinterpret_cast<const UniChar *>(str), len, kCFAllocatorNull); + QCFType<CTFontRef> substituteFont = CTFontCreateForString(ctfont, cfstring, CFRangeMake(i, 1)); + CGGlyph substituteGlyph = 0; + CTFontGetGlyphsForCharacters(substituteFont, (const UniChar*)str + i, &substituteGlyph, 1); + if (substituteGlyph) { + const uint fontIndex = (fontIndexForFont(substituteFont) << 24); + glyphs->glyphs[i] = substituteGlyph | fontIndex; + if (!(flags & QTextEngine::GlyphIndicesOnly)) { + CGSize advance; + CTFontGetAdvancesForGlyphs(substituteFont, kCTFontHorizontalOrientation, &substituteGlyph, &advance, 1); + glyphs->advances_x[i] = QFixed::fromReal(advance.width); + glyphs->advances_y[i] = QFixed::fromReal(advance.height); + } + } + } + } if (flags & QTextEngine::GlyphIndicesOnly) return true; @@ -362,9 +383,14 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, cgGlyphs.data(), advances.data(), len); for (int i = 0; i < len; ++i) { + if (glyphs->glyphs[i] & 0xff000000) + continue; glyphs->advances_x[i] = QFixed::fromReal(advances[i].width); glyphs->advances_y[i] = QFixed::fromReal(advances[i].height); - if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { + } + + if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { + for (int i = 0; i < len; ++i) { glyphs->advances_x[i] = glyphs->advances_x[i].round(); glyphs->advances_y[i] = glyphs->advances_y[i].round(); } diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp index 74ef646fbb..52a1fe70b1 100644 --- a/src/gui/text/qfontengine_s60.cpp +++ b/src/gui/text/qfontengine_s60.cpp @@ -374,7 +374,10 @@ glyph_metrics_t QFontEngineS60::boundingBox(glyph_t glyph) QFixed QFontEngineS60::ascent() const { - return m_originalFont->FontMaxAscent(); + // Workaround for QTBUG-8013 + // Stroke based fonts may return an incorrect FontMaxAscent of 0. + const QFixed ascent = m_originalFont->FontMaxAscent(); + return (ascent > 0) ? ascent : QFixed::fromReal(m_originalFontSizeInPixels) - descent(); } QFixed QFontEngineS60::descent() const diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp index f6daed859d..21c2e0246c 100644 --- a/src/gui/text/qstatictext.cpp +++ b/src/gui/text/qstatictext.cpp @@ -109,10 +109,18 @@ QT_BEGIN_NAMESPACE QPainter::drawStaticText() and can change from call to call with a minimal impact on performance. - QStaticText will attempt to guess the format of the input text using Qt::mightBeRichText(). - To force QStaticText to display its contents as either plain text or rich text, use the - function QStaticText::setTextFormat() and pass in, respectively, Qt::PlainText and - Qt::RichText. + For extra convenience, it is possible to apply formatting to the text using the HTML subset + supported by QTextDocument. QStaticText will attempt to guess the format of the input text using + Qt::mightBeRichText(), and interpret it as rich text if this function returns true. To force + QStaticText to display its contents as either plain text or rich text, use the function + QStaticText::setTextFormat() and pass in, respectively, Qt::PlainText and Qt::RichText. + + QStaticText can only represent text, so only HTML tags which alter the layout or appearance of + the text will be respected. Adding an image to the input HTML, for instance, will cause the + image to be included as part of the layout, affecting the positions of the text glyphs, but it + will not be displayed. The result will be an empty area the size of the image in the output. + Similarly, using tables will cause the text to be laid out in table format, but the borders + will not be drawn. If it's the first time the static text is drawn, or if the static text, or the painter's font has been altered since the last time it was drawn, the text's layout has to be @@ -472,7 +480,12 @@ namespace { memcpy(charsDestination, ti.chars, sizeof(QChar) * currentItem.numChars); m_items.append(currentItem); - } + } + + virtual void drawPolygon(const QPointF *, int , PolygonDrawMode ) + { + /* intentionally empty */ + } virtual bool begin(QPaintDevice *) { return true; } virtual bool end() { return true; } diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index e365c8d51f..4135831354 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -923,6 +923,13 @@ void QTextEngine::shapeText(int item) const si.width += glyphs.advances_x[i]; } +static inline bool hasCaseChange(const QScriptItem &si) +{ + return si.analysis.flags == QScriptAnalysis::SmallCaps || + si.analysis.flags == QScriptAnalysis::Uppercase || + si.analysis.flags == QScriptAnalysis::Lowercase; +} + #if defined(Q_WS_WINCE) //TODO // set the glyph attributes heuristically. Assumes a 1 to 1 relationship between chars and glyphs // and no reordering. @@ -1050,14 +1057,15 @@ void QTextEngine::shapeTextWithCE(int item) const if (option.useDesignMetrics()) flags |= DesignMetrics; - attributes(); // pre-initialize char attributes + // pre-initialize char attributes + if (! attributes()) + return; const int len = length(item); int num_glyphs = length(item); const QChar *str = layoutData->string.unicode() + si.position; ushort upperCased[256]; - if (si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase - || si.analysis.flags == QScriptAnalysis::Lowercase) { + if (hasCaseChange(si)) { ushort *uc = upperCased; if (len > 256) uc = new ushort[len]; @@ -1071,7 +1079,14 @@ void QTextEngine::shapeTextWithCE(int item) const } while (true) { - ensureSpace(num_glyphs); + if (! ensureSpace(num_glyphs)) { + // If str is converted to uppercase/lowercase form with a new buffer, + // we need to delete that buffer before return for error + const ushort *uc = reinterpret_cast<const ushort *>(str); + if (hasCaseChange(si) && uc != upperCased) + delete [] uc; + return; + } num_glyphs = layoutData->glyphLayout.numGlyphs - layoutData->used; QGlyphLayout g = availableGlyphs(&si); @@ -1092,9 +1107,7 @@ void QTextEngine::shapeTextWithCE(int item) const layoutData->used += si.num_glyphs; const ushort *uc = reinterpret_cast<const ushort *>(str); - if ((si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase - || si.analysis.flags == QScriptAnalysis::Lowercase) - && uc != upperCased) + if (hasCaseChange(si) && uc != upperCased) delete [] uc; } #endif @@ -1133,8 +1146,7 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const entire_shaper_item.item.bidiLevel = si.analysis.bidiLevel; HB_UChar16 upperCased[256]; // XXX what about making this 4096, so we don't have to extend it ever. - if (si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase - || si.analysis.flags == QScriptAnalysis::Lowercase) { + if (hasCaseChange(si)) { HB_UChar16 *uc = upperCased; if (entire_shaper_item.item.length > 256) uc = new HB_UChar16[entire_shaper_item.item.length]; @@ -1156,17 +1168,24 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const entire_shaper_item.shaperFlags |= HB_ShaperFlag_UseDesignMetrics; entire_shaper_item.num_glyphs = qMax(layoutData->glyphLayout.numGlyphs - layoutData->used, int(entire_shaper_item.item.length)); - ensureSpace(entire_shaper_item.num_glyphs); + if (! ensureSpace(entire_shaper_item.num_glyphs)) { + if (hasCaseChange(si)) + delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string); + return; + } QGlyphLayout initialGlyphs = availableGlyphs(&si).mid(0, entire_shaper_item.num_glyphs); if (!stringToGlyphs(&entire_shaper_item, &initialGlyphs, font)) { - ensureSpace(entire_shaper_item.num_glyphs); + if (! ensureSpace(entire_shaper_item.num_glyphs)) { + if (hasCaseChange(si)) + delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string); + return; + } initialGlyphs = availableGlyphs(&si).mid(0, entire_shaper_item.num_glyphs); if (!stringToGlyphs(&entire_shaper_item, &initialGlyphs, font)) { // ############ if this happens there's a bug in the fontengine - if ((si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase - || si.analysis.flags == QScriptAnalysis::Lowercase) && entire_shaper_item.string != upperCased) + if (hasCaseChange(si) && entire_shaper_item.string != upperCased) delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string); return; } @@ -1231,7 +1250,11 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const remaining_glyphs -= shaper_item.initialGlyphCount; do { - ensureSpace(glyph_pos + shaper_item.num_glyphs + remaining_glyphs); + if (! ensureSpace(glyph_pos + shaper_item.num_glyphs + remaining_glyphs)) { + if (hasCaseChange(si)) + delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string); + return; + } const QGlyphLayout g = availableGlyphs(&si).mid(glyph_pos); moveGlyphData(g.mid(shaper_item.num_glyphs), g.mid(shaper_item.initialGlyphCount), remaining_glyphs); @@ -1271,8 +1294,7 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const layoutData->used += si.num_glyphs; - if ((si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase) - && entire_shaper_item.string != upperCased) + if (hasCaseChange(si) && entire_shaper_item.string != upperCased) delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string); } @@ -1317,7 +1339,8 @@ const HB_CharAttributes *QTextEngine::attributes() const return (HB_CharAttributes *) layoutData->memory; itemize(); - ensureSpace(layoutData->string.length()); + if (! ensureSpace(layoutData->string.length())) + return NULL; QVarLengthArray<HB_ScriptItem> hbScriptItems(layoutData->items.size()); @@ -1896,7 +1919,10 @@ void QTextEngine::justify(const QScriptLine &line) // don't include trailing white spaces when doing justification int line_length = line.length; - const HB_CharAttributes *a = attributes()+line.from; + const HB_CharAttributes *a = attributes(); + if (! a) + return; + a += line.from; while (line_length && a[line_length-1].whiteSpace) --line_length; // subtract one char more, as we can't justfy after the last character @@ -2077,7 +2103,7 @@ QTextEngine::LayoutData::LayoutData() memory_on_stack = false; used = 0; hasBidi = false; - inLayout = false; + layoutState = LayoutEmpty; haveCharAttributes = false; logClustersPtr = 0; available_glyphs = 0; @@ -2111,7 +2137,7 @@ QTextEngine::LayoutData::LayoutData(const QString &str, void **stack_memory, int } used = 0; hasBidi = false; - inLayout = false; + layoutState = LayoutEmpty; haveCharAttributes = false; } @@ -2122,12 +2148,12 @@ QTextEngine::LayoutData::~LayoutData() memory = 0; } -void QTextEngine::LayoutData::reallocate(int totalGlyphs) +bool QTextEngine::LayoutData::reallocate(int totalGlyphs) { Q_ASSERT(totalGlyphs >= glyphLayout.numGlyphs); if (memory_on_stack && available_glyphs >= totalGlyphs) { glyphLayout.grow(glyphLayout.data(), totalGlyphs); - return; + return true; } int space_charAttributes = sizeof(HB_CharAttributes)*string.length()/sizeof(void*) + 1; @@ -2135,7 +2161,14 @@ void QTextEngine::LayoutData::reallocate(int totalGlyphs) int space_glyphs = QGlyphLayout::spaceNeededForGlyphLayout(totalGlyphs)/sizeof(void*) + 2; int newAllocated = space_charAttributes + space_glyphs + space_logClusters; - Q_ASSERT(newAllocated >= allocated); + // These values can be negative if the length of string/glyphs causes overflow, + // we can't layout such a long string all at once, so return false here to + // indicate there is a failure + if (space_charAttributes < 0 || space_logClusters < 0 || space_glyphs < 0 || newAllocated < allocated) { + layoutState = LayoutFailed; + return false; + } + void **newMem = memory; newMem = (void **)::realloc(memory_on_stack ? 0 : memory, newAllocated*sizeof(void *)); Q_CHECK_PTR(newMem); @@ -2156,6 +2189,7 @@ void QTextEngine::LayoutData::reallocate(int totalGlyphs) glyphLayout.grow(reinterpret_cast<char *>(m), totalGlyphs); allocated = newAllocated; + return true; } // grow to the new size, copying the existing data to the new layout @@ -2187,7 +2221,7 @@ void QTextEngine::freeMemory() } else { layoutData->used = 0; layoutData->hasBidi = false; - layoutData->inLayout = false; + layoutData->layoutState = LayoutEmpty; layoutData->haveCharAttributes = false; } for (int i = 0; i < lines.size(); ++i) { @@ -2341,6 +2375,8 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int if (flags & Qt::TextShowMnemonic) { itemize(); HB_CharAttributes *attributes = const_cast<HB_CharAttributes *>(this->attributes()); + if (!attributes) + return QString(); for (int i = 0; i < layoutData->items.size(); ++i) { QScriptItem &si = layoutData->items[i]; if (!si.num_glyphs) @@ -2417,6 +2453,8 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int return QString(); const HB_CharAttributes *attributes = this->attributes(); + if (!attributes) + return QString(); if (mode == Qt::ElideRight) { QFixed currentWidth; diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 805d242242..b5faf2023d 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -416,6 +416,11 @@ class QTextFormatCollection; class Q_GUI_EXPORT QTextEngine { public: + enum LayoutState { + LayoutEmpty, + InLayout, + LayoutFailed, + }; struct LayoutData { LayoutData(const QString &str, void **stack_memory, int mem_size); LayoutData(); @@ -428,11 +433,11 @@ public: QGlyphLayout glyphLayout; mutable int used; uint hasBidi : 1; - uint inLayout : 1; + uint layoutState : 2; uint memory_on_stack : 1; uint haveCharAttributes : 1; QString string; - void reallocate(int totalGlyphs); + bool reallocate(int totalGlyphs); }; QTextEngine(LayoutData *data); @@ -520,9 +525,10 @@ public: return layoutData->glyphLayout.mid(si->glyph_data_offset, si->num_glyphs); } - inline void ensureSpace(int nGlyphs) const { + inline bool ensureSpace(int nGlyphs) const { if (layoutData->glyphLayout.numGlyphs - layoutData->used < nGlyphs) - layoutData->reallocate((((layoutData->used + nGlyphs)*3/2 + 15) >> 4) << 4); + return layoutData->reallocate((((layoutData->used + nGlyphs)*3/2 + 15) >> 4) << 4); + return true; } void freeMemory(); diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 9d27343ff4..3f83aee7c2 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -76,6 +76,8 @@ static inline QFixed leadingSpaceWidth(QTextEngine *eng, const QScriptLine &line int pos = line.length; const HB_CharAttributes *attributes = eng->attributes(); + if (!attributes) + return QFixed(); while (pos > 0 && attributes[line.from + pos - 1].whiteSpace) --pos; return eng->width(line.from + pos, line.length - pos); @@ -612,7 +614,7 @@ bool QTextLayout::cacheEnabled() const void QTextLayout::beginLayout() { #ifndef QT_NO_DEBUG - if (d->layoutData && d->layoutData->inLayout) { + if (d->layoutData && d->layoutData->layoutState == QTextEngine::InLayout) { qWarning("QTextLayout::beginLayout: Called while already doing layout"); return; } @@ -620,7 +622,7 @@ void QTextLayout::beginLayout() d->invalidate(); d->clearLineData(); d->itemize(); - d->layoutData->inLayout = true; + d->layoutData->layoutState = QTextEngine::InLayout; } /*! @@ -631,7 +633,7 @@ void QTextLayout::beginLayout() void QTextLayout::endLayout() { #ifndef QT_NO_DEBUG - if (!d->layoutData || !d->layoutData->inLayout) { + if (!d->layoutData || d->layoutData->layoutState == QTextEngine::LayoutEmpty) { qWarning("QTextLayout::endLayout: Called without beginLayout()"); return; } @@ -640,7 +642,7 @@ void QTextLayout::endLayout() if (l && d->lines.at(l-1).length < 0) { QTextLine(l-1, d).setNumColumns(INT_MAX); } - d->layoutData->inLayout = false; + d->layoutData->layoutState = QTextEngine::LayoutEmpty; if (!d->cacheGlyphs) d->freeMemory(); } @@ -768,11 +770,14 @@ bool QTextLayout::isValidCursorPosition(int pos) const QTextLine QTextLayout::createLine() { #ifndef QT_NO_DEBUG - if (!d->layoutData || !d->layoutData->inLayout) { + if (!d->layoutData || d->layoutData->layoutState == QTextEngine::LayoutEmpty) { qWarning("QTextLayout::createLine: Called without layouting"); return QTextLine(); } #endif + if (d->layoutData->layoutState == QTextEngine::LayoutFailed) + return QTextLine(); + int l = d->lines.size(); if (l && d->lines.at(l-1).length < 0) { QTextLine(l-1, d).setNumColumns(INT_MAX); @@ -1776,14 +1781,18 @@ namespace { return glyphs.glyphs[logClusters[currentPosition - 1]]; } + inline void adjustRightBearing(glyph_t glyph) + { + qreal rb; + fontEngine->getGlyphBearings(glyph, 0, &rb); + rightBearing = qMin(QFixed(), QFixed::fromReal(rb)); + } + inline void adjustRightBearing() { if (currentPosition <= 0) return; - - qreal rb; - fontEngine->getGlyphBearings(currentGlyph(), 0, &rb); - rightBearing = qMin(QFixed(), QFixed::fromReal(rb)); + adjustRightBearing(currentGlyph()); } inline void resetRightBearing() @@ -1884,6 +1893,8 @@ void QTextLine::layout_helper(int maxGlyphs) Qt::Alignment alignment = eng->option.alignment(); const HB_CharAttributes *attributes = eng->attributes(); + if (!attributes) + return; lbh.currentPosition = line.from; int end = 0; lbh.logClusters = eng->layoutData->logClustersPtr; @@ -1897,6 +1908,8 @@ void QTextLine::layout_helper(int maxGlyphs) if (!current.num_glyphs) { eng->shape(item); attributes = eng->attributes(); + if (!attributes) + return; lbh.logClusters = eng->layoutData->logClustersPtr; } lbh.currentPosition = qMax(line.from, current.position); @@ -1975,6 +1988,9 @@ void QTextLine::layout_helper(int maxGlyphs) } else { lbh.whiteSpaceOrObject = false; bool sb_or_ws = false; + glyph_t previousGlyph = 0; + if (lbh.currentPosition > 0 && lbh.logClusters[lbh.currentPosition - 1] <lbh.glyphs.numGlyphs) + previousGlyph = lbh.currentGlyph(); // needed to calculate right bearing later do { addNextCluster(lbh.currentPosition, end, lbh.tmpData, lbh.glyphCount, current, lbh.logClusters, lbh.glyphs); @@ -2018,9 +2034,17 @@ void QTextLine::layout_helper(int maxGlyphs) // We ignore the right bearing if the minimum negative bearing is too little to // expand the text beyond the edge. if (sb_or_ws|breakany) { + QFixed rightBearing = lbh.rightBearing; // store previous right bearing +#if !defined(Q_WS_MAC) if (lbh.calculateNewWidth(line) - lbh.minimumRightBearing > line.width) +#endif lbh.adjustRightBearing(); if (lbh.checkFullOtherwiseExtend(line)) { + // we are too wide, fix right bearing + if (rightBearing <= 0) + lbh.rightBearing = rightBearing; // take from cache + else if (previousGlyph > 0) + lbh.adjustRightBearing(previousGlyph); if (!breakany) { line.textWidth += lbh.softHyphenWidth; } diff --git a/src/gui/util/qdesktopservices_x11.cpp b/src/gui/util/qdesktopservices_x11.cpp index fe7f9a6be2..75e7209e1b 100644 --- a/src/gui/util/qdesktopservices_x11.cpp +++ b/src/gui/util/qdesktopservices_x11.cpp @@ -71,10 +71,12 @@ static bool openDocument(const QUrl &url) if (launch(url, QLatin1String("xdg-open"))) return true; - if (X11->desktopEnvironment == DE_GNOME && launch(url, QLatin1String("gnome-open"))) { + // Use the X11->desktopEnvironment value if X11 is non-NULL, + // otherwise just attempt to launch command regardless of the desktop environment + if ((!X11 || (X11 && X11->desktopEnvironment == DE_GNOME)) && launch(url, QLatin1String("gnome-open"))) { return true; } else { - if (X11->desktopEnvironment == DE_KDE && launch(url, QLatin1String("kfmclient exec"))) + if ((!X11 || (X11 && X11->desktopEnvironment == DE_KDE)) && launch(url, QLatin1String("kfmclient exec"))) return true; } @@ -104,10 +106,12 @@ static bool launchWebBrowser(const QUrl &url) if (launch(url, QString::fromLocal8Bit(getenv("BROWSER")))) return true; - if (X11->desktopEnvironment == DE_GNOME && launch(url, QLatin1String("gnome-open"))) { + // Use the X11->desktopEnvironment value if X11 is non-NULL, + // otherwise just attempt to launch command regardless of the desktop environment + if ((!X11 || (X11 && X11->desktopEnvironment == DE_GNOME)) && launch(url, QLatin1String("gnome-open"))) { return true; } else { - if (X11->desktopEnvironment == DE_KDE && launch(url, QLatin1String("kfmclient openURL"))) + if ((!X11 || (X11 && X11->desktopEnvironment == DE_KDE)) && launch(url, QLatin1String("kfmclient openURL"))) return true; } diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp index bb2da9a93a..487d24499c 100644 --- a/src/gui/widgets/qcombobox.cpp +++ b/src/gui/widgets/qcombobox.cpp @@ -911,7 +911,7 @@ QComboBox::QComboBox(bool rw, QWidget *parent, const char *name) interaction. The highlighted() signal is emitted when the user highlights an item in the combobox popup list. All three signals exist in two versions, one with a QString argument and one with an - \c int argument. If the user selectes or highlights a pixmap, only + \c int argument. If the user selects or highlights a pixmap, only the \c int signals are emitted. Whenever the text of an editable combobox is changed the editTextChanged() signal is emitted. diff --git a/src/gui/widgets/qcommandlinkbutton.cpp b/src/gui/widgets/qcommandlinkbutton.cpp index d3b586904e..a6f5f7dda9 100644 --- a/src/gui/widgets/qcommandlinkbutton.cpp +++ b/src/gui/widgets/qcommandlinkbutton.cpp @@ -349,7 +349,7 @@ void QCommandLinkButton::paintEvent(QPaintEvent *) QStyleOptionButton option; initStyleOption(&option); - //Enable command link appearence on Vista + //Enable command link appearance on Vista option.features |= QStyleOptionButton::CommandLinkButton; option.text = QString(); option.icon = QIcon(); //we draw this ourselves diff --git a/src/gui/widgets/qdatetimeedit.cpp b/src/gui/widgets/qdatetimeedit.cpp index e272ce47f9..3bc6412017 100644 --- a/src/gui/widgets/qdatetimeedit.cpp +++ b/src/gui/widgets/qdatetimeedit.cpp @@ -754,6 +754,7 @@ QCalendarWidget *QDateTimeEdit::calendarWidget() const Sets the given \a calendarWidget as the widget to be used for the calendar pop-up. The editor does not automatically take ownership of the calendar widget. + \note calendarPopup must be set to true before setting the calendar widget. \sa calendarPopup */ void QDateTimeEdit::setCalendarWidget(QCalendarWidget *calendarWidget) diff --git a/src/gui/widgets/qmainwindowlayout.cpp b/src/gui/widgets/qmainwindowlayout.cpp index 593e391e1a..62ee398e9e 100644 --- a/src/gui/widgets/qmainwindowlayout.cpp +++ b/src/gui/widgets/qmainwindowlayout.cpp @@ -943,7 +943,7 @@ void QMainWindowLayout::toggleToolBarsVisible() #ifdef Q_WS_MAC if (layoutState.mainWindow->unifiedTitleAndToolBarOnMac()) { // If we hit this case, someone has pressed the "toolbar button" which will - // toggle the unified toolbar visiblity, because that's what the user wants. + // toggle the unified toolbar visibility, because that's what the user wants. // We might be in a situation where someone has hidden all the toolbars // beforehand (maybe in construction), but now they've hit this button and // and are expecting the items to show. What do we do? diff --git a/src/gui/widgets/qmainwindowlayout_mac.mm b/src/gui/widgets/qmainwindowlayout_mac.mm index b8cef93456..1bfc746089 100644 --- a/src/gui/widgets/qmainwindowlayout_mac.mm +++ b/src/gui/widgets/qmainwindowlayout_mac.mm @@ -48,6 +48,7 @@ #include <Carbon/Carbon.h> #else #include <private/qcocoatoolbardelegate_mac_p.h> +#import <private/qcocoawindowdelegate_mac_p.h> #endif QT_BEGIN_NAMESPACE @@ -337,6 +338,17 @@ void QMainWindowLayout::updateHIToolBarStatus() #endif layoutState.mainWindow->setUpdatesEnabled(false); // reduces a little bit of flicker, not all though +#if defined(QT_MAC_USE_COCOA) + QMacCocoaAutoReleasePool pool; + NSView *cView = [qt_mac_window_for(layoutState.mainWindow) contentView]; + if (useMacToolbar) { + [cView setPostsFrameChangedNotifications:YES]; + [[NSNotificationCenter defaultCenter] addObserver: [QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] + selector: @selector(syncContentViewFrame:) + name: NSViewFrameDidChangeNotification + object: cView]; + } +#endif if (!useMacToolbar) { macWindowToolbarShow(layoutState.mainWindow, false); // Move everything out of the HIToolbar into the main toolbar. @@ -356,6 +368,14 @@ void QMainWindowLayout::updateHIToolBarStatus() } syncUnifiedToolbarVisibility(); } +#if defined(QT_MAC_USE_COCOA) + if (!useMacToolbar) { + [cView setPostsFrameChangedNotifications:NO]; + [[NSNotificationCenter defaultCenter] removeObserver: [QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] + name: NSViewFrameDidChangeNotification + object: cView]; + } +#endif layoutState.mainWindow->setUpdatesEnabled(true); } diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp index 469c7d429a..245657a618 100644 --- a/src/gui/widgets/qmenu.cpp +++ b/src/gui/widgets/qmenu.cpp @@ -262,7 +262,7 @@ void QMenuPrivate::updateActionRects() const const int deskFw = style->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, &opt, q); const int tearoffHeight = tearoff ? style->pixelMetric(QStyle::PM_MenuTearoffHeight, &opt, q) : 0; - //for compatability now - will have to refactor this away.. + //for compatibility now - will have to refactor this away tabWidth = 0; maxIconWidth = 0; hasCheckableItems = false; @@ -1154,7 +1154,7 @@ void QMenuPrivate::_q_actionHovered() bool QMenuPrivate::hasMouseMoved(const QPoint &globalPos) { - //determines if the mouse has moved (ie its intial position has + //determines if the mouse has moved (ie its initial position has //changed by more than QApplication::startDragDistance() //or if there were at least 6 mouse motions) return motions > 6 || diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp index e8e80b71ca..df16f7f83a 100644 --- a/src/gui/widgets/qmenubar.cpp +++ b/src/gui/widgets/qmenubar.cpp @@ -102,7 +102,7 @@ void QMenuBarExtension::paintEvent(QPaintEvent *) QStylePainter p(this); QStyleOptionToolButton opt; initStyleOption(&opt); - // We do not need to draw both extention arrows + // We do not need to draw both extension arrows opt.features &= ~QStyleOptionToolButton::HasMenu; p.drawComplexControl(QStyle::CC_ToolButton, opt); } diff --git a/src/gui/widgets/qprintpreviewwidget.cpp b/src/gui/widgets/qprintpreviewwidget.cpp index 45b15ef93c..ea311d379f 100644 --- a/src/gui/widgets/qprintpreviewwidget.cpp +++ b/src/gui/widgets/qprintpreviewwidget.cpp @@ -469,7 +469,7 @@ void QPrintPreviewWidgetPrivate::setZoomFactor(qreal _zoomFactor) \o Create the QPrintPreviewWidget Construct the QPrintPreviewWidget either by passing in an - exisiting QPrinter object, or have QPrintPreviewWidget create a + existing QPrinter object, or have QPrintPreviewWidget create a default constructed QPrinter object for you. \o Connect the paintRequested() signal to a slot. diff --git a/src/gui/widgets/qpushbutton.cpp b/src/gui/widgets/qpushbutton.cpp index 8a18ed0ea5..237c266751 100644 --- a/src/gui/widgets/qpushbutton.cpp +++ b/src/gui/widgets/qpushbutton.cpp @@ -687,11 +687,11 @@ bool QPushButton::event(QEvent *e) /*! \reimp */ bool QPushButton::hitButton(const QPoint &pos) const { - // This is only required if we are using the native style, so check that first. - QMacStyle *macStyle = qobject_cast<QMacStyle *>(style()); - // If this is a flat button we just bail out. - if(isFlat() || (0 == macStyle)) + QStyleOptionButton opt; + initStyleOption(&opt); + if (qt_mac_buttonIsRenderedFlat(this, &opt)) return QAbstractButton::hitButton(pos); + // Now that we know we are using the native style, let's proceed. Q_D(const QPushButton); QPushButtonPrivate *nonConst = const_cast<QPushButtonPrivate *>(d); diff --git a/src/gui/widgets/qtoolbarextension.cpp b/src/gui/widgets/qtoolbarextension.cpp index 032c6f07ce..574a7759b3 100644 --- a/src/gui/widgets/qtoolbarextension.cpp +++ b/src/gui/widgets/qtoolbarextension.cpp @@ -75,7 +75,7 @@ void QToolBarExtension::paintEvent(QPaintEvent *) QStylePainter p(this); QStyleOptionToolButton opt; initStyleOption(&opt); - // We do not need to draw both extention arrows + // We do not need to draw both extension arrows opt.features &= ~QStyleOptionToolButton::HasMenu; p.drawComplexControl(QStyle::CC_ToolButton, opt); } |