diff options
author | Oswald Buddenhagen <oswald.buddenhagen@nokia.com> | 2011-03-21 16:38:25 (GMT) |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@nokia.com> | 2011-03-21 16:38:25 (GMT) |
commit | 123a3aacd6a40fb07a225ef4db34ff7f986363ce (patch) | |
tree | 69744fb08a3b0dd4e246b90d2e90d4f533ca768b /src | |
parent | f92501a82f5bca1ccac07ed17850c84b281a1fb1 (diff) | |
parent | 12689cc05936d675c8a7065cf39b8334b83f95bb (diff) | |
download | Qt-123a3aacd6a40fb07a225ef4db34ff7f986363ce.zip Qt-123a3aacd6a40fb07a225ef4db34ff7f986363ce.tar.gz Qt-123a3aacd6a40fb07a225ef4db34ff7f986363ce.tar.bz2 |
Merge remote-tracking branch 'mainline/4.7' into 4.7
Conflicts:
dist/changes-4.7.4
Diffstat (limited to 'src')
34 files changed, 557 insertions, 256 deletions
diff --git a/src/declarative/declarative.pro b/src/declarative/declarative.pro index 1ad888b..f3a7db9 100644 --- a/src/declarative/declarative.pro +++ b/src/declarative/declarative.pro @@ -29,6 +29,8 @@ symbian: { LIBS += -lefsrv } +linux-g++-maemo:DEFINES += QDECLARATIVEVIEW_NOBACKGROUND + DEFINES += QT_NO_OPENTYPE INCLUDEPATH += ../3rdparty/harfbuzz/src diff --git a/src/declarative/graphicsitems/qdeclarativeimage.cpp b/src/declarative/graphicsitems/qdeclarativeimage.cpp index 2c9bde5..ed5d5fc 100644 --- a/src/declarative/graphicsitems/qdeclarativeimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimage.cpp @@ -147,8 +147,8 @@ void QDeclarativeImagePrivate::setPixmap(const QPixmap &pixmap) /*! \qmlproperty enumeration Image::fillMode - Set this property to define what happens when the image set for the item is smaller - than the size of the item. + Set this property to define what happens when the source image has a different size + than the item. \list \o Image.Stretch - the image is scaled to fit @@ -234,6 +234,9 @@ void QDeclarativeImagePrivate::setPixmap(const QPixmap &pixmap) \endtable + Note that \c clip is \c false by default which means that the element might + paint outside its bounding rectangle even if the fillMode is set to \c PreserveAspectCrop. + \sa {declarative/imageelements/image}{Image example} */ QDeclarativeImage::FillMode QDeclarativeImage::fillMode() const @@ -386,14 +389,16 @@ void QDeclarativeImage::updatePaintedGeometry() if (d->fillMode == PreserveAspectFit) { if (!d->pix.width() || !d->pix.height()) return; - qreal widthScale = width() / qreal(d->pix.width()); - qreal heightScale = height() / qreal(d->pix.height()); + qreal w = widthValid() ? width() : d->pix.width(); + qreal widthScale = w / qreal(d->pix.width()); + qreal h = heightValid() ? height() : d->pix.height(); + qreal heightScale = h / qreal(d->pix.height()); if (widthScale <= heightScale) { - d->paintedWidth = width(); + d->paintedWidth = w; d->paintedHeight = widthScale * qreal(d->pix.height()); } else if(heightScale < widthScale) { d->paintedWidth = heightScale * qreal(d->pix.width()); - d->paintedHeight = height(); + d->paintedHeight = h; } if (widthValid() && !heightValid()) { setImplicitHeight(d->paintedHeight); diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp index 471c87f..2de3ba0 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp @@ -130,7 +130,7 @@ QSize QDeclarativeImageBase::sourceSize() const int width = d->sourcesize.width(); int height = d->sourcesize.height(); - return QSize(width != -1 ? width : implicitWidth(), height != -1 ? height : implicitHeight()); + return QSize(width != -1 ? width : d->pix.width(), height != -1 ? height : d->pix.height()); } bool QDeclarativeImageBase::cache() const diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp index 9cf1e78..4af91ce 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp @@ -746,44 +746,63 @@ void QDeclarativeKeyNavigationAttached::setFocusNavigation(QDeclarativeItem *cur \qmlclass LayoutMirroring QDeclarativeLayoutMirroringAttached \since QtQuick 1.1 \ingroup qml-utility-elements - \brief The LayoutMirroring is used for mirroring the Qt Quick application layouts. + \brief The LayoutMirroring attached property is used to mirror layout behavior. - LayoutMirroring \l enabled property can be used to horizontally mirror \l {anchor-layout}{Item anchors}, - \l{Using QML Positioner and Repeater Items}{Positioner} elements and QML views like \l {GridView}{GridView} - and horizontal \l {ListView}{ListView}. Mirroring is a visual change, left anchors will become - right anchors and left-to-right positioner will instead position child items from right to left. - By default setting the \l enabled property to true only affects the item in question. You can set property - LayoutDirection \l childrenInherit to true if you want the item children also inherit the mirror setting. - If no attached property has been defined, mirroring is disabled. + The LayoutMirroring attached property is used to horizontally mirror \l {anchor-layout}{Item anchors}, + \l{Using QML Positioner and Repeater Items}{positioner} elements (such as \l Row and \l Grid) + and views (such as \l GridView and horizontal \l ListView). Mirroring is a visual change: left + anchors become right anchors, and positioner elements like \l Grid and \l Row reverse the + horizontal layout of child items. - The following example shows mirroring in action. When \l enabled is set to true, left anchor - becomes right, and \l {Row}{Row} starts positioning items in a reverse order: + Mirroring is enabled for an item by setting the \l enabled property to true. By default, this + only affects the item itself; setting the \l childrenInherit property to true propagates the mirroring + behavior to all child elements as well. If the \c LayoutMirroring attached property has not been defined + for an item, mirroring is not enabled. + + The following example shows mirroring in action. The \l Row below is specified as being anchored + to the left of its parent. However, since mirroring has been enabled, the anchor is horizontally + reversed and it is now anchored to the right. Also, since items in a \l Row are positioned + from left to right by default, they are now positioned from right to left instead, as demonstrated + by the numbering and opacity of the items: \snippet doc/src/snippets/declarative/layoutmirroring.qml 0 - Layout mirroring is useful when you need to support both left-to-right and right-to-left - layout versions of your application that target different language areas. Inheritance saves - you from having to mirror the layouts manually for each layout item in your application. Keep - in mind however that the mirroring does not affect the positioning done by modifying Item's x - co-ordinate directly, so even with the mirroring enabled you will often need to do some layout - fixes to support the other reading direction. Also, there are cases where you need to disable - mirroring of individual child items, either because mirroring is not the wanted behavior or - because the item already implements mirroring in some custom way. + \image layoutmirroring.png + + Layout mirroring is useful when it is necessary to support both left-to-right and right-to-left + layout versions of an application to target different language areas. The \l childrenInherit + property allows layout mirroring to be applied without manually setting layout configurations + for every item in an application. Keep in mind, however, that mirroring does not affect any + positioning that is defined by the \l Item \l {Item::}{x} coordinate value, so even with + mirroring enabled, it will often be necessary to apply some layout fixes to support the + desired layout direction. Also, it may be necessary to disable the mirroring of individual + child items (by setting \l {enabled}{LayoutMirroring.enabled} to false for such items) if + mirroring is not the desired behavior, or if the child item already implements mirroring in + some custom way. + + See \l {QML Right-to-left User Interfaces} for further details on using \c LayoutMirroring and + other related features to implement right-to-left support for an application. */ /*! \qmlproperty bool LayoutMirroring::enabled - Setting this property to true mirrors item's layout horizontally, whether the layout is done - using \l {anchor-layout}{anchors}, \l{Using QML Positioner and Repeater Items}{Positioners} - or as a QML view \l {GridView}{GridView} or \l {ListView}{ListView}. + This property holds whether the item's layout is mirrored horizontally. Setting this to true + horizontally reverses \l {anchor-layout}{anchor} settings such that left anchors become right, + and right anchors become left. For \l{Using QML Positioner and Repeater Items}{positioner} elements + (such as \l Row and \l Grid) and view elements (such as \l {GridView}{GridView} and \l {ListView}{ListView}) + this also mirrors the horizontal layout direction of the item. + + The default value is false. */ /*! \qmlproperty bool LayoutMirroring::childrenInherit - This property can be set to true if you want the item children - to inherit the item's mirror setting. + This property holds whether the \l {enabled}{LayoutMirroring.enabled} value for this item + is inherited by its children. + + The default value is false. */ QDeclarativeLayoutMirroringAttached::QDeclarativeLayoutMirroringAttached(QObject *parent) : QObject(parent), itemPrivate(0) @@ -1558,7 +1577,7 @@ QDeclarativeKeysAttached *QDeclarativeKeysAttached::qmlAttachedProperties(QObjec \section1 Layout Mirroring - Item layouts can be mirrored using \l {LayoutMirroring}{LayoutMirroring} attached property. + Item layouts can be mirrored using the \l {LayoutMirroring}{LayoutMirroring} attached property. */ diff --git a/src/declarative/graphicsitems/qdeclarativepathview.cpp b/src/declarative/graphicsitems/qdeclarativepathview.cpp index 4e401e9..778b8b9 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview.cpp +++ b/src/declarative/graphicsitems/qdeclarativepathview.cpp @@ -796,6 +796,7 @@ void QDeclarativePathView::setPreferredHighlightBegin(qreal start) return; d->highlightRangeStart = start; d->haveHighlightRange = d->highlightRangeMode != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd; + refill(); emit preferredHighlightBeginChanged(); } @@ -812,6 +813,7 @@ void QDeclarativePathView::setPreferredHighlightEnd(qreal end) return; d->highlightRangeEnd = end; d->haveHighlightRange = d->highlightRangeMode != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd; + refill(); emit preferredHighlightEndChanged(); } diff --git a/src/declarative/graphicsitems/qdeclarativepositioners.cpp b/src/declarative/graphicsitems/qdeclarativepositioners.cpp index 84dcec6..8a9bdb3 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners.cpp +++ b/src/declarative/graphicsitems/qdeclarativepositioners.cpp @@ -385,7 +385,7 @@ void QDeclarativeBasePositioner::finishApplyTransitions() Items with a width or height of 0 will not be positioned. - \sa Row, Grid, Flow, {declarative/positioners/addandremove}{Positioners example} + \sa Row, Grid, Flow, {declarative/positioners}{Positioners example} */ /*! \qmlproperty Transition Column::add @@ -425,7 +425,7 @@ void QDeclarativeBasePositioner::finishApplyTransitions() } \endqml - \sa add, {declarative/positioners/addandremove}{Positioners example} + \sa add, {declarative/positioners}{Positioners example} */ /*! \qmlproperty int Column::spacing @@ -528,7 +528,7 @@ void QDeclarativeColumn::reportConflictingAnchors() Items with a width or height of 0 will not be positioned. - \sa Column, Grid, Flow, {declarative/positioners/addandremove}{Positioners example} + \sa Column, Grid, Flow, {declarative/positioners}{Positioners example} */ /*! \qmlproperty Transition Row::add @@ -567,7 +567,7 @@ void QDeclarativeColumn::reportConflictingAnchors() } \endqml - \sa add, {declarative/positioners/addandremove}{Positioners example} + \sa add, {declarative/positioners}{Positioners example} */ /*! \qmlproperty int Row::spacing @@ -597,7 +597,7 @@ QDeclarativeRow::QDeclarativeRow(QDeclarativeItem *parent) the right anchor remains to the right of the row. \endlist - \sa Grid::layoutDirection, Flow::layoutDirection, {declarative/positioners/layoutdirection}{Layout directions example} + \sa Grid::layoutDirection, Flow::layoutDirection, {declarative/righttoleft/layoutdirection}{Layout directions example} */ Qt::LayoutDirection QDeclarativeRow::layoutDirection() const { @@ -753,7 +753,7 @@ void QDeclarativeRow::reportConflictingAnchors() Items with a width or height of 0 will not be positioned. - \sa Flow, Row, Column, {declarative/positioners/addandremove}{Positioners example} + \sa Flow, Row, Column, {declarative/positioners}{Positioners example} */ /*! \qmlproperty Transition Grid::add @@ -791,7 +791,7 @@ void QDeclarativeRow::reportConflictingAnchors() } \endqml - \sa add, {declarative/positioners/addandremove}{Positioners example} + \sa add, {declarative/positioners}{Positioners example} */ /*! \qmlproperty int Grid::spacing @@ -895,7 +895,7 @@ void QDeclarativeGrid::setFlow(Flow flow) \l Grid::flow property. \endlist - \sa Flow::layoutDirection, Row::layoutDirection, {declarative/positioners/layoutdirection}{Layout directions example} + \sa Flow::layoutDirection, Row::layoutDirection, {declarative/righttoleft/layoutdirection}{Layout directions example} */ Qt::LayoutDirection QDeclarativeGrid::layoutDirection() const { @@ -1137,7 +1137,7 @@ void QDeclarativeGrid::reportConflictingAnchors() Items with a width or height of 0 will not be positioned. - \sa Column, Row, Grid, {declarative/positioners/addandremove}{Positioners example} + \sa Column, Row, Grid, {declarative/positioners}{Positioners example} */ /*! \qmlproperty Transition Flow::add @@ -1176,7 +1176,7 @@ void QDeclarativeGrid::reportConflictingAnchors() } \endqml - \sa add, {declarative/positioners/addandremove}{Positioners example} + \sa add, {declarative/positioners}{Positioners example} */ /*! \qmlproperty int Flow::spacing @@ -1255,7 +1255,7 @@ void QDeclarativeFlow::setFlow(Flow flow) \l Flow::flow property. \endlist - \sa Grid::layoutDirection, Row::layoutDirection, {declarative/positioners/layoutdirection}{Layout directions example} + \sa Grid::layoutDirection, Row::layoutDirection, {declarative/righttoleft/layoutdirection}{Layout directions example} */ Qt::LayoutDirection QDeclarativeFlow::layoutDirection() const diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index c6de7a0..af18c90 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -399,10 +399,10 @@ bool QDeclarativeTextInputPrivate::setHAlign(QDeclarativeTextInput::HAlignment a if ((hAlign != alignment || forceAlign) && alignment <= QDeclarativeTextInput::AlignHCenter) { // justify not supported QDeclarativeTextInput::HAlignment oldEffectiveHAlign = q->effectiveHAlign(); hAlign = alignment; - return true; emit q->horizontalAlignmentChanged(alignment); if (oldEffectiveHAlign != q->effectiveHAlign()) emit q->effectiveHorizontalAlignmentChanged(); + return true; } return false; } diff --git a/src/declarative/qml/qdeclarativescriptparser.cpp b/src/declarative/qml/qdeclarativescriptparser.cpp index b604706..d9e3ebf 100644 --- a/src/declarative/qml/qdeclarativescriptparser.cpp +++ b/src/declarative/qml/qdeclarativescriptparser.cpp @@ -940,7 +940,7 @@ QDeclarativeParser::Object::ScriptBlock::Pragmas QDeclarativeScriptParser::extra if (l.currentLineNo() == startLine) return rv; - if (pragmaValue == QLatin1String("library")) { + if (pragmaValue == library) { rv |= QDeclarativeParser::Object::ScriptBlock::Shared; replaceWithSpace(script, startOffset, endOffset - startOffset); } else { diff --git a/src/declarative/qml/qdeclarativetypenamescriptclass.cpp b/src/declarative/qml/qdeclarativetypenamescriptclass.cpp index d3e2025..0314a7a 100644 --- a/src/declarative/qml/qdeclarativetypenamescriptclass.cpp +++ b/src/declarative/qml/qdeclarativetypenamescriptclass.cpp @@ -158,7 +158,7 @@ void QDeclarativeTypeNameScriptClass::setProperty(Object *o, const Identifier &n Q_ASSERT(!type); QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); - ep->objectClass->setProperty(((TypeNameData *)o)->object, n, v, context()); + ep->objectClass->setProperty(object, n, v, context()); } QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativeworkerscript.cpp b/src/declarative/qml/qdeclarativeworkerscript.cpp index f8d52b5..1ff0caa 100644 --- a/src/declarative/qml/qdeclarativeworkerscript.cpp +++ b/src/declarative/qml/qdeclarativeworkerscript.cpp @@ -313,7 +313,7 @@ void QDeclarativeWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url) QScriptContext *ctxt = QScriptDeclarativeClass::pushCleanContext(workerEngine); QScriptValue urlContext = workerEngine->newObject(); - urlContext.setData(QScriptValue(workerEngine, fileName)); + urlContext.setData(QScriptValue(workerEngine, url.toString())); ctxt->pushScope(urlContext); ctxt->pushScope(activation); ctxt->setActivationObject(activation); diff --git a/src/declarative/util/qdeclarativeview.cpp b/src/declarative/util/qdeclarativeview.cpp index c2e5efe..13880c2 100644 --- a/src/declarative/util/qdeclarativeview.cpp +++ b/src/declarative/util/qdeclarativeview.cpp @@ -293,6 +293,13 @@ void QDeclarativeViewPrivate::init() q->setFocusPolicy(Qt::StrongFocus); q->scene()->setStickyFocus(true); //### needed for correct focus handling + +#ifdef QDECLARATIVEVIEW_NOBACKGROUND + q->setAttribute(Qt::WA_OpaquePaintEvent); + q->setAttribute(Qt::WA_NoSystemBackground); + q->viewport()->setAttribute(Qt::WA_OpaquePaintEvent); + q->viewport()->setAttribute(Qt::WA_NoSystemBackground); +#endif } /*! diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 1caa325..b4d8d56 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -417,6 +417,11 @@ click focus to items underneath when being clicked on. This flag allows you create a non-focusable item that can be clicked on without changing the focus. \endomit + + \omitvalue ItemStopsFocusHandling \omit Same as + ItemStopsClickFocusPropagation, but also suppresses focus-out. This flag + allows you to completely take over focus handling. + This flag was introduced in Qt 4.7. */ /*! @@ -11551,6 +11556,9 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag) case QGraphicsItem::ItemStopsClickFocusPropagation: str = "ItemStopsClickFocusPropagation"; break; + case QGraphicsItem::ItemStopsFocusHandling: + str = "ItemStopsFocusHandling"; + break; } debug << str; return debug; diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index e59a7c9..67c9cd3 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -107,7 +107,8 @@ public: ItemIsPanel = 0x4000, ItemIsFocusScope = 0x8000, // internal ItemSendsScenePositionChanges = 0x10000, - ItemStopsClickFocusPropagation = 0x20000 + ItemStopsClickFocusPropagation = 0x20000, + ItemStopsFocusHandling = 0x40000 // NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag. }; Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 5c82116..90ff43f 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -559,7 +559,7 @@ public: quint32 dirtyChildrenBoundingRect : 1; // Packed 32 bits - quint32 flags : 18; + quint32 flags : 19; quint32 paintedViewBoundingRectsNeedRepaint : 1; quint32 dirtySceneTransform : 1; quint32 geometryChanged : 1; @@ -573,9 +573,9 @@ public: quint32 sceneTransformTranslateOnly : 1; quint32 notifyBoundingRectChanged : 1; quint32 notifyInvalidated : 1; - quint32 mouseSetsFocus : 1; // New 32 bits + quint32 mouseSetsFocus : 1; quint32 explicitActivate : 1; quint32 wantsActive : 1; quint32 holesInSiblingIndex : 1; @@ -586,7 +586,7 @@ public: quint32 mayHaveChildWithGraphicsEffect : 1; quint32 isDeclarativeItem : 1; quint32 sendParentChangeNotification : 1; - quint32 padding : 22; + quint32 padding : 21; // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index df68b1d..85a4e16 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1320,8 +1320,10 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou // Set focus on the topmost enabled item that can take focus. bool setFocus = false; + foreach (QGraphicsItem *item, cachedItemsUnderMouse) { - if (item->isBlockedByModalPanel()) { + if (item->isBlockedByModalPanel() + || (item->d_ptr->flags & QGraphicsItem::ItemStopsFocusHandling)) { // Make sure we don't clear focus. setFocus = true; break; @@ -1334,10 +1336,10 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou break; } } - if (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation) - break; if (item->isPanel()) break; + if (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation) + break; } // Check for scene modality. @@ -5930,6 +5932,7 @@ bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEve // Set focus on the topmost enabled item that can take focus. bool setFocus = false; + foreach (QGraphicsItem *item, cachedItemsUnderMouse) { if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) { if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) { @@ -5943,6 +5946,11 @@ bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEve break; if (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation) break; + if (item->d_ptr->flags & QGraphicsItem::ItemStopsFocusHandling) { + // Make sure we don't clear focus. + setFocus = true; + break; + } } // If nobody could take focus, clear it. @@ -5975,7 +5983,8 @@ bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEve } if (item && item->isPanel()) break; - if (item && (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation)) + if (item && (item->d_ptr->flags + & (QGraphicsItem::ItemStopsClickFocusPropagation | QGraphicsItem::ItemStopsFocusHandling))) break; } diff --git a/src/gui/image/qpixmap_s60.cpp b/src/gui/image/qpixmap_s60.cpp index fbdebf3..32d8dd7 100644 --- a/src/gui/image/qpixmap_s60.cpp +++ b/src/gui/image/qpixmap_s60.cpp @@ -601,6 +601,9 @@ bool QS60PixmapData::scroll(int dx, int dy, const QRect &rect) return res; } +Q_GUI_EXPORT int qt_defaultDpiX(); +Q_GUI_EXPORT int qt_defaultDpiY(); + int QS60PixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const { if (!cfbsBitmap) @@ -611,28 +614,18 @@ int QS60PixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const return cfbsBitmap->SizeInPixels().iWidth; case QPaintDevice::PdmHeight: return cfbsBitmap->SizeInPixels().iHeight; - case QPaintDevice::PdmWidthMM: { - TInt twips = cfbsBitmap->SizeInTwips().iWidth; - return (int)(twips * (25.4/KTwipsPerInch)); - } - case QPaintDevice::PdmHeightMM: { - TInt twips = cfbsBitmap->SizeInTwips().iHeight; - return (int)(twips * (25.4/KTwipsPerInch)); - } + case QPaintDevice::PdmWidthMM: + return qRound(cfbsBitmap->SizeInPixels().iWidth * 25.4 / qt_defaultDpiX()); + case QPaintDevice::PdmHeightMM: + return qRound(cfbsBitmap->SizeInPixels().iHeight * 25.4 / qt_defaultDpiY()); case QPaintDevice::PdmNumColors: return TDisplayModeUtils::NumDisplayModeColors(cfbsBitmap->DisplayMode()); case QPaintDevice::PdmDpiX: - case QPaintDevice::PdmPhysicalDpiX: { - TReal inches = cfbsBitmap->SizeInTwips().iWidth / (TReal)KTwipsPerInch; - TInt pixels = cfbsBitmap->SizeInPixels().iWidth; - return pixels / inches; - } + case QPaintDevice::PdmPhysicalDpiX: + return qt_defaultDpiX(); case QPaintDevice::PdmDpiY: - case QPaintDevice::PdmPhysicalDpiY: { - TReal inches = cfbsBitmap->SizeInTwips().iHeight / (TReal)KTwipsPerInch; - TInt pixels = cfbsBitmap->SizeInPixels().iHeight; - return pixels / inches; - } + case QPaintDevice::PdmPhysicalDpiY: + return qt_defaultDpiY(); case QPaintDevice::PdmDepth: return TDisplayModeUtils::NumDisplayModeBitsPerPixel(cfbsBitmap->DisplayMode()); default: diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 43b9b01..2b10d63 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -1132,7 +1132,8 @@ void QSymbianControl::Draw(const TRect& controlRect) const // Do nothing break; case QWExtra::Blit: - if (qwidget->d_func()->isOpaque) + case QWExtra::BlitWriteAlpha: + if (qwidget->d_func()->isOpaque || nativePaintMode == QWExtra::BlitWriteAlpha) gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha); gc.BitBlt(controlRect.iTl, bitmap, backingStoreRect); break; diff --git a/src/gui/kernel/qclipboard_win.cpp b/src/gui/kernel/qclipboard_win.cpp index 52b9663..ea41165 100644 --- a/src/gui/kernel/qclipboard_win.cpp +++ b/src/gui/kernel/qclipboard_win.cpp @@ -52,6 +52,7 @@ #include "qt_windows.h" #include "qdnd_p.h" #include <private/qwidget_p.h> +#include <private/qsystemlibrary_p.h> QT_BEGIN_NAMESPACE @@ -70,6 +71,9 @@ void QtCeFlushClipboard(); #endif +typedef BOOL (WINAPI *PtrIsHungAppWindow)(HWND); + +static PtrIsHungAppWindow ptrIsHungAppWindow = 0; class QClipboardWatcher : public QInternalMimeData { public: @@ -327,9 +331,16 @@ bool QClipboard::event(QEvent *e) d->releaseIData(); propagate = true; } - if (propagate && d->nextClipboardViewer) { - SendMessage(d->nextClipboardViewer, m->message, m->wParam, m->lParam); + if (ptrIsHungAppWindow == 0) { + QSystemLibrary library(QLatin1String("User32")); + ptrIsHungAppWindow = (PtrIsHungAppWindow)library.resolve("IsHungAppWindow"); + } + if (ptrIsHungAppWindow && ptrIsHungAppWindow(d->nextClipboardViewer)) { + qWarning("%s: Cowardly refusing to send clipboard message to hung application...", Q_FUNC_INFO); + } else { + SendMessage(d->nextClipboardViewer, m->message, m->wParam, m->lParam); + } } return true; diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 5235dc4..13e2349 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -315,6 +315,11 @@ struct QWExtra { */ ZeroFill, + /** + * Blit backing store, propagating alpha channel into the framebuffer. + */ + BlitWriteAlpha, + Default = Blit }; diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 62d09fe..b65ae4d 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -805,9 +805,14 @@ void QWidgetPrivate::s60UpdateIsOpaque() { Q_Q(QWidget); - if (!q->testAttribute(Qt::WA_WState_Created) || !q->testAttribute(Qt::WA_TranslucentBackground)) + if (!q->testAttribute(Qt::WA_WState_Created)) return; + const bool writeAlpha = extraData()->nativePaintMode == QWExtra::BlitWriteAlpha; + if (!q->testAttribute(Qt::WA_TranslucentBackground) && !writeAlpha) + return; + const bool requireAlphaChannel = !isOpaque || writeAlpha; + createTLExtra(); RWindow *const window = static_cast<RWindow *>(q->effectiveWinId()->DrawableWindow()); @@ -819,12 +824,11 @@ void QWidgetPrivate::s60UpdateIsOpaque() return; } #endif - if (!isOpaque) { + if (requireAlphaChannel) { const TDisplayMode displayMode = static_cast<TDisplayMode>(window->SetRequiredDisplayMode(EColor16MA)); if (window->SetTransparencyAlphaChannel() == KErrNone) { window->SetBackgroundColor(TRgb(255, 255, 255, 0)); extra->topextra->nativeWindowTransparencyEnabled = 1; - if (extra->topextra->backingStore.data() && ( QApplicationPrivate::graphics_system_name == QLatin1String("openvg") || QApplicationPrivate::graphics_system_name == QLatin1String("opengl"))) { diff --git a/src/gui/painting/qgraphicssystem_runtime.cpp b/src/gui/painting/qgraphicssystem_runtime.cpp index 5841d40..33652ee 100644 --- a/src/gui/painting/qgraphicssystem_runtime.cpp +++ b/src/gui/painting/qgraphicssystem_runtime.cpp @@ -394,7 +394,10 @@ void QRuntimeGraphicsSystem::setGraphicsSystem(const QString &name) if(m_windowSurfaceDestroyPolicy == DestroyAfterFirstFlush) proxy->m_pendingWindowSurface.reset(proxy->m_windowSurface.take()); - proxy->m_windowSurface.reset(m_graphicsSystem->createWindowSurface(widget)); + QWindowSurface *newWindowSurface = m_graphicsSystem->createWindowSurface(widget); + newWindowSurface->setGeometry(proxy->geometry()); + + proxy->m_windowSurface.reset(newWindowSurface); qt_widget_private(widget)->invalidateBuffer(widget->rect()); } diff --git a/src/gui/painting/qwindowsurface_s60.cpp b/src/gui/painting/qwindowsurface_s60.cpp index 9f371a8..cb53ea0 100644 --- a/src/gui/painting/qwindowsurface_s60.cpp +++ b/src/gui/painting/qwindowsurface_s60.cpp @@ -63,7 +63,6 @@ struct QS60WindowSurfacePrivate TDisplayMode displayMode(bool opaque) { - TDisplayMode mode = S60->screenDevice()->DisplayMode(); if (opaque) { mode = EColor16MU; @@ -76,10 +75,18 @@ TDisplayMode displayMode(bool opaque) return mode; } +bool blitWriteAlpha(QWidgetPrivate *widgetPrivate) +{ + QWExtra *extra = widgetPrivate->extraData(); + return extra ? extra->nativePaintMode == QWExtra::BlitWriteAlpha : false; +} + QS60WindowSurface::QS60WindowSurface(QWidget* widget) : QWindowSurface(widget), d_ptr(new QS60WindowSurfacePrivate) { - TDisplayMode mode = displayMode(qt_widget_private(widget)->isOpaque); + QWidgetPrivate *widgetPrivate = qt_widget_private(widget); + const bool opaque = widgetPrivate->isOpaque && !blitWriteAlpha(widgetPrivate); + TDisplayMode mode = displayMode(opaque); // 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 qt_symbian_throwIfError( bitmap->Create( TSize(0, 0), mode ) ); @@ -123,7 +130,8 @@ void QS60WindowSurface::beginPaint(const QRegion &rgn) S60->wsSession().Finish(); #endif - if (!qt_widget_private(window())->isOpaque) { + QWidgetPrivate *windowPrivate = qt_widget_private(window()); + if (!windowPrivate->isOpaque || blitWriteAlpha(windowPrivate)) { QS60PixmapData *pixmapData = static_cast<QS60PixmapData *>(d_ptr->device.data_ptr().data()); TDisplayMode mode = displayMode(false); @@ -132,12 +140,14 @@ void QS60WindowSurface::beginPaint(const QRegion &rgn) pixmapData->beginDataAccess(); - QPainter p(&pixmapData->image); - p.setCompositionMode(QPainter::CompositionMode_Source); - const QVector<QRect> rects = rgn.rects(); - const QColor blank = Qt::transparent; - for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) { - p.fillRect(*it, blank); + if (!windowPrivate->isOpaque) { + QPainter p(&pixmapData->image); + p.setCompositionMode(QPainter::CompositionMode_Source); + const QVector<QRect> rects = rgn.rects(); + const QColor blank = Qt::transparent; + for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) { + p.fillRect(*it, blank); + } } pixmapData->endDataAccess(); diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp index 1ff195d..e46c826 100644 --- a/src/gui/styles/qs60style_s60.cpp +++ b/src/gui/styles/qs60style_s60.cpp @@ -639,13 +639,14 @@ QPixmap QS60StyleModeSpecifics::fromFbsBitmap(CFbsBitmap *icon, CFbsBitmap *mask QPixmap pixmap; QScopedPointer<QPixmapData> pd(QPixmapData::create(0, 0, QPixmapData::PixmapType)); - bool nativeMaskSupported = (pd->toNativeType(QPixmapData::VolatileImage) != 0); - if (mask && nativeMaskSupported) { - // Efficient path, less copying and conversion. + if (mask) { + // Try the efficient path with less copying and conversion. QVolatileImage img(icon, mask); pd->fromNativeType(&img, QPixmapData::VolatileImage); - pixmap = QPixmap(pd.take()); - } else { + if (!pd->isNull()) + pixmap = QPixmap(pd.take()); + } + if (pixmap.isNull()) { // Potentially more expensive path. pd->fromNativeType(icon, QPixmapData::FbsBitmap); pixmap = QPixmap(pd.take()); diff --git a/src/opengl/qgl_egl.cpp b/src/opengl/qgl_egl.cpp index 674d80d..d6b2d3b 100644 --- a/src/opengl/qgl_egl.cpp +++ b/src/opengl/qgl_egl.cpp @@ -39,6 +39,7 @@ ** ****************************************************************************/ +#include <QtCore/qdebug.h> #include <QtOpenGL/qgl.h> #include <QtOpenGL/qglpixelbuffer.h> #include "qgl_p.h" @@ -195,6 +196,7 @@ void QGLContext::makeCurrent() // PowerVR MBX/SGX chips needs to clear all buffers when starting to render // a new frame, otherwise there will be a performance penalty to pay for // each frame. + qDebug() << "Found SGX/MBX driver, enabling FullClearOnEveryFrame"; d->workaround_needsFullClearOnEveryFrame = true; // Older PowerVR SGX drivers (like the one in the N900) have a @@ -202,10 +204,31 @@ void QGLContext::makeCurrent() // or GL_ALPHA texture bound to an FBO. The only way to // identify that driver is to check the EGL version number for it. const char *egl_version = eglQueryString(d->eglContext->display(), EGL_VERSION); - if (egl_version && strstr(egl_version, "1.3")) + + if (egl_version && strstr(egl_version, "1.3")) { + qDebug() << "Found v1.3 driver, enabling brokenFBOReadBack"; d->workaround_brokenFBOReadBack = true; - else if (egl_version && strstr(egl_version, "1.4")) + } else if (egl_version && strstr(egl_version, "1.4")) { + qDebug() << "Found v1.4 driver, enabling brokenTexSubImage"; d->workaround_brokenTexSubImage = true; + + // this is a bit complicated; 1.4 version SGX drivers from + // Nokia have fixed the brokenFBOReadBack problem, but + // official drivers from TI haven't, meaning that things + // like the beagleboard are broken unless we hack around it + // - but at the same time, we want to not reduce performance + // by not enabling this elsewhere. + // + // so, let's check for a Nokia-specific addon, and only + // enable if it isn't present. + // (see MeeGo bug #5616) + if (!QEgl::hasExtension("EGL_NOK_image_shared")) { + // no Nokia extension, this is probably a standard SGX + // driver, so enable the workaround + qDebug() << "Found non-Nokia v1.4 driver, enabling brokenFBOReadBack"; + d->workaround_brokenFBOReadBack = true; + } + } } } } diff --git a/src/opengl/qgl_symbian.cpp b/src/opengl/qgl_symbian.cpp index 2978514..78624a2 100644 --- a/src/opengl/qgl_symbian.cpp +++ b/src/opengl/qgl_symbian.cpp @@ -41,9 +41,7 @@ #include "qgl.h" -#include <coemain.h> -#include <coecntrl.h> -#include <w32std.h> +#include <fbs.h> #include <private/qt_s60_p.h> #include <private/qpixmap_s60_p.h> #include <private/qimagepixmapcleanuphooks_p.h> @@ -72,6 +70,8 @@ QT_BEGIN_NAMESPACE #endif #endif +extern int qt_gl_pixmap_serial; + /* QGLTemporaryContext implementation */ @@ -361,117 +361,61 @@ void QGLWidgetPrivate::recreateEglSurface() eglSurfaceWindowId = currentId; } -/* - * Symbian specific QGLPixmapData functions - */ - -static CFbsBitmap* createBlitCopy(CFbsBitmap* bitmap) +static inline bool knownGoodFormat(QImage::Format format) { - CFbsBitmap *copy = q_check_ptr(new CFbsBitmap); - if (!copy) - return 0; - - if (copy->Create(bitmap->SizeInPixels(), bitmap->DisplayMode()) != KErrNone) { - delete copy; - copy = 0; - - return 0; + switch (format) { + case QImage::Format_RGB16: // EColor64K + case QImage::Format_RGB32: // EColor16MU + case QImage::Format_ARGB32_Premultiplied: // EColor16MAP + return true; + default: + return false; } - - CFbsBitmapDevice* bitmapDevice = 0; - CFbsBitGc *bitmapGc = 0; - QT_TRAP_THROWING(bitmapDevice = CFbsBitmapDevice::NewL(copy)); - QT_TRAP_THROWING(bitmapGc = CFbsBitGc::NewL()); - bitmapGc->Activate(bitmapDevice); - - bitmapGc->BitBlt(TPoint(), bitmap); - - delete bitmapGc; - delete bitmapDevice; - - return copy; } void QGLPixmapData::fromNativeType(void* pixmap, NativeType type) { if (type == QPixmapData::FbsBitmap) { - CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap*>(pixmap); - - bool deleteSourceBitmap = false; -#ifdef Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE - - // Rasterize extended bitmaps - - TUid extendedBitmapType = bitmap->ExtendedBitmapType(); - if (extendedBitmapType != KNullUid) { - bitmap = createBlitCopy(bitmap); - deleteSourceBitmap = true; - } -#endif - - if (bitmap->IsCompressedInRAM()) { - bitmap = createBlitCopy(bitmap); - deleteSourceBitmap = true; + CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap *>(pixmap); + QSize size(bitmap->SizeInPixels().iWidth, bitmap->SizeInPixels().iHeight); + if (size.width() == w && size.height() == h) + setSerialNumber(++qt_gl_pixmap_serial); + resize(size.width(), size.height()); + m_source = QVolatileImage(bitmap); + if (pixelType() == BitmapType) { + m_source.ensureFormat(QImage::Format_MonoLSB); + } else if (!knownGoodFormat(m_source.format())) { + m_source.beginDataAccess(); + QImage::Format format = idealFormat(m_source.imageRef(), Qt::AutoColor); + m_source.endDataAccess(true); + m_source.ensureFormat(format); } - - TDisplayMode displayMode = bitmap->DisplayMode(); - QImage::Format format = qt_TDisplayMode2Format(displayMode); - - TSize size = bitmap->SizeInPixels(); - int bytesPerLine = bitmap->ScanLineLength(size.iWidth, displayMode); - - bitmap->BeginDataAccess(); - uchar *bytes = (uchar*)bitmap->DataAddress(); - QImage img = QImage(bytes, size.iWidth, size.iHeight, bytesPerLine, format); - img = img.copy(); - bitmap->EndDataAccess(); - - if (displayMode == EGray2) { - //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid - //So invert mono bitmaps so that masks work correctly. - img.invertPixels(); - } else if (displayMode == EColor16M) { - img = img.rgbSwapped(); // EColor16M is BGR - } - - fromImage(img, Qt::AutoColor); - - if (deleteSourceBitmap) - delete bitmap; + m_hasAlpha = m_source.hasAlphaChannel(); + m_hasFillColor = false; + m_dirty = true; + + } else if (type == QPixmapData::VolatileImage && pixmap) { + // Support QS60Style in more efficient skin graphics retrieval. + QVolatileImage *img = static_cast<QVolatileImage *>(pixmap); + if (img->width() == w && img->height() == h) + setSerialNumber(++qt_gl_pixmap_serial); + resize(img->width(), img->height()); + m_source = *img; + m_hasAlpha = m_source.hasAlphaChannel(); + m_hasFillColor = false; + m_dirty = true; } } void* QGLPixmapData::toNativeType(NativeType type) { if (type == QPixmapData::FbsBitmap) { - CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap); - - if (bitmap) { - QImage image = toImage(); - - TDisplayMode displayMode(EColor16MU); - if (image.format()==QImage::Format_ARGB32_Premultiplied) - displayMode = EColor16MAP; - - if (bitmap->Create(TSize(image.width(), image.height()), - displayMode) == KErrNone) { - const uchar *sptr = const_cast<const QImage&>(image).bits(); - bitmap->BeginDataAccess(); - - uchar *dptr = (uchar*)bitmap->DataAddress(); - Mem::Copy(dptr, sptr, image.byteCount()); - - bitmap->EndDataAccess(); - } else { - delete bitmap; - bitmap = 0; - } - } - - return reinterpret_cast<void*>(bitmap); + if (m_source.isNull()) + m_source = QVolatileImage(w, h, QImage::Format_ARGB32_Premultiplied); + return m_source.duplicateNativeImage(); } + return 0; } QT_END_NAMESPACE - diff --git a/src/opengl/qpixmapdata_gl_p.h b/src/opengl/qpixmapdata_gl_p.h index 55cc29d..41740dd 100644 --- a/src/opengl/qpixmapdata_gl_p.h +++ b/src/opengl/qpixmapdata_gl_p.h @@ -59,6 +59,10 @@ #include "private/qpixmapdata_p.h" #include "private/qglpaintdevice_p.h" +#ifdef Q_OS_SYMBIAN +#include "private/qvolatileimage_p.h" +#endif + QT_BEGIN_NAMESPACE class QPaintEngine; @@ -153,6 +157,7 @@ public: #endif #ifdef Q_OS_SYMBIAN + QImage::Format idealFormat(QImage &image, Qt::ImageConversionFlags flags); void* toNativeType(NativeType type); void fromNativeType(void* pixmap, NativeType type); #endif @@ -184,7 +189,11 @@ private: mutable QGLFramebufferObject *m_renderFbo; mutable QPaintEngine *m_engine; mutable QGLContext *m_ctx; +#ifdef Q_OS_SYMBIAN + mutable QVolatileImage m_source; +#else mutable QImage m_source; +#endif mutable QGLTexture m_texture; // the texture is not in sync with the source image diff --git a/src/opengl/qpixmapdata_poolgl.cpp b/src/opengl/qpixmapdata_poolgl.cpp index f1220b1..64de29e 100644 --- a/src/opengl/qpixmapdata_poolgl.cpp +++ b/src/opengl/qpixmapdata_poolgl.cpp @@ -247,7 +247,7 @@ void QGLPixmapGLPaintDevice::setPixmapData(QGLPixmapData* d) data = d; } -static int qt_gl_pixmap_serial = 0; +int qt_gl_pixmap_serial = 0; QGLPixmapData::QGLPixmapData(PixelType type) : QPixmapData(type, OpenGLClass) @@ -330,7 +330,7 @@ void QGLPixmapData::resize(int width, int height) destroyTexture(); - m_source = QImage(); + m_source = QVolatileImage(); m_dirty = isValid(); setSerialNumber(++qt_gl_pixmap_serial); } @@ -353,6 +353,11 @@ void QGLPixmapData::ensureCreated() const #endif const GLenum target = GL_TEXTURE_2D; + GLenum type = GL_UNSIGNED_BYTE; + // Avoid conversion when pixmap is created from CFbsBitmap of EColor64K. + if (!m_source.isNull() && m_source.format() == QImage::Format_RGB16) + type = GL_UNSIGNED_SHORT_5_6_5; + m_texture.options &= ~QGLContext::MemoryManagedBindOption; if (!m_texture.id) { @@ -361,7 +366,7 @@ void QGLPixmapData::ensureCreated() const 0, internal_format, w, h, external_format, - GL_UNSIGNED_BYTE, + type, const_cast<QGLPixmapData*>(this)); if (!m_texture.id) { failedToAlloc = true; @@ -378,21 +383,35 @@ void QGLPixmapData::ensureCreated() const if (!m_source.isNull() && m_texture.id) { if (external_format == GL_RGB) { - const QImage tx = m_source.convertToFormat(QImage::Format_RGB888).mirrored(false, true); + m_source.beginDataAccess(); + QImage tx; + if (type == GL_UNSIGNED_BYTE) + tx = m_source.imageRef().convertToFormat(QImage::Format_RGB888).mirrored(false, true); + else if (type == GL_UNSIGNED_SHORT_5_6_5) + tx = m_source.imageRef().mirrored(false, true); + m_source.endDataAccess(true); glBindTexture(target, m_texture.id); - glTexSubImage2D(target, 0, 0, 0, w, h, external_format, - GL_UNSIGNED_BYTE, tx.bits()); + if (!tx.isNull()) + glTexSubImage2D(target, 0, 0, 0, w, h, external_format, + type, tx.constBits()); + else + qWarning("QGLPixmapData: Failed to create GL_RGB image of size %dx%d", w, h); } else { // do byte swizzling ARGB -> RGBA - const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, external_format); + m_source.beginDataAccess(); + const QImage tx = ctx->d_func()->convertToGLFormat(m_source.imageRef(), true, external_format); + m_source.endDataAccess(true); glBindTexture(target, m_texture.id); - glTexSubImage2D(target, 0, 0, 0, w, h, external_format, - GL_UNSIGNED_BYTE, tx.bits()); + if (!tx.isNull()) + glTexSubImage2D(target, 0, 0, 0, w, h, external_format, + type, tx.constBits()); + else + qWarning("QGLPixmapData: Failed to create GL_RGBA image of size %dx%d", w, h); } if (useFramebufferObjects()) - m_source = QImage(); + m_source = QVolatileImage(); } } @@ -437,7 +456,7 @@ bool QGLPixmapData::fromFile(const QString &filename, const char *format, is_null = false; d = 32; m_hasAlpha = alpha; - m_source = QImage(); + m_source = QVolatileImage(); m_dirty = isValid(); return true; } @@ -469,7 +488,7 @@ bool QGLPixmapData::fromData(const uchar *buffer, uint len, const char *format, is_null = false; d = 32; m_hasAlpha = alpha; - m_source = QImage(); + m_source = QVolatileImage(); m_dirty = isValid(); return true; } @@ -487,9 +506,20 @@ bool QGLPixmapData::fromData(const uchar *buffer, uint len, const char *format, return !isNull(); } -/*! - out-of-place conversion (inPlace == false) will always detach() - */ +QImage::Format QGLPixmapData::idealFormat(QImage &image, Qt::ImageConversionFlags flags) +{ + QImage::Format format = QImage::Format_RGB32; + if (qApp->desktop()->depth() == 16) + format = QImage::Format_RGB16; + + if (image.hasAlphaChannel() + && ((flags & Qt::NoOpaqueDetection) + || const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels())) + format = QImage::Format_ARGB32_Premultiplied; + + return format; +} + void QGLPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags flags, bool inPlace) { if (image.size() == QSize(w, h)) @@ -498,26 +528,25 @@ void QGLPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags resize(image.width(), image.height()); if (pixelType() == BitmapType) { - m_source = image.convertToFormat(QImage::Format_MonoLSB); + QImage convertedImage = image.convertToFormat(QImage::Format_MonoLSB); + if (image.format() == QImage::Format_MonoLSB) + convertedImage.detach(); - } else { - QImage::Format format = QImage::Format_RGB32; - if (qApp->desktop()->depth() == 16) - format = QImage::Format_RGB16; + m_source = QVolatileImage(convertedImage); - if (image.hasAlphaChannel() - && ((flags & Qt::NoOpaqueDetection) - || const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels())) - format = QImage::Format_ARGB32_Premultiplied; + } else { + QImage::Format format = idealFormat(image, flags); if (inPlace && image.data_ptr()->convertInPlace(format, flags)) { - m_source = image; + m_source = QVolatileImage(image); } else { - m_source = image.convertToFormat(format); + QImage convertedImage = image.convertToFormat(format); // convertToFormat won't detach the image if format stays the same. if (image.format() == format) - m_source.detach(); + convertedImage.detach(); + + m_source = QVolatileImage(convertedImage); } } @@ -596,16 +625,13 @@ void QGLPixmapData::fill(const QColor &color) } if (useFramebufferObjects()) { - m_source = QImage(); + m_source = QVolatileImage(); m_hasFillColor = true; m_fillColor = color; } else { + forceToImage(); - if (m_source.isNull()) { - m_fillColor = color; - m_hasFillColor = true; - - } else if (m_source.depth() == 32) { + if (m_source.depth() == 32) { m_source.fill(PREMUL(color.rgba())); } else if (m_source.depth() == 1) { @@ -656,13 +682,15 @@ QImage QGLPixmapData::toImage() const if (m_renderFbo) { copyBackFromRenderFbo(true); } else if (!m_source.isNull()) { - QImageData *data = const_cast<QImage &>(m_source).data_ptr(); - if (data->paintEngine && data->paintEngine->isActive() - && data->paintEngine->paintDevice() == &m_source) - { - return m_source.copy(); + // QVolatileImage::toImage() will make a copy always so no check + // for active painting is needed. + QImage img = m_source.toImage(); + if (img.format() == QImage::Format_MonoLSB) { + img.setColorCount(2); + img.setColor(0, QColor(Qt::color0).rgba()); + img.setColor(1, QColor(Qt::color1).rgba()); } - return m_source; + return img; } else if (m_dirty || m_hasFillColor) { return fillImage(m_fillColor); } else { @@ -802,7 +830,7 @@ GLuint QGLPixmapData::bind(bool copyBack) const if (m_hasFillColor) { if (!useFramebufferObjects()) { - m_source = QImage(w, h, QImage::Format_ARGB32_Premultiplied); + m_source = QVolatileImage(w, h, QImage::Format_ARGB32_Premultiplied); m_source.fill(PREMUL(m_fillColor.rgba())); } @@ -811,7 +839,7 @@ GLuint QGLPixmapData::bind(bool copyBack) const GLenum format = qt_gl_preferredTextureFormat(); QImage tx(w, h, QImage::Format_ARGB32_Premultiplied); tx.fill(qt_gl_convertToGLFormat(m_fillColor.rgba(), format)); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, tx.bits()); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, tx.constBits()); } return id; @@ -888,8 +916,12 @@ void QGLPixmapData::forceToImage() if (!isValid()) return; - if (m_source.isNull()) - m_source = QImage(w, h, QImage::Format_ARGB32_Premultiplied); + if (m_source.isNull()) { + QImage::Format format = QImage::Format_ARGB32_Premultiplied; + if (pixelType() == BitmapType) + format = QImage::Format_MonoLSB; + m_source = QVolatileImage(w, h, format); + } m_dirty = true; } diff --git a/src/openvg/qvg_symbian.cpp b/src/openvg/qvg_symbian.cpp index 2924d41..0d2ed9e 100644 --- a/src/openvg/qvg_symbian.cpp +++ b/src/openvg/qvg_symbian.cpp @@ -195,14 +195,16 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type) if (!conversionLessFormat(source.format())) { // Here we may need to copy if the formats do not match. // (e.g. for display modes other than EColor16MAP and EColor16MU) - source.ensureFormat(idealFormat(&source.imageRef(), Qt::AutoColor)); + source.beginDataAccess(); + QImage::Format format = idealFormat(&source.imageRef(), Qt::AutoColor); + source.endDataAccess(true); + source.ensureFormat(format); } recreate = true; } else if (type == QPixmapData::VolatileImage && pixmap) { QVolatileImage *img = static_cast<QVolatileImage *>(pixmap); resize(img->width(), img->height()); source = *img; - source.ensureFormat(idealFormat(&source.imageRef(), Qt::AutoColor)); recreate = true; } else if (type == QPixmapData::NativeImageHandleProvider && pixmap) { destroyImages(); @@ -282,8 +284,6 @@ void* QVGPixmapData::toNativeType(NativeType type) } // Just duplicate the bitmap handle, no data copying happens. return source.duplicateNativeImage(); - } else if (type == QPixmapData::VolatileImage) { - return &source; } return 0; } diff --git a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp index 13eab7f..c904c3c 100644 --- a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp +++ b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp @@ -59,10 +59,16 @@ #include "qmeegographicssystem.h" #include "qmeegoextensions.h" +#include <QTimer> + bool QMeeGoGraphicsSystem::surfaceWasCreated = false; QHash <Qt::HANDLE, QPixmap*> QMeeGoGraphicsSystem::liveTexturePixmaps; +QList<QMeeGoSwitchCallback> QMeeGoGraphicsSystem::switchCallbacks; + +QMeeGoGraphicsSystem::SwitchPolicy QMeeGoGraphicsSystem::switchPolicy = QMeeGoGraphicsSystem::AutomaticSwitch; + QMeeGoGraphicsSystem::QMeeGoGraphicsSystem() { qDebug("Using the meego graphics system"); @@ -74,6 +80,115 @@ QMeeGoGraphicsSystem::~QMeeGoGraphicsSystem() qt_destroy_gl_share_widget(); } +class QMeeGoGraphicsSystemSwitchHandler : public QObject +{ + Q_OBJECT +public: + QMeeGoGraphicsSystemSwitchHandler(); + + void addWidget(QWidget *widget); + bool eventFilter(QObject *, QEvent *); + + void handleMapNotify(); + +private slots: + void removeWidget(QObject *object); + void switchToRaster(); + void switchToMeeGo(); + +private: + int visibleWidgets() const; + +private: + QList<QWidget *> m_widgets; +}; + +typedef bool(*QX11FilterFunction)(XEvent *event); +Q_GUI_EXPORT void qt_installX11EventFilter(QX11FilterFunction func); + +static bool x11EventFilter(XEvent *event); + +QMeeGoGraphicsSystemSwitchHandler::QMeeGoGraphicsSystemSwitchHandler() +{ + qt_installX11EventFilter(x11EventFilter); +} + +void QMeeGoGraphicsSystemSwitchHandler::addWidget(QWidget *widget) +{ + if (widget != qt_gl_share_widget() && !m_widgets.contains(widget)) { + widget->installEventFilter(this); + connect(widget, SIGNAL(destroyed(QObject *)), this, SLOT(removeWidget(QObject *))); + m_widgets << widget; + } +} + +void QMeeGoGraphicsSystemSwitchHandler::handleMapNotify() +{ + if (m_widgets.isEmpty() && QMeeGoGraphicsSystem::switchPolicy == QMeeGoGraphicsSystem::AutomaticSwitch) + QTimer::singleShot(0, this, SLOT(switchToMeeGo())); +} + +void QMeeGoGraphicsSystemSwitchHandler::removeWidget(QObject *object) +{ + m_widgets.removeOne(static_cast<QWidget *>(object)); + if (m_widgets.isEmpty() && QMeeGoGraphicsSystem::switchPolicy == QMeeGoGraphicsSystem::AutomaticSwitch) + QTimer::singleShot(0, this, SLOT(switchToRaster())); +} + +void QMeeGoGraphicsSystemSwitchHandler::switchToRaster() +{ + QMeeGoGraphicsSystem::switchToRaster(); +} + +void QMeeGoGraphicsSystemSwitchHandler::switchToMeeGo() +{ + QMeeGoGraphicsSystem::switchToMeeGo(); +} + +int QMeeGoGraphicsSystemSwitchHandler::visibleWidgets() const +{ + int count = 0; + for (int i = 0; i < m_widgets.size(); ++i) + count += m_widgets.at(i)->isVisible() && !(m_widgets.at(i)->windowState() & Qt::WindowMinimized); + return count; +} + +bool QMeeGoGraphicsSystemSwitchHandler::eventFilter(QObject *object, QEvent *event) +{ + if (event->type() == QEvent::WindowStateChange + && QMeeGoGraphicsSystem::switchPolicy == QMeeGoGraphicsSystem::AutomaticSwitch) + { + QWindowStateChangeEvent *change = static_cast<QWindowStateChangeEvent *>(event); + QWidget *widget = static_cast<QWidget *>(object); + + Qt::WindowStates current = widget->windowState(); + Qt::WindowStates old = change->oldState(); + + // did minimized flag change? + if ((current ^ old) & Qt::WindowMinimized) { + if (current & Qt::WindowMinimized) { + if (visibleWidgets() == 0) + QMeeGoGraphicsSystem::switchToRaster(); + } else { + if (visibleWidgets() == 1) + QMeeGoGraphicsSystem::switchToMeeGo(); + } + } + } + + // resume processing of event + return false; +} + +Q_GLOBAL_STATIC(QMeeGoGraphicsSystemSwitchHandler, switch_handler) + +bool x11EventFilter(XEvent *event) +{ + if (event->type == MapNotify) + switch_handler()->handleMapNotify(); + return false; +} + QWindowSurface* QMeeGoGraphicsSystem::createWindowSurface(QWidget *widget) const { QGLWidget *shareWidget = qt_gl_share_widget(); @@ -83,6 +198,9 @@ QWindowSurface* QMeeGoGraphicsSystem::createWindowSurface(QWidget *widget) const QGLShareContextScope ctx(shareWidget->context()); + if (QApplicationPrivate::instance()->graphics_system_name == QLatin1String("runtime")) + switch_handler()->addWidget(widget); + QMeeGoGraphicsSystem::surfaceWasCreated = true; QWindowSurface *surface = new QGLWindowSurface(widget); return surface; @@ -203,18 +321,7 @@ QPixmapData *QMeeGoGraphicsSystem::pixmapDataWithGLTexture(int w, int h) bool QMeeGoGraphicsSystem::meeGoRunning() { - if (! QApplicationPrivate::instance()) { - qWarning("Application not running just yet... hard to know what system running!"); - return false; - } - - QString name = QApplicationPrivate::instance()->graphics_system_name; - if (name == "runtime") { - QRuntimeGraphicsSystem *rsystem = (QRuntimeGraphicsSystem *) QApplicationPrivate::instance()->graphics_system; - name = rsystem->graphicsSystemName(); - } - - return (name == "meego"); + return runningGraphicsSystemName() == "meego"; } QPixmapData* QMeeGoGraphicsSystem::pixmapDataWithNewLiveTexture(int w, int h, QImage::Format format) @@ -259,6 +366,69 @@ void QMeeGoGraphicsSystem::destroyFenceSync(void *fenceSync) QMeeGoExtensions::eglDestroySyncKHR(QEgl::display(), fenceSync); } +QString QMeeGoGraphicsSystem::runningGraphicsSystemName() +{ + if (!QApplicationPrivate::instance()) { + qWarning("Querying graphics system but application not running yet!"); + return QString(); + } + + QString name = QApplicationPrivate::instance()->graphics_system_name; + if (name == QLatin1String("runtime")) { + QRuntimeGraphicsSystem *rsystem = (QRuntimeGraphicsSystem *) QApplicationPrivate::instance()->graphics_system; + name = rsystem->graphicsSystemName(); + } + + return name; +} + +void QMeeGoGraphicsSystem::switchToMeeGo() +{ + if (switchPolicy == NoSwitch || meeGoRunning()) + return; + + if (QApplicationPrivate::instance()->graphics_system_name != QLatin1String("runtime")) + qWarning("Can't switch to meego - switching only supported with 'runtime' graphics system."); + else { + triggerSwitchCallbacks(0, "meego"); + + QApplication *app = static_cast<QApplication *>(QCoreApplication::instance()); + app->setGraphicsSystem(QLatin1String("meego")); + + triggerSwitchCallbacks(1, "meego"); + } +} + +void QMeeGoGraphicsSystem::switchToRaster() +{ + if (switchPolicy == NoSwitch || runningGraphicsSystemName() == QLatin1String("raster")) + return; + + if (QApplicationPrivate::instance()->graphics_system_name != QLatin1String("runtime")) + qWarning("Can't switch to raster - switching only supported with 'runtime' graphics system."); + else { + triggerSwitchCallbacks(0, "raster"); + + QApplication *app = static_cast<QApplication *>(QCoreApplication::instance()); + app->setGraphicsSystem(QLatin1String("raster")); + + QMeeGoLivePixmapData::invalidateSurfaces(); + + triggerSwitchCallbacks(1, "raster"); + } +} + +void QMeeGoGraphicsSystem::registerSwitchCallback(QMeeGoSwitchCallback callback) +{ + switchCallbacks << callback; +} + +void QMeeGoGraphicsSystem::triggerSwitchCallbacks(int type, const char *name) +{ + for (int i = 0; i < switchCallbacks.size(); ++i) + switchCallbacks.at(i)(type, name); +} + /* C API */ int qt_meego_image_to_egl_shared_image(const QImage &image) @@ -340,3 +510,25 @@ void qt_meego_invalidate_live_surfaces(void) { return QMeeGoLivePixmapData::invalidateSurfaces(); } + +void qt_meego_switch_to_raster(void) +{ + QMeeGoGraphicsSystem::switchToRaster(); +} + +void qt_meego_switch_to_meego(void) +{ + QMeeGoGraphicsSystem::switchToMeeGo(); +} + +void qt_meego_register_switch_callback(QMeeGoSwitchCallback callback) +{ + QMeeGoGraphicsSystem::registerSwitchCallback(callback); +} + +void qt_meego_set_switch_policy(int policy) +{ + QMeeGoGraphicsSystem::switchPolicy = QMeeGoGraphicsSystem::SwitchPolicy(policy); +} + +#include "qmeegographicssystem.moc" diff --git a/src/plugins/graphicssystems/meego/qmeegographicssystem.h b/src/plugins/graphicssystems/meego/qmeegographicssystem.h index 27a4e7a..3528425 100644 --- a/src/plugins/graphicssystems/meego/qmeegographicssystem.h +++ b/src/plugins/graphicssystems/meego/qmeegographicssystem.h @@ -47,9 +47,13 @@ #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> +extern "C" typedef void (*QMeeGoSwitchCallback)(int type, const char *name); + class QMeeGoGraphicsSystem : public QGraphicsSystem { public: + enum SwitchPolicy { AutomaticSwitch, ManualSwitch, NoSwitch }; + QMeeGoGraphicsSystem(); ~QMeeGoGraphicsSystem(); @@ -76,13 +80,23 @@ public: static void* createFenceSync(); static void destroyFenceSync(void* fenceSync); + static void switchToRaster(); + static void switchToMeeGo(); + static QString runningGraphicsSystemName(); + + static void registerSwitchCallback(QMeeGoSwitchCallback callback); + + static SwitchPolicy switchPolicy; + private: static bool meeGoRunning(); static EGLSurface getSurfaceForLiveTexturePixmap(QPixmap *pixmap); static void destroySurfaceForLiveTexturePixmap(QPixmapData* pmd); + static void triggerSwitchCallbacks(int type, const char *name); static bool surfaceWasCreated; - static QHash <Qt::HANDLE, QPixmap*> liveTexturePixmaps; + static QHash<Qt::HANDLE, QPixmap*> liveTexturePixmaps; + static QList<QMeeGoSwitchCallback> switchCallbacks; }; /* C api */ @@ -95,7 +109,7 @@ extern "C" { Q_DECL_EXPORT bool qt_meego_destroy_egl_shared_image(Qt::HANDLE handle); Q_DECL_EXPORT void qt_meego_set_surface_fixed_size(int width, int height); Q_DECL_EXPORT void qt_meego_set_surface_scaling(int x, int y, int width, int height); - Q_DECL_EXPORT void qt_meego_set_translucent(bool translucent); + Q_DECL_EXPORT void qt_meego_set_translucent(bool translucent); Q_DECL_EXPORT QPixmapData* qt_meego_pixmapdata_with_new_live_texture(int w, int h, QImage::Format format); Q_DECL_EXPORT QPixmapData* qt_meego_pixmapdata_from_live_texture_handle(Qt::HANDLE handle); Q_DECL_EXPORT QImage* qt_meego_live_texture_lock(QPixmap *pixmap, void *fenceSync); @@ -104,6 +118,10 @@ extern "C" { Q_DECL_EXPORT void* qt_meego_create_fence_sync(void); Q_DECL_EXPORT void qt_meego_destroy_fence_sync(void* fs); Q_DECL_EXPORT void qt_meego_invalidate_live_surfaces(void); + Q_DECL_EXPORT void qt_meego_switch_to_raster(void); + Q_DECL_EXPORT void qt_meego_switch_to_meego(void); + Q_DECL_EXPORT void qt_meego_register_switch_callback(QMeeGoSwitchCallback callback); + Q_DECL_EXPORT void qt_meego_set_switch_policy(int policy); } #endif diff --git a/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.cpp b/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.cpp index 2a2a098..0970b89 100644 --- a/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.cpp +++ b/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.cpp @@ -219,7 +219,7 @@ QImage* QMeeGoLivePixmapData::lock(EGLSyncKHR fenceSync) return &lockedImage; } - lockedImage = QImage((uchar *) data, width(), height(), format); + lockedImage = QImage((uchar *) data, width(), height(), pitch, format); return &lockedImage; } diff --git a/src/s60installs/bwins/QtOpenGLu.def b/src/s60installs/bwins/QtOpenGLu.def index 87d1b56..f52932c 100644 --- a/src/s60installs/bwins/QtOpenGLu.def +++ b/src/s60installs/bwins/QtOpenGLu.def @@ -718,4 +718,5 @@ EXPORTS ?releaseCachedResources@QGLGraphicsSystem@@UAEXXZ @ 717 NONAME ; void QGLGraphicsSystem::releaseCachedResources(void) ?serialNumber@QGLTextureGlyphCache@@QBEHXZ @ 718 NONAME ; int QGLTextureGlyphCache::serialNumber(void) const ?forceToImage@QGLPixmapData@@QAEXXZ @ 719 NONAME ; void QGLPixmapData::forceToImage(void) + ?idealFormat@QGLPixmapData@@QAE?AW4Format@QImage@@AAV3@V?$QFlags@W4ImageConversionFlag@Qt@@@@@Z @ 720 NONAME ; enum QImage::Format QGLPixmapData::idealFormat(class QImage &, class QFlags<enum Qt::ImageConversionFlag>) diff --git a/src/s60installs/eabi/QtOpenGLu.def b/src/s60installs/eabi/QtOpenGLu.def index 4c5dca9..f7a7f71 100644 --- a/src/s60installs/eabi/QtOpenGLu.def +++ b/src/s60installs/eabi/QtOpenGLu.def @@ -720,4 +720,5 @@ EXPORTS _ZN13QGLPixmapData21detachTextureFromPoolEv @ 719 NONAME _ZN13QGLPixmapData9hibernateEv @ 720 NONAME _ZN17QGLGraphicsSystem22releaseCachedResourcesEv @ 721 NONAME + _ZN13QGLPixmapData11idealFormatER6QImage6QFlagsIN2Qt19ImageConversionFlagEE @ 722 NONAME diff --git a/src/s60installs/s60installs.pro b/src/s60installs/s60installs.pro index 1e5ce0f..76f1dda 100644 --- a/src/s60installs/s60installs.pro +++ b/src/s60installs/s60installs.pro @@ -58,7 +58,7 @@ symbian: { " \"$$pluginLocations/qts60plugin_5_0$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qts60plugin_5_0$${QT_LIBINFIX}.dll\"" \ " \"$$bearerPluginLocation/qsymbianbearer$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qsymbianbearer$${QT_LIBINFIX}.dll\"" \ "ENDIF" \ - " \"$$bearerStubZ\" - \"c:$$replace(QT_PLUGINS_BASE_DIR,/,\\)\\bearer\\qsymbianbearer$${QT_LIBINFIX}.qtplugin\" + " \"$$bearerStubZ\" - \"c:$$replace(QT_PLUGINS_BASE_DIR,/,\\)\\bearer\\qsymbianbearer$${QT_LIBINFIX}.qtplugin\"" } else { # No need to deploy plugins for older platform versions when building on Symbian3 or later qts60plugindeployment = \ |