diff options
Diffstat (limited to 'src/gui')
61 files changed, 1176 insertions, 390 deletions
diff --git a/src/gui/egl/qegl_symbian.cpp b/src/gui/egl/qegl_symbian.cpp index 6533d11..fabf9d1 100644 --- a/src/gui/egl/qegl_symbian.cpp +++ b/src/gui/egl/qegl_symbian.cpp @@ -42,6 +42,7 @@ #include <QtGui/qpaintdevice.h> #include <QtGui/qpixmap.h> #include <QtGui/qwidget.h> +#include <QtGui/private/qapplication_p.h> #include "qegl_p.h" #include "qeglcontext_p.h" @@ -73,10 +74,14 @@ void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev) return; int devType = dev->devType(); - if (devType == QInternal::Image) + if (devType == QInternal::Image) { setPixelFormat(static_cast<QImage *>(dev)->format()); - else - setPixelFormat(QImage::Format_RGB32); + } else { + QImage::Format format = QImage::Format_RGB32; + if (QApplicationPrivate::instance() && QApplicationPrivate::instance()->useTranslucentEGLSurfaces) + format = QImage::Format_ARGB32_Premultiplied; + setPixelFormat(format); + } } diff --git a/src/gui/embedded/qvfbhdr.h b/src/gui/embedded/qvfbhdr.h index 31704b3..84f82ac 100644 --- a/src/gui/embedded/qvfbhdr.h +++ b/src/gui/embedded/qvfbhdr.h @@ -53,36 +53,37 @@ QT_BEGIN_NAMESPACE QT_MODULE(Gui) #ifndef QT_QWS_TEMP_DIR -#define QT_QWS_TEMP_DIR "/tmp" +# define QT_QWS_TEMP_DIR QLatin1String("/tmp") #endif #ifdef QT_PRIVATE_QWS -#define QT_VFB_DATADIR(DISPLAY) QString("%1/qtembedded-%2-%3") \ - .arg(QT_QWS_TEMP_DIR).arg(getuid()).arg(DISPLAY) - +#define QT_VFB_DATADIR(DISPLAY) QString::fromLatin1("%1/qtembedded-%2-%3") \ + .arg(QT_QWS_TEMP_DIR).arg(getuid()).arg(DISPLAY) #define QT_VFB_MOUSE_PIPE(DISPLAY) QT_VFB_DATADIR(DISPLAY) \ - .append("/qtvfb_mouse") + .append(QLatin1String("/qtvfb_mouse")) #define QT_VFB_KEYBOARD_PIPE(DISPLAY) QT_VFB_DATADIR(DISPLAY) \ - .append("/qtvfb_keyboard") + .append(QLatin1String("/qtvfb_keyboard")) #define QT_VFB_MAP(DISPLAY) QT_VFB_DATADIR(DISPLAY) \ - .append("/qtvfb_map") + .append(QLatin1String("/qtvfb_map")) #define QT_VFB_SOUND_PIPE(DISPLAY) QT_VFB_DATADIR(DISPLAY) \ - .append("/qt_soundserver") + .append(QLatin1String("/qt_soundserver")) #define QTE_PIPE(DISPLAY) QT_VFB_DATADIR(DISPLAY) \ - .append("/QtEmbedded") + .append(QLatin1String("/QtEmbedded")) #define QTE_PIPE_QVFB(DISPLAY) QTE_PIPE(DISPLAY) #else -#define QT_VFB_DATADIR(DISPLAY) QString("%1/qtembedded-%2") \ - .arg(QT_QWS_TEMP_DIR).arg(DISPLAY) -#define QT_VFB_MOUSE_PIPE(DISPLAY) QString("/tmp/.qtvfb_mouse-%1").arg(DISPLAY) -#define QT_VFB_KEYBOARD_PIPE(DISPLAY) QString("/tmp/.qtvfb_keyboard-%1").arg(DISPLAY) -#define QT_VFB_MAP(DISPLAY) QString("/tmp/.qtvfb_map-%1").arg(DISPLAY) -#define QT_VFB_SOUND_PIPE(DISPLAY) QString("/tmp/.qt_soundserver-%1").arg(DISPLAY) -#define QTE_PIPE(DISPLAY) QT_VFB_DATADIR(DISPLAY) \ - .append("/QtEmbedded-%1") \ - .arg(DISPLAY) -#define QTE_PIPE_QVFB(DISPLAY) QString("/tmp/qtembedded-%1/QtEmbedded-%1") \ - .arg(DISPLAY) +#define QT_VFB_DATADIR(DISPLAY) QString::fromLatin1("%1/qtembedded-%2") \ + .arg(QT_QWS_TEMP_DIR).arg(DISPLAY) +#define QT_VFB_MOUSE_PIPE(DISPLAY) QString::fromLatin1("%1/.qtvfb_mouse-%2") \ + .arg(QT_QWS_TEMP_DIR).arg(DISPLAY) +#define QT_VFB_KEYBOARD_PIPE(DISPLAY) QString::fromLatin1("%1/.qtvfb_keyboard-%2") \ + .arg(QT_QWS_TEMP_DIR).arg(DISPLAY) +#define QT_VFB_MAP(DISPLAY) QString::fromLatin1("%1/.qtvfb_map-%2") \ + .arg(QT_QWS_TEMP_DIR).arg(DISPLAY) +#define QT_VFB_SOUND_PIPE(DISPLAY) QString::fromLatin1("%1/.qt_soundserver-%2") \ + .arg(QT_QWS_TEMP_DIR).arg(DISPLAY) +#define QTE_PIPE(DISPLAY) QT_VFB_DATADIR(DISPLAY) \ + .append(QLatin1String("/QtEmbedded-%1")).arg(DISPLAY) +#define QTE_PIPE_QVFB(DISPLAY) QTE_PIPE(DISPLAY) #endif struct QVFbHeader diff --git a/src/gui/graphicsview/qgraphicslayout.cpp b/src/gui/graphicsview/qgraphicslayout.cpp index ed213f1..e50989c 100644 --- a/src/gui/graphicsview/qgraphicslayout.cpp +++ b/src/gui/graphicsview/qgraphicslayout.cpp @@ -167,7 +167,7 @@ QGraphicsLayout::QGraphicsLayout(QGraphicsLayoutItem *parent) " neither a QGraphicsWidget nor QGraphicsLayout"); } } - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, QSizePolicy::DefaultType); + d_func()->sizePolicy = QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, QSizePolicy::DefaultType); setOwnedByLayout(true); } @@ -188,7 +188,7 @@ QGraphicsLayout::QGraphicsLayout(QGraphicsLayoutPrivate &dd, QGraphicsLayoutItem " neither a QGraphicsWidget nor QGraphicsLayout"); } } - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, QSizePolicy::DefaultType); + d_func()->sizePolicy = QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, QSizePolicy::DefaultType); setOwnedByLayout(true); } @@ -269,12 +269,20 @@ void QGraphicsLayout::activate() return; Q_ASSERT(!parentItem->isLayout()); - setGeometry(parentItem->contentsRect()); // relayout children - - // ### bug, should be parentItem ? - parentLayoutItem()->updateGeometry(); // bubble up; will set activated to false - // ### too many resizes? maybe we should walk up the chain to the - // ### top-level layouted layoutItem and call activate there. + if (QGraphicsLayout::instantInvalidatePropagation()) { + QGraphicsWidget *parentWidget = static_cast<QGraphicsWidget*>(parentItem); + if (!parentWidget->parentLayoutItem()) { + // we've reached the topmost widget, resize it + bool wasResized = parentWidget->testAttribute(Qt::WA_Resized); + parentWidget->resize(parentWidget->size()); + parentWidget->setAttribute(Qt::WA_Resized, wasResized); + } + + setGeometry(parentItem->contentsRect()); // relayout children + } else { + setGeometry(parentItem->contentsRect()); // relayout children + parentLayoutItem()->updateGeometry(); + } } /*! @@ -300,32 +308,36 @@ bool QGraphicsLayout::isActivated() const */ void QGraphicsLayout::invalidate() { - // only mark layouts as invalid (activated = false) if we can post a LayoutRequest event. - QGraphicsLayoutItem *layoutItem = this; - while (layoutItem && layoutItem->isLayout()) { - // we could call updateGeometry(), but what if that method - // does not call the base implementation? In addition, updateGeometry() - // does more than we need. - layoutItem->d_func()->sizeHintCacheDirty = true; - layoutItem->d_func()->sizeHintWithConstraintCacheDirty = true; - layoutItem = layoutItem->parentLayoutItem(); - } - if (layoutItem) { - layoutItem->d_func()->sizeHintCacheDirty = true; - layoutItem->d_func()->sizeHintWithConstraintCacheDirty = true; - } - - bool postIt = layoutItem ? !layoutItem->isLayout() : false; - if (postIt) { - layoutItem = this; - while (layoutItem && layoutItem->isLayout() - && static_cast<QGraphicsLayout*>(layoutItem)->d_func()->activated) { - static_cast<QGraphicsLayout*>(layoutItem)->d_func()->activated = false; + if (QGraphicsLayout::instantInvalidatePropagation()) { + updateGeometry(); + } else { + // only mark layouts as invalid (activated = false) if we can post a LayoutRequest event. + QGraphicsLayoutItem *layoutItem = this; + while (layoutItem && layoutItem->isLayout()) { + // we could call updateGeometry(), but what if that method + // does not call the base implementation? In addition, updateGeometry() + // does more than we need. + layoutItem->d_func()->sizeHintCacheDirty = true; + layoutItem->d_func()->sizeHintWithConstraintCacheDirty = true; layoutItem = layoutItem->parentLayoutItem(); } - if (layoutItem && !layoutItem->isLayout()) { - // If a layout has a parent that is not a layout it must be a QGraphicsWidget. - QApplication::postEvent(static_cast<QGraphicsWidget *>(layoutItem), new QEvent(QEvent::LayoutRequest)); + if (layoutItem) { + layoutItem->d_func()->sizeHintCacheDirty = true; + layoutItem->d_func()->sizeHintWithConstraintCacheDirty = true; + } + + bool postIt = layoutItem ? !layoutItem->isLayout() : false; + if (postIt) { + layoutItem = this; + while (layoutItem && layoutItem->isLayout() + && static_cast<QGraphicsLayout*>(layoutItem)->d_func()->activated) { + static_cast<QGraphicsLayout*>(layoutItem)->d_func()->activated = false; + layoutItem = layoutItem->parentLayoutItem(); + } + if (layoutItem && !layoutItem->isLayout()) { + // If a layout has a parent that is not a layout it must be a QGraphicsWidget. + QApplication::postEvent(static_cast<QGraphicsWidget *>(layoutItem), new QEvent(QEvent::LayoutRequest)); + } } } } @@ -335,12 +347,27 @@ void QGraphicsLayout::invalidate() */ void QGraphicsLayout::updateGeometry() { - QGraphicsLayoutItem::updateGeometry(); - if (QGraphicsLayoutItem *parentItem = parentLayoutItem()) { - if (parentItem->isLayout()) { + Q_D(QGraphicsLayout); + if (QGraphicsLayout::instantInvalidatePropagation()) { + d->activated = false; + QGraphicsLayoutItem::updateGeometry(); + + QGraphicsLayoutItem *parentItem = parentLayoutItem(); + if (!parentItem) + return; + + if (parentItem->isLayout()) + static_cast<QGraphicsLayout *>(parentItem)->invalidate(); + else parentItem->updateGeometry(); - } else { - invalidate(); + } else { + QGraphicsLayoutItem::updateGeometry(); + if (QGraphicsLayoutItem *parentItem = parentLayoutItem()) { + if (parentItem->isLayout()) { + parentItem->updateGeometry(); + } else { + invalidate(); + } } } } @@ -446,6 +473,50 @@ void QGraphicsLayout::addChildLayoutItem(QGraphicsLayoutItem *layoutItem) d->addChildLayoutItem(layoutItem); } +static bool g_instantInvalidatePropagation = false; + +/*! + \internal + \since 4.8 + \see instantInvalidatePropagation + + Calling this function with \a enable set to true will enable a feature that + makes propagation of invalidation up to ancestor layout items to be done in + one go. It will propagate up the parentLayoutItem() hierarchy until it has + reached the root. If the root item is a QGraphicsWidget, it will *post* a + layout request to it. When the layout request is consumed it will traverse + down the hierarchy of layouts and widgets and activate all layouts that is + invalid (not activated). This is the recommended behaviour. + + If not set it will also propagate up the parentLayoutItem() hierarchy, but + it will stop at the \i first \i widget it encounters, and post a layout + request to the widget. When the layout request is consumed, this might + cause it to continue propagation up to the parentLayoutItem() of the + widget. It will continue in this fashion until it has reached a widget with + no parentLayoutItem(). This strategy might cause drawing artifacts, since + it is not done in one go, and the consumption of layout requests might be + interleaved by consumption of paint events, which might cause significant + flicker. + Note, this is not the recommended behavior, but for compatibility reasons + this is the default behaviour. +*/ +void QGraphicsLayout::setInstantInvalidatePropagation(bool enable) +{ + g_instantInvalidatePropagation = enable; +} + +/*! + \internal + \since 4.8 + \see setInstantInvalidatePropagation + + returns true if the complete widget/layout hierarchy is rearranged in one go. +*/ +bool QGraphicsLayout::instantInvalidatePropagation() +{ + return g_instantInvalidatePropagation; +} + QT_END_NAMESPACE #endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicslayout.h b/src/gui/graphicsview/qgraphicslayout.h index c622fb8..6031174 100644 --- a/src/gui/graphicsview/qgraphicslayout.h +++ b/src/gui/graphicsview/qgraphicslayout.h @@ -76,6 +76,8 @@ public: virtual QGraphicsLayoutItem *itemAt(int i) const = 0; virtual void removeAt(int index) = 0; + static void setInstantInvalidatePropagation(bool enable); + static bool instantInvalidatePropagation(); protected: QGraphicsLayout(QGraphicsLayoutPrivate &, QGraphicsLayoutItem *); void addChildLayoutItem(QGraphicsLayoutItem *layoutItem); diff --git a/src/gui/graphicsview/qgraphicslayout_p.cpp b/src/gui/graphicsview/qgraphicslayout_p.cpp index c2d4a08..6afdc19 100644 --- a/src/gui/graphicsview/qgraphicslayout_p.cpp +++ b/src/gui/graphicsview/qgraphicslayout_p.cpp @@ -180,8 +180,13 @@ void QGraphicsLayoutPrivate::activateRecursive(QGraphicsLayoutItem *item) { if (item->isLayout()) { QGraphicsLayout *layout = static_cast<QGraphicsLayout *>(item); - if (layout->d_func()->activated) - layout->invalidate(); + if (layout->d_func()->activated) { + if (QGraphicsLayout::instantInvalidatePropagation()) { + return; + } else { + layout->invalidate(); // ### LOOKS SUSPICIOUSLY WRONG!!??? + } + } for (int i = layout->count() - 1; i >= 0; --i) { QGraphicsLayoutItem *childItem = layout->itemAt(i); diff --git a/src/gui/graphicsview/qgraphicslinearlayout.cpp b/src/gui/graphicsview/qgraphicslinearlayout.cpp index 5591638..40f9b1d 100644 --- a/src/gui/graphicsview/qgraphicslinearlayout.cpp +++ b/src/gui/graphicsview/qgraphicslinearlayout.cpp @@ -275,17 +275,13 @@ void QGraphicsLinearLayout::insertItem(int index, QGraphicsLayoutItem *item) qWarning("QGraphicsLinearLayout::insertItem: cannot insert itself"); return; } - Q_ASSERT(item); - - //the order of the following instructions is very important because - //invalidating the layout before adding the child item will make the layout happen - //before we try to paint the item - invalidate(); d->addChildLayoutItem(item); + Q_ASSERT(item); d->fixIndex(&index); d->engine.insertRow(index, d->orientation); new QGridLayoutItem(&d->engine, item, d->gridRow(index), d->gridColumn(index), 1, 1, 0, index); + invalidate(); } /*! diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 85a4e16..c0a4bf9 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5983,9 +5983,6 @@ bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEve } if (item && item->isPanel()) break; - if (item && (item->d_ptr->flags - & (QGraphicsItem::ItemStopsClickFocusPropagation | QGraphicsItem::ItemStopsFocusHandling))) - break; } touchEvent->setAccepted(eventAccepted); diff --git a/src/gui/graphicsview/qgraphicstransform.cpp b/src/gui/graphicsview/qgraphicstransform.cpp index 06df788..513c41f 100644 --- a/src/gui/graphicsview/qgraphicstransform.cpp +++ b/src/gui/graphicsview/qgraphicstransform.cpp @@ -92,6 +92,7 @@ #include "qgraphicstransform_p.h" #include <QDebug> #include <QtCore/qmath.h> +#include <QtCore/qnumeric.h> #ifndef QT_NO_GRAPHICSVIEW QT_BEGIN_NAMESPACE @@ -467,6 +468,7 @@ void QGraphicsRotation::setOrigin(const QVector3D &point) item will be rotated counter-clockwise. Normally the rotation angle will be in the range (-360, 360), but you can also provide numbers outside of this range (e.g., a angle of 370 degrees gives the same result as 10 degrees). + Setting the angle to NaN results in no rotation. \sa origin */ @@ -570,7 +572,7 @@ void QGraphicsRotation::applyTo(QMatrix4x4 *matrix) const { Q_D(const QGraphicsRotation); - if (d->angle == 0. || d->axis.isNull()) + if (d->angle == 0. || d->axis.isNull() || qIsNaN(d->angle)) return; matrix->translate(d->origin); diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 2b129d7..16268a8 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -2498,7 +2498,7 @@ QVariant QGraphicsView::inputMethodQuery(Qt::InputMethodQuery query) const else if (value.type() == QVariant::PointF) value = mapFromScene(value.toPointF()); else if (value.type() == QVariant::Rect) - value = mapFromScene(value.toRect()).boundingRect(); + value = d->mapRectFromScene(value.toRect()).toRect(); else if (value.type() == QVariant::Point) value = mapFromScene(value.toPoint()); return value; diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index 675a5c5..141e305 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -354,8 +354,10 @@ void QGraphicsWidget::setGeometry(const QRectF &rect) newGeom = rect; newGeom.setSize(rect.size().expandedTo(effectiveSizeHint(Qt::MinimumSize)) .boundedTo(effectiveSizeHint(Qt::MaximumSize))); - if (newGeom == d->geom) - return; + + if (newGeom == d->geom) { + goto relayoutChildrenAndReturn; + } // setPos triggers ItemPositionChange, which can adjust position wd->inSetGeometry = 1; @@ -363,8 +365,9 @@ void QGraphicsWidget::setGeometry(const QRectF &rect) wd->inSetGeometry = 0; newGeom.moveTopLeft(pos()); - if (newGeom == d->geom) - return; + if (newGeom == d->geom) { + goto relayoutChildrenAndReturn; + } // Update and prepare to change the geometry (remove from index) if the size has changed. if (wd->scene) { @@ -375,35 +378,54 @@ void QGraphicsWidget::setGeometry(const QRectF &rect) } // Update the layout item geometry - bool moved = oldPos != pos(); - if (moved) { - // Send move event. - QGraphicsSceneMoveEvent event; - event.setOldPos(oldPos); - event.setNewPos(pos()); - QApplication::sendEvent(this, &event); - if (wd->inSetPos) { - //set the new pos - d->geom.moveTopLeft(pos()); - emit geometryChanged(); - return; + { + bool moved = oldPos != pos(); + if (moved) { + // Send move event. + QGraphicsSceneMoveEvent event; + event.setOldPos(oldPos); + event.setNewPos(pos()); + QApplication::sendEvent(this, &event); + if (wd->inSetPos) { + //set the new pos + d->geom.moveTopLeft(pos()); + emit geometryChanged(); + goto relayoutChildrenAndReturn; + } + } + QSizeF oldSize = size(); + QGraphicsLayoutItem::setGeometry(newGeom); + // Send resize event + bool resized = newGeom.size() != oldSize; + if (resized) { + QGraphicsSceneResizeEvent re; + re.setOldSize(oldSize); + re.setNewSize(newGeom.size()); + if (oldSize.width() != newGeom.size().width()) + emit widthChanged(); + if (oldSize.height() != newGeom.size().height()) + emit heightChanged(); + QGraphicsLayout *lay = wd->layout; + if (QGraphicsLayout::instantInvalidatePropagation()) { + if (!lay || lay->isActivated()) { + QApplication::sendEvent(this, &re); + } + } else { + QApplication::sendEvent(this, &re); + } } } - QSizeF oldSize = size(); - QGraphicsLayoutItem::setGeometry(newGeom); - // Send resize event - bool resized = newGeom.size() != oldSize; - if (resized) { - QGraphicsSceneResizeEvent re; - re.setOldSize(oldSize); - re.setNewSize(newGeom.size()); - if (oldSize.width() != newGeom.size().width()) - emit widthChanged(); - if (oldSize.height() != newGeom.size().height()) - emit heightChanged(); - QApplication::sendEvent(this, &re); - } + emit geometryChanged(); +relayoutChildrenAndReturn: + if (QGraphicsLayout::instantInvalidatePropagation()) { + if (QGraphicsLayout *lay = wd->layout) { + if (!lay->isActivated()) { + QEvent layoutRequest(QEvent::LayoutRequest); + QApplication::sendEvent(this, &layoutRequest); + } + } + } } /*! @@ -1052,16 +1074,31 @@ void QGraphicsWidget::updateGeometry() QGraphicsLayoutItem *parentItem = parentLayoutItem(); if (parentItem && parentItem->isLayout()) { - parentItem->updateGeometry(); + if (QGraphicsLayout::instantInvalidatePropagation()) { + static_cast<QGraphicsLayout *>(parentItem)->invalidate(); + } else { + parentItem->updateGeometry(); + } } else { if (parentItem) { + // This is for custom layouting QGraphicsWidget *parentWid = parentWidget(); //### if (parentWid->isVisible()) QApplication::postEvent(parentWid, new QEvent(QEvent::LayoutRequest)); + } else { + /** + * If this is the topmost widget, post a LayoutRequest event to the widget. + * When the event is received, it will start flowing all the way down to the leaf + * widgets in one go. This will make a relayout flicker-free. + */ + if (QGraphicsLayout::instantInvalidatePropagation()) + QApplication::postEvent(static_cast<QGraphicsWidget *>(this), new QEvent(QEvent::LayoutRequest)); + } + if (!QGraphicsLayout::instantInvalidatePropagation()) { + bool wasResized = testAttribute(Qt::WA_Resized); + resize(size()); // this will restrict the size + setAttribute(Qt::WA_Resized, wasResized); } - bool wasResized = testAttribute(Qt::WA_Resized); - resize(size()); // this will restrict the size - setAttribute(Qt::WA_Resized, wasResized); } } diff --git a/src/gui/gui.pro b/src/gui/gui.pro index 4d51fa8..cf492d6 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -55,11 +55,9 @@ DEFINES += Q_INTERNAL_QAPP_SRC symbian { TARGET.UID3=0x2001B2DD - symbian-abld|symbian-sbsv2 { - # ro-section in gui can exceed default allocated space, so move rw-section a little further - QMAKE_LFLAGS.ARMCC += --rw-base 0x800000 - QMAKE_LFLAGS.GCCE += -Tdata 0xC00000 - } + # ro-section in gui can exceed default allocated space, so move rw-section a little further + QMAKE_LFLAGS.ARMCC += --rw-base 0x800000 + QMAKE_LFLAGS.GCCE += -Tdata 0x800000 } neon:*-g++* { diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 441bdb1..c867984 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -4377,6 +4377,8 @@ QImage QImage::scaled(const QSize& s, Qt::AspectRatioMode aspectMode, Qt::Transf QSize newSize = size(); newSize.scale(s, aspectMode); + newSize.rwidth() = qMax(newSize.width(), 1); + newSize.rheight() = qMax(newSize.height(), 1); if (newSize == size()) return *this; diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 1a83318..ed1b0f0 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -1479,6 +1479,8 @@ QPixmap QPixmap::scaled(const QSize& s, Qt::AspectRatioMode aspectMode, Qt::Tran QSize newSize = size(); newSize.scale(s, aspectMode); + newSize.rwidth() = qMax(newSize.width(), 1); + newSize.rheight() = qMax(newSize.height(), 1); if (newSize == size()) return *this; diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp index 41fc6e9..ae772d8 100644 --- a/src/gui/image/qpixmapcache.cpp +++ b/src/gui/image/qpixmapcache.cpp @@ -91,9 +91,7 @@ QT_BEGIN_NAMESPACE \sa QCache, QPixmap */ -#if defined(Q_OS_SYMBIAN) -static int cache_limit = 1024; // 1048 KB cache limit for symbian -#elif defined(Q_WS_QWS) || defined(Q_WS_WINCE) +#if defined(Q_WS_QWS) || defined(Q_WS_WINCE) static int cache_limit = 2048; // 2048 KB cache limit for embedded #else static int cache_limit = 10240; // 10 MB cache limit for desktop diff --git a/src/gui/image/qvolatileimage.cpp b/src/gui/image/qvolatileimage.cpp index 098e9a1..f5076e1 100644 --- a/src/gui/image/qvolatileimage.cpp +++ b/src/gui/image/qvolatileimage.cpp @@ -103,6 +103,11 @@ QVolatileImage &QVolatileImage::operator=(const QVolatileImage &rhs) return *this; } +bool QVolatileImage::paintingActive() const +{ + return d->pengine && d->pengine->isActive(); +} + bool QVolatileImage::isNull() const { return d->image.isNull(); diff --git a/src/gui/image/qvolatileimage_p.h b/src/gui/image/qvolatileimage_p.h index fc5d6b1..d835f45 100644 --- a/src/gui/image/qvolatileimage_p.h +++ b/src/gui/image/qvolatileimage_p.h @@ -71,6 +71,7 @@ public: ~QVolatileImage(); QVolatileImage &operator=(const QVolatileImage &rhs); + bool paintingActive() const; bool isNull() const; QImage::Format format() const; int width() const; diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index 2c70ade..06dc25c 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -77,6 +77,15 @@ QT_BEGIN_NAMESPACE Q_GUI_EXPORT void qt_s60_setPartialScreenInputMode(bool enable) { S60->partial_keyboard = enable; + + QInputContext *ic = 0; + if (QApplication::focusWidget()) { + ic = QApplication::focusWidget()->inputContext(); + } else if (qApp && qApp->inputContext()) { + ic = qApp->inputContext(); + } + if (ic) + ic->update(); } QCoeFepInputContext::QCoeFepInputContext(QObject *parent) @@ -108,7 +117,7 @@ QCoeFepInputContext::QCoeFepInputContext(QObject *parent) m_fepState->SetDefaultCase( EAknEditorTextCase ); m_fepState->SetPermittedCases( EAknEditorAllCaseModes ); m_fepState->SetSpecialCharacterTableResourceId(R_AVKON_SPECIAL_CHARACTER_TABLE_DIALOG); - m_fepState->SetNumericKeymap( EAknEditorStandardNumberModeKeymap ); + m_fepState->SetNumericKeymap(EAknEditorAlphanumericNumberModeKeymap); } QCoeFepInputContext::~QCoeFepInputContext() @@ -231,7 +240,7 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event) // It ignores the mouse event, so we need to commit and send a selection event (which will get triggered // after the commit) if (!m_preeditString.isEmpty()) { - commitCurrentString(false); + commitCurrentString(true); int pos = focusWidget()->inputMethodQuery(Qt::ImCursorPosition).toInt(); @@ -246,9 +255,13 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event) // fall through intended case QEvent::KeyRelease: const QKeyEvent *keyEvent = static_cast<const QKeyEvent *>(event); + //If proxy exists, always use hints from proxy. + QWidget *proxy = focusWidget()->focusProxy(); + Qt::InputMethodHints currentHints = proxy ? proxy->inputMethodHints() : focusWidget()->inputMethodHints(); + switch (keyEvent->key()) { case Qt::Key_F20: - Q_ASSERT(m_lastImHints == focusWidget()->inputMethodHints()); + Q_ASSERT(m_lastImHints == currentHints); if (m_lastImHints & Qt::ImhHiddenText) { // Special case in Symbian. On editors with secret text, F20 is for some reason // considered to be a backspace. @@ -278,7 +291,7 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event) } if (keyEvent->type() == QEvent::KeyPress - && focusWidget()->inputMethodHints() & Qt::ImhHiddenText + && currentHints & Qt::ImhHiddenText && !keyEvent->text().isEmpty()) { // Send some temporary preedit text in order to make text visible for a moment. m_preeditString = keyEvent->text(); @@ -410,12 +423,14 @@ void QCoeFepInputContext::resetSplitViewWidget(bool keepInputWidget) windowToMove->setUpdatesEnabled(false); if (!alwaysResize) { - if (gv->scene() && gv->scene()->focusItem()) { - // Check if the widget contains cursorPositionChanged signal and disconnect from it. - QByteArray signal = QMetaObject::normalizedSignature(SIGNAL(cursorPositionChanged())); - int index = gv->scene()->focusItem()->toGraphicsObject()->metaObject()->indexOfSignal(signal.right(signal.length() - 1)); - if (index != -1) - disconnect(gv->scene()->focusItem()->toGraphicsObject(), SIGNAL(cursorPositionChanged()), this, SLOT(translateInputWidget())); + if (gv->scene()) { + if (gv->scene()->focusItem()) { + // Check if the widget contains cursorPositionChanged signal and disconnect from it. + QByteArray signal = QMetaObject::normalizedSignature(SIGNAL(cursorPositionChanged())); + int index = gv->scene()->focusItem()->toGraphicsObject()->metaObject()->indexOfSignal(signal.right(signal.length() - 1)); + if (index != -1) + disconnect(gv->scene()->focusItem()->toGraphicsObject(), SIGNAL(cursorPositionChanged()), this, SLOT(translateInputWidget())); + } QGraphicsItem *rootItem = 0; foreach (QGraphicsItem *item, gv->scene()->items()) { @@ -529,28 +544,32 @@ void QCoeFepInputContext::ensureFocusWidgetVisible(QWidget *widget) // and greatly reduces event passing in orientation switch cases, // as the statuspane size is not changing. + if (alwaysResize) + windowToMove->setUpdatesEnabled(false); + if (!(windowToMove->windowState() & Qt::WindowFullScreen)) { windowToMove->setWindowState( (windowToMove->windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen)) | Qt::WindowFullScreen); } if (alwaysResize) { - windowToMove->setUpdatesEnabled(false); - if (!moveWithinVisibleArea) + if (!moveWithinVisibleArea) { m_splitViewResizeBy = widget->height(); - - windowTop = widget->geometry().top(); - widget->resize(widget->width(), splitViewRect.height() - windowTop); + windowTop = widget->geometry().top(); + widget->resize(widget->width(), splitViewRect.height() - windowTop); + } if (gv->scene()) { const QRectF microFocusRect = gv->scene()->inputMethodQuery(Qt::ImMicroFocus).toRectF(); gv->ensureVisible(microFocusRect); } - windowToMove->setUpdatesEnabled(true); } else { translateInputWidget(); } + if (alwaysResize) + windowToMove->setUpdatesEnabled(true); + widget->setAttribute(Qt::WA_Resized, userResize); //not a user resize } @@ -573,7 +592,21 @@ void QCoeFepInputContext::updateHints(bool mustUpdateInputCapabilities) { QWidget *w = focusWidget(); if (w) { - Qt::InputMethodHints hints = w->inputMethodHints(); + QWidget *proxy = w->focusProxy(); + Qt::InputMethodHints hints = proxy ? proxy->inputMethodHints() : w->inputMethodHints(); + + // Since splitview support works like an input method hint, yet it is private flag, + // we need to update its state separately. + if (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0) { + TInt currentFlags = m_fepState->Flags(); + if (S60->partial_keyboard) + currentFlags |= QT_EAknEditorFlagEnablePartialScreen; + else + currentFlags &= ~QT_EAknEditorFlagEnablePartialScreen; + if (currentFlags != m_fepState->Flags()) + m_fepState->SetFlags(currentFlags); + } + if (hints != m_lastImHints) { m_lastImHints = hints; applyHints(hints); @@ -726,6 +759,8 @@ void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints) m_fepState->SetSpecialCharacterTableResourceId(R_AVKON_EMAIL_ADDR_SPECIAL_CHARACTER_TABLE_DIALOG); } else if (needsCharMap) { m_fepState->SetSpecialCharacterTableResourceId(R_AVKON_SPECIAL_CHARACTER_TABLE_DIALOG); + } else if ((hints & ImhFormattedNumbersOnly) || (hints & ImhDialableCharactersOnly)) { + m_fepState->SetSpecialCharacterTableResourceId(R_AVKON_SPECIAL_CHARACTER_TABLE_DIALOG); } else { m_fepState->SetSpecialCharacterTableResourceId(0); } diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index f9c84c1..467eb9b 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -111,6 +111,8 @@ win32 { } symbian { + exists($${EPOCROOT}epoc32/include/platform/mw/akntranseffect.h): DEFINES += QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H + SOURCES += \ kernel/qapplication_s60.cpp \ kernel/qeventdispatcher_s60.cpp \ diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 59aec91..f906bbf 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -128,6 +128,10 @@ extern bool qt_wince_is_pocket_pc(); //qguifunctions_wince.cpp //#define ALIEN_DEBUG +#if defined(Q_OS_SYMBIAN) +#include "qt_s60_p.h" +#endif + static void initResources() { #if defined(Q_WS_WINCE) @@ -2432,6 +2436,11 @@ bool QApplication::event(QEvent *e) { Q_D(QApplication); if(e->type() == QEvent::Close) { +#if defined(Q_OS_SYMBIAN) + // In order to have proper application-exit effects on Symbian, certain + // native APIs have to be called _before_ closing/destroying the widgets. + bool effectStarted = qt_beginFullScreenEffect(); +#endif QCloseEvent *ce = static_cast<QCloseEvent*>(e); ce->accept(); closeAllWindows(); @@ -2445,8 +2454,14 @@ bool QApplication::event(QEvent *e) break; } } - if(ce->isAccepted()) + if (ce->isAccepted()) { return true; + } else { +#if defined(Q_OS_SYMBIAN) + if (effectStarted) + qt_abortFullScreenEffect(); +#endif + } } else if(e->type() == QEvent::LanguageChange) { #ifndef QT_NO_TRANSLATION setLayoutDirection(qt_detectRTLLanguage()?Qt::RightToLeft:Qt::LeftToRight); diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 0427ae4..6620efd 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -142,6 +142,60 @@ void QS60Data::setStatusPaneAndButtonGroupVisibility(bool statusPaneVisible, boo // Ensure that control rectangle is updated static_cast<QSymbianControl *>(QApplication::activeWindow()->winId())->handleClientAreaChange(); } + +bool QS60Data::setRecursiveDecorationsVisibility(QWidget *window, Qt::WindowStates newState) +{ + // Show statusbar: + // Topmost parent: Show unless fullscreen/minimized. + // Child windows: Follow topmost parent, unless fullscreen, in which case do not show statusbar + // Show CBA: + // Topmost parent: Show unless fullscreen/minimized. + // Exception: Show if fullscreen with Qt::WindowSoftkeysVisibleHint. + // Child windows: + // Minimized: Unclear if there is an use case for having focused minimized window at all. + // Always follow topmost parent just to be safe. + // Maximized and normal: follow topmost parent. + // Exception: If topmost parent is not showing CBA, show CBA if any softkey actions are + // defined. + // Fullscreen: Show only if Qt::WindowSoftkeysVisibleHint set. + + Qt::WindowStates comparisonState = newState; + QWidget *parentWindow = window->parentWidget(); + if (parentWindow) { + while (parentWindow->parentWidget()) + parentWindow = parentWindow->parentWidget(); + comparisonState = parentWindow->windowState(); + } else { + parentWindow = window; + } + + bool decorationsVisible = !(comparisonState & (Qt::WindowFullScreen | Qt::WindowMinimized)); + const bool parentIsFullscreen = comparisonState & Qt::WindowFullScreen; + const bool parentCbaVisibilityHint = parentWindow->windowFlags() & Qt::WindowSoftkeysVisibleHint; + bool buttonGroupVisibility = (decorationsVisible || (parentIsFullscreen && parentCbaVisibilityHint)); + + // Do extra checking for child windows + if (window->parentWidget()) { + if (newState & Qt::WindowFullScreen) { + decorationsVisible = false; + if (window->windowFlags() & Qt::WindowSoftkeysVisibleHint) + buttonGroupVisibility = true; + else + buttonGroupVisibility = false; + } else if (!(newState & Qt::WindowMinimized) && !buttonGroupVisibility) { + for (int i = 0; i < window->actions().size(); ++i) { + if (window->actions().at(i)->softKeyRole() != QAction::NoSoftKey) { + buttonGroupVisibility = true; + break; + } + } + } + } + + S60->setStatusPaneAndButtonGroupVisibility(decorationsVisible, buttonGroupVisibility); + + return decorationsVisible; +} #endif void QS60Data::controlVisibilityChanged(CCoeControl *control, bool visible) @@ -161,6 +215,12 @@ void QS60Data::controlVisibilityChanged(CCoeControl *control, bool visible) widget->repaint(); } } else { + // In certain special scenarios we may get an ENotVisible event + // without a previous EPartiallyVisible. The backingstore must + // still be destroyed, hence the registerWidget() call below. + if (backingStore.data() && widget->internalWinId() + && qt_widget_private(widget)->maybeBackingStore() == backingStore.data()) + backingStore.registerWidget(widget); backingStore.unregisterWidget(widget); // In order to ensure that any resources used by the window surface // are immediately freed, we flush the WSERV command buffer. @@ -405,6 +465,7 @@ QSymbianControl::QSymbianControl(QWidget *w) , m_ignoreFocusChanged(0) , m_symbianPopupIsOpen(0) , m_inExternalScreenOverride(false) + , m_lastStatusPaneVisibility(0) { } @@ -491,11 +552,52 @@ void QSymbianControl::setWidget(QWidget *w) { qwidget = w; } + +QPoint QSymbianControl::translatePointForFixedNativeOrientation(const TPoint &pointerEventPos) const +{ + QPoint pos(pointerEventPos.iX, pointerEventPos.iY); + if (qwidget->d_func()->fixNativeOrientationCalled) { + QSize wsize = qwidget->size(); + TSize size = Size(); + if (size.iWidth == wsize.height() && size.iHeight == wsize.width()) { + qreal x = pos.x(); + qreal y = pos.y(); + pos.setX(size.iHeight - y); + pos.setY(x); + } + } + return pos; +} + +TRect QSymbianControl::translateRectForFixedNativeOrientation(const TRect &controlRect) const +{ + TRect rect = controlRect; + if (qwidget->d_func()->fixNativeOrientationCalled) { + QPoint a = translatePointForFixedNativeOrientation(rect.iTl); + QPoint b = translatePointForFixedNativeOrientation(rect.iBr); + if (a.x() < b.x()) { + rect.iTl.iX = a.x(); + rect.iBr.iX = b.x(); + } else { + rect.iTl.iX = b.x(); + rect.iBr.iX = a.x(); + } + if (a.y() < b.y()) { + rect.iTl.iY = a.y(); + rect.iBr.iY = b.y(); + } else { + rect.iTl.iY = b.y(); + rect.iBr.iY = a.y(); + } + } + return rect; +} + void QSymbianControl::HandleLongTapEventL( const TPoint& aPenEventLocation, const TPoint& aPenEventScreenLocation ) { QWidget *alienWidget; - QPoint widgetPos = QPoint(aPenEventLocation.iX, aPenEventLocation.iY); - QPoint globalPos = QPoint(aPenEventScreenLocation.iX,aPenEventScreenLocation.iY); + QPoint widgetPos = translatePointForFixedNativeOrientation(aPenEventLocation); + QPoint globalPos = translatePointForFixedNativeOrientation(aPenEventScreenLocation); alienWidget = qwidget->childAt(widgetPos); if (!alienWidget) alienWidget = qwidget; @@ -510,7 +612,7 @@ void QSymbianControl::HandleLongTapEventL( const TPoint& aPenEventLocation, cons void QSymbianControl::translateAdvancedPointerEvent(const TAdvancedPointerEvent *event) { QApplicationPrivate *d = QApplicationPrivate::instance(); - QPointF screenPos = qwidget->mapToGlobal(QPoint(event->iPosition.iX, event->iPosition.iY)); + QPointF screenPos = qwidget->mapToGlobal(translatePointForFixedNativeOrientation(event->iPosition)); qreal pressure; if(d->pressureSupported && event->Pressure() > 0) //workaround for misconfigured HAL @@ -611,7 +713,7 @@ void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent) mapS60MouseEventTypeToQt(&type, &button, &pEvent); Qt::KeyboardModifiers modifiers = mapToQtModifiers(pEvent.iModifiers); - QPoint widgetPos = QPoint(pEvent.iPosition.iX, pEvent.iPosition.iY); + QPoint widgetPos = translatePointForFixedNativeOrientation(pEvent.iPosition); TPoint controlScreenPos = PositionRelativeToScreen(); QPoint globalPos = QPoint(controlScreenPos.iX, controlScreenPos.iY) + widgetPos; S60->lastCursorPos = globalPos; @@ -1077,6 +1179,9 @@ void QSymbianControl::Draw(const TRect& controlRect) const Q_ASSERT(window); QTLWExtra *topExtra = window->d_func()->maybeTopData(); Q_ASSERT(topExtra); + + TRect wcontrolRect = translateRectForFixedNativeOrientation(controlRect); + if (!topExtra->inExpose) { topExtra->inExpose = true; if (!qwidget->isWindow()) { @@ -1087,7 +1192,7 @@ void QSymbianControl::Draw(const TRect& controlRect) const gc.SetBrushColor(TRgb(0, 0, 0, 0)); gc.Clear(controlRect); } - QRect exposeRect = qt_TRect2QRect(controlRect); + QRect exposeRect = qt_TRect2QRect(wcontrolRect); qwidget->d_func()->syncBackingStore(exposeRect); topExtra->inExpose = false; } @@ -1100,7 +1205,7 @@ void QSymbianControl::Draw(const TRect& controlRect) const const bool sendNativePaintEvents = qwidget->d_func()->extraData()->receiveNativePaintEvents; if (sendNativePaintEvents) { - const QRect r = qt_TRect2QRect(controlRect); + const QRect r = qt_TRect2QRect(wcontrolRect); QMetaObject::invokeMethod(qwidget, "beginNativePaintEvent", Qt::DirectConnection, Q_ARG(QRect, r)); } @@ -1155,7 +1260,7 @@ void QSymbianControl::Draw(const TRect& controlRect) const } if (sendNativePaintEvents) { - const QRect r = qt_TRect2QRect(controlRect); + const QRect r = qt_TRect2QRect(wcontrolRect); // The draw ops aren't actually sent to WSERV until the graphics // context is deactivated, which happens in the function calling // this one. We therefore delay the delivery of endNativePaintEvent, @@ -1168,14 +1273,45 @@ void QSymbianControl::Draw(const TRect& controlRect) const } } +void QSymbianControl::qwidgetResize_helper(const QSize &newSize) +{ + QRect cr = qwidget->geometry(); + QSize oldSize(cr.size()); + cr.setSize(newSize); + qwidget->data->crect = cr; + if (qwidget->isVisible()) { + QTLWExtra *tlwExtra = qwidget->d_func()->maybeTopData(); + bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt(); + if (!slowResize && tlwExtra) + tlwExtra->inTopLevelResize = true; + QResizeEvent e(newSize, oldSize); + qt_sendSpontaneousEvent(qwidget, &e); + if (!qwidget->testAttribute(Qt::WA_StaticContents)) + qwidget->d_func()->syncBackingStore(); + if (!slowResize && tlwExtra) + tlwExtra->inTopLevelResize = false; + } else { + if (!qwidget->testAttribute(Qt::WA_PendingResizeEvent)) { + QResizeEvent *e = new QResizeEvent(newSize, oldSize); + QApplication::postEvent(qwidget, e); + } + } +} + void QSymbianControl::SizeChanged() { CCoeControl::SizeChanged(); + // When FixNativeOrientation had been called, the RWindow/CCoeControl size + // and the surface/QWidget size have nothing to do with each other. + if (qwidget->d_func()->fixNativeOrientationCalled) + return; + QSize oldSize = qwidget->size(); QSize newSize(Size().iWidth, Size().iHeight); if (oldSize != newSize) { + // Enforce the proper size for fullscreen widgets on the secondary screen. const bool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen; const int screenNumber = S60->screenNumberForWidget(qwidget); if (!m_inExternalScreenOverride && isFullscreen && screenNumber > 0) { @@ -1188,26 +1324,8 @@ void QSymbianControl::SizeChanged() return; } } - QRect cr = qwidget->geometry(); - cr.setSize(newSize); - qwidget->data->crect = cr; - if (qwidget->isVisible()) { - QTLWExtra *tlwExtra = qwidget->d_func()->maybeTopData(); - bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt(); - if (!slowResize && tlwExtra) - tlwExtra->inTopLevelResize = true; - QResizeEvent e(newSize, oldSize); - qt_sendSpontaneousEvent(qwidget, &e); - if (!qwidget->testAttribute(Qt::WA_StaticContents)) - qwidget->d_func()->syncBackingStore(); - if (!slowResize && tlwExtra) - tlwExtra->inTopLevelResize = false; - } else { - if (!qwidget->testAttribute(Qt::WA_PendingResizeEvent)) { - QResizeEvent *e = new QResizeEvent(newSize, oldSize); - QApplication::postEvent(qwidget, e); - } - } + + qwidgetResize_helper(newSize); } m_inExternalScreenOverride = false; @@ -1271,37 +1389,8 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) qwidget->d_func()->setWindowIcon_sys(true); qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle()); #ifdef Q_WS_S60 - if (qwidget->isWindow()) { - QWidget *const window = qwidget->window(); - QWidget *parentWindow = window->parentWidget(); - if (parentWindow) { - while (parentWindow->parentWidget()) - parentWindow = parentWindow->parentWidget(); - } else { - parentWindow = window; - } - - const bool parentDecorationsVisible = !(parentWindow->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized)); - const bool parentIsFullscreen = parentWindow->windowState() & Qt::WindowFullScreen; - const bool parentCbaVisibilityHint = parentWindow->windowFlags() & Qt::WindowSoftkeysVisibleHint; - bool buttonGroupVisibility = (parentDecorationsVisible || (parentIsFullscreen && parentCbaVisibilityHint)); - - // For non-toplevel normal and maximized windows, show cba if window has softkey - // actions even if topmost parent is not showing cba. Do the same for fullscreen - // windows that request it. - if (!buttonGroupVisibility - && window->parentWidget() - && !(window->windowState() & Qt::WindowMinimized) - && ((window->windowFlags() & Qt::WindowSoftkeysVisibleHint) || !(window->windowState() & Qt::WindowFullScreen))) { - for (int i = 0; i < window->actions().size(); ++i) { - if (window->actions().at(i)->softKeyRole() != QAction::NoSoftKey) { - buttonGroupVisibility = true; - break; - } - } - } - S60->setStatusPaneAndButtonGroupVisibility(parentDecorationsVisible, buttonGroupVisibility); - } + if (qwidget->isWindow()) + S60->setRecursiveDecorationsVisibility(qwidget, qwidget->windowState()); #endif } else if (QApplication::activeWindow() == qwidget->window()) { bool focusedControlFound = false; @@ -1402,7 +1491,13 @@ void QSymbianControl::HandleResourceChange(int resourceType) } break; case KInternalStatusPaneChange: - handleClientAreaChange(); + // When status pane is not visible, only handle client area change if status pane was + // previously visible, as size changes to hidden status pane should not affect + // client area. + if (S60->statusPane() && (S60->statusPane()->IsVisible() || m_lastStatusPaneVisibility)) { + m_lastStatusPaneVisibility = S60->statusPane()->IsVisible(); + handleClientAreaChange(); + } if (IsFocused() && IsVisible()) { qwidget->d_func()->setWindowIcon_sys(true); qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle()); @@ -1416,8 +1511,10 @@ void QSymbianControl::HandleResourceChange(int resourceType) { handleClientAreaChange(); // Send resize event to trigger desktopwidget workAreaResized signal - QResizeEvent e(qt_desktopWidget->size(), qt_desktopWidget->size()); - QApplication::sendEvent(qt_desktopWidget, &e); + if (qt_desktopWidget) { + QResizeEvent e(qt_desktopWidget->size(), qt_desktopWidget->size()); + QApplication::sendEvent(qt_desktopWidget, &e); + } break; } #endif @@ -1479,29 +1576,49 @@ bool QSymbianControl::isControlActive() void QSymbianControl::ensureFixNativeOrientation() { #if defined(Q_SYMBIAN_SUPPORTS_FIXNATIVEORIENTATION) - // Call FixNativeOrientation() for fullscreen QDeclarativeViews that - // have a locked orientation matching the native orientation of the device. - // This avoids unnecessary window rotation on wserv level. - if (!qwidget->isWindow() || qwidget->windowType() == Qt::Desktop - || !qwidget->inherits("QDeclarativeView") - || S60->screenNumberForWidget(qwidget) > 0) + if (!qwidget->isWindow() || qwidget->windowType() == Qt::Desktop) + return; + if (S60->screenNumberForWidget(qwidget) > 0) return; - const bool isFullScreen = qwidget->windowState().testFlag(Qt::WindowFullScreen); const bool isFixed = qwidget->d_func()->fixNativeOrientationCalled; - const bool matchesNative = qwidget->testAttribute( - S60->nativeOrientationIsPortrait ? Qt::WA_LockPortraitOrientation - : Qt::WA_LockLandscapeOrientation); - if (isFullScreen && matchesNative) { - if (!isFixed) { - Window().FixNativeOrientation(); - qwidget->d_func()->fixNativeOrientationCalled = true; + const bool isFixEnabled = qwidget->testAttribute(Qt::WA_SymbianNoSystemRotation); + const bool isFullScreen = qwidget->windowState().testFlag(Qt::WindowFullScreen); + if (isFullScreen && isFixEnabled) { + const bool surfaceBasedGs = + QApplicationPrivate::graphics_system_name == QLatin1String("openvg") + || QApplicationPrivate::graphics_system_name == QLatin1String("opengl"); + if (!surfaceBasedGs) + qwidget->setAttribute(Qt::WA_SymbianNoSystemRotation, false); + if (!isFixed && surfaceBasedGs) { + if (Window().FixNativeOrientation() == KErrNone) { + qwidget->d_func()->fixNativeOrientationCalled = true; + // The EGL window surface is now fixed to the native orientation + // of the device, no matter what size we pass when creating it. + // Enforce the same size for the QWidget too. For the underlying + // CCoeControl and RWindow it is up to the system to resize them + // when the standard auto-rotation mechanism is in use, we must not + // change that behavior by forcing any size for those. In practice + // this means that the QWidget and the underlying native control + // dimensions will be out of sync when FixNativeOrientation was + // called and the device is turned to the non-native (typically + // landscape) orientation. The pointer event handling and certain + // functions like Draw() will need to compensate for this. + QSize newSize(S60->nativeScreenWidthInPixels, S60->nativeScreenHeightInPixels); + if (qwidget->size() != newSize) + qwidgetResize_helper(newSize); + } else { + qwidget->setAttribute(Qt::WA_SymbianNoSystemRotation, false); + } } } else if (isFixed) { + qwidget->setAttribute(Qt::WA_SymbianNoSystemRotation, false); qwidget->d_func()->fixNativeOrientationCalled = false; qwidget->hide(); qwidget->d_func()->create_sys(0, false, true); qwidget->show(); } +#else + qwidget->setAttribute(Qt::WA_SymbianNoSystemRotation, false); #endif } @@ -1711,9 +1828,7 @@ void qt_init(QApplicationPrivate * /* priv */, int) systemFont.setFamily(systemFont.defaultFamily()); QApplicationPrivate::setSystemFont(systemFont); -#ifdef Q_SYMBIAN_TRANSITION_EFFECTS QObject::connect(qApp, SIGNAL(aboutToQuit()), qApp, SLOT(_q_aboutToQuit())); -#endif #ifdef Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE QApplicationPrivate::instance()->useTranslucentEGLSurfaces = true; @@ -1738,6 +1853,8 @@ void qt_init(QApplicationPrivate * /* priv */, int) } else { QApplicationPrivate::instance()->useTranslucentEGLSurfaces = false; } + if (QApplicationPrivate::graphics_system_name == QLatin1String("raster")) + QApplicationPrivate::instance()->useTranslucentEGLSurfaces = false; #else QApplicationPrivate::instance()->useTranslucentEGLSurfaces = false; #endif @@ -1802,6 +1919,9 @@ void qt_cleanup() S60->setButtonGroupContainer(0); #endif + // Call EndFullScreen() to prevent confusing the system effect state machine. + qt_endFullScreenEffect(); + if (S60->qtOwnsS60Environment) { // Restore the S60 framework trap handler. See qt_init(). User::SetTrapHandler(S60->s60InstalledTrapHandler); @@ -2173,7 +2293,8 @@ int QApplicationPrivate::symbianProcessWsEvent(const QSymbianEvent *symbianEvent } #endif #ifdef QT_SOFTKEYS_ENABLED - QSoftKeyManager::updateSoftKeys(); + if (!CEikonEnv::Static()->EikAppUi()->IsDisplayingMenuOrDialog()) + QSoftKeyManager::updateSoftKeys(); #endif break; case EEventFocusLost: @@ -2539,6 +2660,8 @@ void QApplication::restoreOverrideCursor() void QApplicationPrivate::_q_aboutToQuit() { + qt_beginFullScreenEffect(); + #ifdef Q_SYMBIAN_TRANSITION_EFFECTS // Send the shutdown tfx command S60->wsSession().SendEffectCommand(ETfxCmdAppShutDown); diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 6e89ceb..913bc7e 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -3779,16 +3779,32 @@ bool QETWidget::translateConfigEvent(const MSG &msg) QApplication::sendSpontaneousEvent(this, &e); hideChildren(true); } - } else if (msg.wParam != SIZE_MINIMIZED && isMinimized()) { + } else if (msg.wParam != SIZE_MINIMIZED) { + bool window_state_changed = false; + Qt::WindowStates oldstate = Qt::WindowStates(dataPtr()->window_state); + if (isMinimized()) { #ifndef Q_WS_WINCE - const QString title = windowTitle(); - if (!title.isEmpty()) - d_func()->setWindowTitle_helper(title); + const QString title = windowTitle(); + if (!title.isEmpty()) + d_func()->setWindowTitle_helper(title); #endif - data->window_state &= ~Qt::WindowMinimized; - showChildren(true); - QShowEvent e; - QApplication::sendSpontaneousEvent(this, &e); + data->window_state &= ~Qt::WindowMinimized; + showChildren(true); + QShowEvent e; + QApplication::sendSpontaneousEvent(this, &e); + // Capture SIZE_MAXIMIZED and SIZE_RESTORED without preceding WM_SYSCOMMAND + // (Aero Snap on Win7) + } else if (msg.wParam == SIZE_MAXIMIZED && !isMaximized()) { + data->window_state |= Qt::WindowMaximized; + window_state_changed = true; + } else if (msg.wParam == SIZE_RESTORED && isMaximized()) { + data->window_state &= ~(Qt::WindowMaximized); + window_state_changed = true; + } + if (window_state_changed) { + QWindowStateChangeEvent e(oldstate); + QApplication::sendSpontaneousEvent(this, &e); + } } } if (msg.wParam != SIZE_MINIMIZED && oldSize != newSize) { @@ -3820,7 +3836,7 @@ bool QETWidget::translateConfigEvent(const MSG &msg) QApplication::postEvent(this, e); } } -} else if (msg.message == WM_MOVE) { // move event + } else if (msg.message == WM_MOVE) { // move event int a = (int) (short) LOWORD(msg.lParam); int b = (int) (short) HIWORD(msg.lParam); QPoint oldPos = geometry().topLeft(); diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h index 6254061..406e6d4 100644 --- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h +++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h @@ -157,6 +157,20 @@ QT_END_NAMESPACE [NSApp terminate:sender]; } +- (void)setLevel:(NSInteger)windowLevel +{ + // Cocoa will upon activating/deactivating applications level modal + // windows up and down, regardsless of any explicit set window level. + // To ensure that modal stays-on-top dialogs actually stays on top after + // the application is activated (and therefore stacks in front of + // other stays-on-top windows), we need to add this little special-case override: + QWidget *widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self]; + if (widget && widget->isModal() && (widget->windowFlags() & Qt::WindowStaysOnTopHint)) + [super setLevel:NSPopUpMenuWindowLevel]; + else + [super setLevel:windowLevel]; +} + - (void)sendEvent:(NSEvent *)event { if ([event type] == NSApplicationDefined) { diff --git a/src/gui/kernel/qsoftkeymanager.cpp b/src/gui/kernel/qsoftkeymanager.cpp index 1b26933..204efe9 100644 --- a/src/gui/kernel/qsoftkeymanager.cpp +++ b/src/gui/kernel/qsoftkeymanager.cpp @@ -50,6 +50,10 @@ #include "private/qsoftkeymanager_s60_p.h" #endif +#ifdef SYMBIAN_VERSION_SYMBIAN3 +#include "private/qt_s60_p.h" +#endif + #ifndef QT_NO_SOFTKEYMANAGER QT_BEGIN_NAMESPACE @@ -101,6 +105,30 @@ QSoftKeyManager::QSoftKeyManager() : QAction *QSoftKeyManager::createAction(StandardSoftKey standardKey, QWidget *actionWidget) { QAction *action = new QAction(standardSoftKeyText(standardKey), actionWidget); +#ifdef SYMBIAN_VERSION_SYMBIAN3 + int key = 0; + switch (standardKey) { + case OkSoftKey: + key = EAknSoftkeyOk; + break; + case SelectSoftKey: + key = EAknSoftkeySelect; + break; + case DoneSoftKey: + key = EAknSoftkeyDone; + break; + case MenuSoftKey: + key = EAknSoftkeyOptions; + break; + case CancelSoftKey: + key = EAknSoftkeyCancel; + break; + default: + break; + }; + if (key != 0) + QSoftKeyManager::instance()->d_func()->softKeyCommandActions.insert(action, key); +#endif QAction::SoftKeyRole softKeyRole = QAction::NoSoftKey; switch (standardKey) { case MenuSoftKey: // FALL-THROUGH @@ -143,6 +171,9 @@ void QSoftKeyManager::cleanupHash(QObject *obj) Q_D(QSoftKeyManager); QAction *action = qobject_cast<QAction*>(obj); d->keyedActions.remove(action); +#ifdef SYMBIAN_VERSION_SYMBIAN3 + d->softKeyCommandActions.remove(action); +#endif } void QSoftKeyManager::sendKeyEvent() diff --git a/src/gui/kernel/qsoftkeymanager_common_p.h b/src/gui/kernel/qsoftkeymanager_common_p.h index 27d8ee9..02ae697 100644 --- a/src/gui/kernel/qsoftkeymanager_common_p.h +++ b/src/gui/kernel/qsoftkeymanager_common_p.h @@ -72,6 +72,9 @@ protected: QMultiHash<int, QAction*> requestedSoftKeyActions; QWidget *initialSoftKeySource; bool pendingUpdate; +#ifdef SYMBIAN_VERSION_SYMBIAN3 + QHash<QAction*, int> softKeyCommandActions; +#endif }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qsoftkeymanager_s60.cpp b/src/gui/kernel/qsoftkeymanager_s60.cpp index 09e2b5f..79ed91a 100644 --- a/src/gui/kernel/qsoftkeymanager_s60.cpp +++ b/src/gui/kernel/qsoftkeymanager_s60.cpp @@ -298,6 +298,10 @@ bool QSoftKeyManagerPrivateS60::setSoftkey(CEikButtonGroupContainer &cba, QString text = softkeyText(*action); TPtrC nativeText = qt_QString2TPtrC(text); int command = S60_COMMAND_START + position; +#ifdef SYMBIAN_VERSION_SYMBIAN3 + if (softKeyCommandActions.contains(action)) + command = softKeyCommandActions.value(action); +#endif setNativeSoftkey(cba, position, command, nativeText); const bool dimmed = !action->isEnabled() && !QSoftKeyManager::isForceEnabledInSofkeys(action); cba.DimCommand(command, dimmed); diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index 102c0ca..8aba53a 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -77,6 +77,10 @@ #include <akncontext.h> // CAknContextPane #include <eikspane.h> // CEikStatusPane #include <AknPopupFader.h> // MAknFadedComponent and TAknPopupFader +#include <gfxtranseffect/gfxtranseffect.h> // BeginFullScreen +#ifdef QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H +#include <akntranseffect.h> // BeginFullScreen +#endif #endif QT_BEGIN_NAMESPACE @@ -85,6 +89,9 @@ QT_BEGIN_NAMESPACE // system events seems to start with 0x10 const TInt KInternalStatusPaneChange = 0x50000000; +// For BeginFullScreen(). +const TUint KQtAppExitFlag = 0x400; + static const int qt_symbian_max_screens = 4; //this macro exists because EColor16MAP enum value doesn't exist in Symbian OS 9.2 @@ -178,6 +185,7 @@ public: static inline CEikButtonGroupContainer* buttonGroupContainer(); static inline void setButtonGroupContainer(CEikButtonGroupContainer* newCba); static void setStatusPaneAndButtonGroupVisibility(bool statusPaneVisible, bool buttonGroupVisible); + static bool setRecursiveDecorationsVisibility(QWidget *window, Qt::WindowStates newState); #endif static void controlVisibilityChanged(CCoeControl *control, bool visible); @@ -190,7 +198,11 @@ public: int screenWidthInTwipsForScreen[qt_symbian_max_screens]; int screenHeightInTwipsForScreen[qt_symbian_max_screens]; - bool nativeOrientationIsPortrait; + int nativeScreenWidthInPixels; + int nativeScreenHeightInPixels; + + int beginFullScreenCalled : 1; + int endFullScreenCalled : 1; }; Q_AUTOTEST_EXPORT QS60Data* qGlobalS60Data(); @@ -236,6 +248,8 @@ public: bool isControlActive(); void ensureFixNativeOrientation(); + QPoint translatePointForFixedNativeOrientation(const TPoint &pointerEventPos) const; + TRect translateRectForFixedNativeOrientation(const TRect &controlRect) const; #ifdef Q_WS_S60 void FadeBehindPopup(bool fade){ popupFader.FadeBehindPopup( this, this, fade); } @@ -255,6 +269,9 @@ protected: void PositionChanged(); void FocusChanged(TDrawNow aDrawNow); +protected: + void qwidgetResize_helper(const QSize &newSize); + private: void HandlePointerEvent(const TPointerEvent& aPointerEvent); TKeyResponse OfferKeyEvent(const TKeyEvent& aKeyEvent,TEventCode aType); @@ -294,6 +311,7 @@ private: #endif bool m_inExternalScreenOverride : 1; + bool m_lastStatusPaneVisibility : 1; }; inline QS60Data::QS60Data() @@ -326,6 +344,8 @@ inline QS60Data::QS60Data() #ifdef Q_OS_SYMBIAN ,s60InstalledTrapHandler(0) #endif + ,beginFullScreenCalled(0), + endFullScreenCalled(0) { } @@ -361,18 +381,15 @@ inline void QS60Data::updateScreenSize() // Look for a screen mode with rotation 0 // in order to decide what the native orientation is. - int nativeScreenWidthInPixels = 0; - int nativeScreenHeightInPixels = 0; for (mode = 0; mode < screenModeCount; ++mode) { TPixelsAndRotation sizeAndRotation; dev->GetScreenModeSizeAndRotation(mode, sizeAndRotation); if (sizeAndRotation.iRotation == CFbsBitGc::EGraphicsOrientationNormal) { - nativeScreenWidthInPixels = sizeAndRotation.iPixelSize.iWidth; - nativeScreenHeightInPixels = sizeAndRotation.iPixelSize.iHeight; + S60->nativeScreenWidthInPixels = sizeAndRotation.iPixelSize.iWidth; + S60->nativeScreenHeightInPixels = sizeAndRotation.iPixelSize.iHeight; break; } } - S60->nativeOrientationIsPortrait = nativeScreenWidthInPixels <= nativeScreenHeightInPixels; } inline RWsSession& QS60Data::wsSession() @@ -560,6 +577,49 @@ void qt_symbian_set_cursor_visible(bool visible); bool qt_symbian_is_cursor_visible(); #endif +static inline bool qt_beginFullScreenEffect() +{ +#if defined(Q_WS_S60) && defined(QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H) + // Only for post-S^3. On earlier versions the system transition effects + // may not be able to capture the non-Avkon content, leading to confusing + // looking effects, so just skip the whole thing. + if (S60->beginFullScreenCalled || QSysInfo::s60Version() <= QSysInfo::SV_S60_5_2) + return false; + S60->beginFullScreenCalled = true; + // For Avkon apps the app-exit effect is triggered from CAknAppUi::PrepareToExit(). + // That is good for Avkon apps, but in case of Qt the RWindows are destroyed earlier. + // Therefore we call BeginFullScreen() ourselves. + GfxTransEffect::BeginFullScreen(AknTransEffect::EApplicationExit, + TRect(0, 0, 0, 0), + AknTransEffect::EParameterType, + AknTransEffect::GfxTransParam(S60->uid, + AknTransEffect::TParameter::EAvkonCheck | KQtAppExitFlag)); + return true; +#else + return false; +#endif +} + +static inline void qt_abortFullScreenEffect() +{ +#if defined(Q_WS_S60) && defined(QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H) + if (!S60->beginFullScreenCalled || QSysInfo::s60Version() <= QSysInfo::SV_S60_5_2) + return; + GfxTransEffect::AbortFullScreen(); + S60->beginFullScreenCalled = S60->endFullScreenCalled = false; +#endif +} + +static inline void qt_endFullScreenEffect() +{ +#if defined(Q_WS_S60) && defined(QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H) + if (S60->endFullScreenCalled || QSysInfo::s60Version() <= QSysInfo::SV_S60_5_2) + return; + S60->endFullScreenCalled = true; + GfxTransEffect::EndFullScreen(); +#endif +} + QT_END_NAMESPACE #endif // QT_S60_P_H diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 9d9cd75..6cf5474 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -292,6 +292,7 @@ QWidgetPrivate::QWidgetPrivate(int version) #ifndef QT_NO_IM , inheritsInputMethodHints(0) #endif + , inSetParent(0) #if defined(Q_WS_X11) , picture(0) #elif defined(Q_WS_WIN) @@ -2563,6 +2564,22 @@ WId QWidget::effectiveWinId() const if (id || !testAttribute(Qt::WA_WState_Created)) return id; QWidget *realParent = nativeParentWidget(); + if (!realParent && d_func()->inSetParent) { + // In transitional state. This is really just a workaround. The real problem + // is that QWidgetPrivate::setParent_sys (platform specific code) first sets + // the window id to 0 (setWinId(0)) before it sets the Qt::WA_WState_Created + // attribute to false. The correct way is to do it the other way around, and + // in that case the Qt::WA_WState_Created logic above will kick in and + // return 0 whenever the widget is in a transitional state. However, changing + // the original logic for all platforms is far more intrusive and might + // break existing applications. + // Note: The widget can only be in a transitional state when changing its + // parent -- everything else is an internal error -- hence explicitly checking + // against 'inSetParent' rather than doing an unconditional return whenever + // 'realParent' is 0 (which may cause strange artifacts and headache later). + return 0; + } + // This widget *must* have a native parent widget. Q_ASSERT(realParent); Q_ASSERT(realParent->internalWinId()); return realParent->internalWinId(); @@ -10041,6 +10058,7 @@ void QWidget::setParent(QWidget *parent) void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) { Q_D(QWidget); + d->inSetParent = true; bool resized = testAttribute(Qt::WA_Resized); bool wasCreated = testAttribute(Qt::WA_WState_Created); QWidget *oldtlw = window(); @@ -10195,6 +10213,8 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) ancestorProxy->d_func()->embedSubWindow(this); } #endif + + d->inSetParent = false; } /*! diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 7e5173f..8784ffd 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -2794,6 +2794,11 @@ void QWidgetPrivate::transferChildren() #ifdef QT_MAC_USE_COCOA void QWidgetPrivate::setSubWindowStacking(bool set) { + // After hitting too many unforeseen bugs trying to put Qt on top of the cocoa child + // window API, we have decided to revert this behaviour as much as we can. We + // therefore now only allow child windows to exist for children of modal dialogs. + static bool use_behaviour_qt473 = !qgetenv("QT_MAC_USE_CHILDWINDOWS").isEmpty(); + // This will set/remove a visual relationship between parent and child on screen. // The reason for doing this is to ensure that a child always stacks infront of // its parent. Unfortunatly is turns out that [NSWindow addChildWindow] has @@ -2822,7 +2827,10 @@ void QWidgetPrivate::setSubWindowStacking(bool set) if (NSWindow *pwin = [qt_mac_nativeview_for(parent) window]) { if (set) { Qt::WindowType ptype = parent->window()->windowType(); - if ([pwin isVisible] && (ptype == Qt::Window || ptype == Qt::Dialog) && ![qwin parentWindow]) { + if ([pwin isVisible] + && (ptype == Qt::Window || ptype == Qt::Dialog) + && ![qwin parentWindow] + && (use_behaviour_qt473 || parent->windowModality() == Qt::ApplicationModal)) { NSInteger level = [qwin level]; [pwin addChildWindow:qwin ordered:NSWindowAbove]; if ([qwin level] < level) @@ -2834,6 +2842,10 @@ void QWidgetPrivate::setSubWindowStacking(bool set) } } + // Only set-up child windows for q if q is modal: + if (set && !use_behaviour_qt473 && q->windowModality() != Qt::ApplicationModal) + return; + QObjectList widgets = q->children(); for (int i=0; i<widgets.size(); ++i) { QWidget *child = qobject_cast<QWidget *>(widgets.at(i)); diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 377e3a7..7bf65f6 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -227,6 +227,7 @@ struct QTLWExtra { #elif defined(Q_OS_SYMBIAN) uint inExpose : 1; // Prevents drawing recursion uint nativeWindowTransparencyEnabled : 1; // Tracks native window transparency + uint forcedToRaster : 1; #endif }; @@ -759,6 +760,7 @@ public: #ifndef QT_NO_IM uint inheritsInputMethodHints : 1; #endif + uint inSetParent : 1; // *************************** Platform specific ************************************ #if defined(Q_WS_X11) // <----------------------------------------------------------- X11 diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index e7d5e95..8ca29cd 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -563,6 +563,11 @@ void QWidgetPrivate::show_sys() if (isFullscreen) { const bool cbaVisible = S60->buttonGroupContainer() && S60->buttonGroupContainer()->IsVisible(); S60->setStatusPaneAndButtonGroupVisibility(false, cbaVisible); + if (cbaVisible) { + // Fix window dimensions as without screen furniture they will have + // defaulted to full screen dimensions initially. + id->handleClientAreaChange(); + } } } } @@ -777,7 +782,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) adjustFlags(data.window_flags, q); // keep compatibility with previous versions, we need to preserve the created state // (but we recreate the winId for the widget being reparented, again for compatibility) - if (wasCreated || (!q->isWindow() && parent->testAttribute(Qt::WA_WState_Created))) + if (wasCreated || (!q->isWindow() && parent && parent->testAttribute(Qt::WA_WState_Created))) createWinId(); if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden) q->setAttribute(Qt::WA_WState_Hidden); @@ -820,7 +825,8 @@ void QWidgetPrivate::s60UpdateIsOpaque() RWindow *const window = static_cast<RWindow *>(q->effectiveWinId()->DrawableWindow()); #ifdef Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE - if (QApplicationPrivate::instance()->useTranslucentEGLSurfaces) { + if (QApplicationPrivate::instance()->useTranslucentEGLSurfaces + && !extra->topextra->forcedToRaster) { window->SetSurfaceTransparency(!isOpaque); extra->topextra->nativeWindowTransparencyEnabled = !isOpaque; return; @@ -838,6 +844,8 @@ void QWidgetPrivate::s60UpdateIsOpaque() // recreate backing store to get translucent surface (raster surface). extra->topextra->backingStore.create(q); extra->topextra->backingStore.registerWidget(q); + // FixNativeOrientation() will not work without an EGL surface. + q->setAttribute(Qt::WA_SymbianNoSystemRotation, false); } } } else if (extra->topextra->nativeWindowTransparencyEnabled) { @@ -1002,6 +1010,7 @@ void QWidgetPrivate::createTLSysExtra() { extra->topextra->inExpose = 0; extra->topextra->nativeWindowTransparencyEnabled = 0; + extra->topextra->forcedToRaster = 0; } void QWidgetPrivate::deleteTLSysExtra() @@ -1206,41 +1215,10 @@ void QWidget::setWindowState(Qt::WindowStates newstate) } #ifdef Q_WS_S60 - // Hide window decoration when switching to fullscreen / minimized otherwise show decoration. // 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 unnecessary redraws - Qt::WindowStates comparisonState = newstate; - QWidget *parentWindow = parentWidget(); - if (parentWindow) { - while (parentWindow->parentWidget()) - parentWindow = parentWindow->parentWidget(); - comparisonState = parentWindow->windowState(); - } else { - parentWindow = this; - } - - const bool decorationsVisible = !(comparisonState & (Qt::WindowFullScreen | Qt::WindowMinimized)); - const bool parentIsFullscreen = comparisonState & Qt::WindowFullScreen; - const bool parentCbaVisibilityHint = parentWindow->windowFlags() & Qt::WindowSoftkeysVisibleHint; - bool buttonGroupVisibility = (decorationsVisible || (parentIsFullscreen && parentCbaVisibilityHint)); - - // For non-toplevel normal and maximized windows, show cba if window has softkey - // actions even if topmost parent is not showing cba. Do the same for fullscreen - // windows that request it. - if (!buttonGroupVisibility - && parentWidget() - && !(newstate & Qt::WindowMinimized) - && ((windowFlags() & Qt::WindowSoftkeysVisibleHint) || !(newstate & Qt::WindowFullScreen))) { - for (int i = 0; i < actions().size(); ++i) { - if (actions().at(i)->softKeyRole() != QAction::NoSoftKey) { - buttonGroupVisibility = true; - break; - } - } - } - S60->setStatusPaneAndButtonGroupVisibility(decorationsVisible, buttonGroupVisibility); - + bool decorationsVisible = S60->setRecursiveDecorationsVisibility(this, newstate); #endif // Q_WS_S60 // Ensure the initial size is valid, since we store it as normalGeometry below. @@ -1451,7 +1429,8 @@ void QWidget::activateWindow() if (tlw->isVisible()) { window()->createWinId(); QSymbianControl *id = static_cast<QSymbianControl *>(tlw->internalWinId()); - id->setFocusSafely(true); + if (!id->IsFocused()) + id->setFocusSafely(true); } } diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index bd37d9f..b3b647a 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -9,6 +9,7 @@ HEADERS += \ painting/qdrawutil.h \ painting/qemulationpaintengine_p.h \ painting/qgraphicssystem_p.h \ + painting/qgraphicssystemex_p.h \ painting/qmatrix.h \ painting/qmemrotate_p.h \ painting/qoutlinemapper_p.h \ @@ -235,8 +236,10 @@ embedded { symbian { HEADERS += painting/qwindowsurface_s60_p.h \ - painting/qdrawhelper_arm_simd_p.h - SOURCES += painting/qwindowsurface_s60.cpp + painting/qdrawhelper_arm_simd_p.h \ + painting/qgraphicssystemex_symbian_p.h + SOURCES += painting/qwindowsurface_s60.cpp \ + painting/qgraphicssystemex_symbian.cpp armccIfdefBlock = \ "$${LITERAL_HASH}if defined(ARMV6)" \ "MACRO QT_HAVE_ARM_SIMD" \ diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index dc61e34..8f965c2 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -49,6 +49,7 @@ #include "qdebug.h" #include <QtCore/qcoreapplication.h> #include "private/qstylehelper_p.h" +#include <QtCore/qnumeric.h> QT_BEGIN_NAMESPACE @@ -1360,13 +1361,14 @@ QGradient::QGradient() void QGradient::setColorAt(qreal pos, const QColor &color) { - if (pos > 1 || pos < 0) { + if ((pos > 1 || pos < 0) && !qIsNaN(pos)) { qWarning("QGradient::setColorAt: Color position must be specified in the range 0 to 1"); return; } int index = 0; - while (index < m_stops.size() && m_stops.at(index).first < pos) ++index; + if (!qIsNaN(pos)) + while (index < m_stops.size() && m_stops.at(index).first < pos) ++index; if (index < m_stops.size() && m_stops.at(index).first == pos) m_stops[index].second = color; diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp index 00b103d..debca37 100644 --- a/src/gui/painting/qdrawhelper_neon.cpp +++ b/src/gui/painting/qdrawhelper_neon.cpp @@ -327,10 +327,8 @@ void qt_blend_argb32_on_rgb16_neon(uchar *destPixels, int dbpl, blend_8_pixels_argb32_on_rgb16_neon(dstBuffer, srcBuffer, const_alpha); - for (int j = 0; j < tail; ++j) { + for (int j = 0; j < tail; ++j) dst[i + j] = dstBuffer[j]; - src[i + j] = srcBuffer[j]; - } } dst = (quint16 *)(((uchar *) dst) + dbpl); diff --git a/src/gui/painting/qgraphicssystem.cpp b/src/gui/painting/qgraphicssystem.cpp index 5112019..4b79600 100644 --- a/src/gui/painting/qgraphicssystem.cpp +++ b/src/gui/painting/qgraphicssystem.cpp @@ -52,6 +52,9 @@ #endif #ifdef Q_OS_SYMBIAN # include <private/qpixmap_s60_p.h> +# include <private/qgraphicssystemex_symbian_p.h> +#else +# include <private/qgraphicssystemex_p.h> #endif QT_BEGIN_NAMESPACE @@ -84,9 +87,18 @@ QPixmapData *QGraphicsSystem::createPixmapData(QPixmapData *origin) return createPixmapData(origin->pixelType()); } -void QGraphicsSystem::releaseCachedResources() +#ifdef Q_OS_SYMBIAN +Q_GLOBAL_STATIC(QSymbianGraphicsSystemEx, symbianPlatformExtension) +#endif + +QGraphicsSystemEx* QGraphicsSystem::platformExtension() { - // Do nothing here +#ifdef Q_OS_SYMBIAN + // this is used on raster graphics systems. HW accelerated + // graphics systems will overwrite this function. + return symbianPlatformExtension(); +#endif + return 0; } QT_END_NAMESPACE diff --git a/src/gui/painting/qgraphicssystem_p.h b/src/gui/painting/qgraphicssystem_p.h index 80e8959..d5acaa4 100644 --- a/src/gui/painting/qgraphicssystem_p.h +++ b/src/gui/painting/qgraphicssystem_p.h @@ -59,6 +59,7 @@ QT_BEGIN_NAMESPACE class QPixmapFilter; +class QGraphicsSystemEx; class Q_GUI_EXPORT QGraphicsSystem { @@ -73,7 +74,7 @@ public: // to have a graphics system. static QPixmapData *createDefaultPixmapData(QPixmapData::PixelType type); - virtual void releaseCachedResources(); + virtual QGraphicsSystemEx* platformExtension(); }; QT_END_NAMESPACE diff --git a/src/gui/painting/qgraphicssystemex_p.h b/src/gui/painting/qgraphicssystemex_p.h new file mode 100644 index 0000000..6feb116 --- /dev/null +++ b/src/gui/painting/qgraphicssystemex_p.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSYSTEMEX_P_H +#define QGRAPHICSSYSTEMEX_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <qglobal.h> + +QT_BEGIN_NAMESPACE + +class Q_GUI_EXPORT QGraphicsSystemEx +{ +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/gui/painting/qgraphicssystemex_symbian.cpp b/src/gui/painting/qgraphicssystemex_symbian.cpp new file mode 100644 index 0000000..54d21ac --- /dev/null +++ b/src/gui/painting/qgraphicssystemex_symbian.cpp @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 "qgraphicssystemex_symbian_p.h" +#include "private/qwidget_p.h" +#include "private/qbackingstore_p.h" +#include "private/qapplication_p.h" +#include "qwidget_p.h" + +#include <QDebug> + +QT_BEGIN_NAMESPACE + +void QSymbianGraphicsSystemEx::releaseCachedGpuResources() +{ + // Do nothing here + // This is implemented in graphics system specific plugin +} + +void QSymbianGraphicsSystemEx::releaseAllGpuResources() +{ + releaseCachedGpuResources(); + + foreach (QWidget *widget, QApplication::topLevelWidgets()) { + if (QTLWExtra *topExtra = qt_widget_private(widget)->maybeTopData()) + topExtra->backingStore.destroy(); + } +} + +bool QSymbianGraphicsSystemEx::hasBCM2727() +{ + return !QApplicationPrivate::instance()->useTranslucentEGLSurfaces; +} + +void QSymbianGraphicsSystemEx::forceToRaster(QWidget *window) +{ + if (window && window->isWindow()) { + qt_widget_private(window)->createTLExtra(); + if (QTLWExtra *topExtra = qt_widget_private(window)->maybeTopData()) { + topExtra->forcedToRaster = 1; + if (topExtra->backingStore.data()) { + topExtra->backingStore.create(window); + topExtra->backingStore.registerWidget(window); + } + } + } +} + +QT_END_NAMESPACE diff --git a/src/gui/painting/qgraphicssystemex_symbian_p.h b/src/gui/painting/qgraphicssystemex_symbian_p.h new file mode 100644 index 0000000..0b1e39e --- /dev/null +++ b/src/gui/painting/qgraphicssystemex_symbian_p.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSYMBIANGRAPHICSSYSTEMEX_P_H +#define QSYMBIANGRAPHICSSYSTEMEX_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "private/qgraphicssystemex_p.h" + +QT_BEGIN_NAMESPACE + +class QWidget; + +class Q_GUI_EXPORT QSymbianGraphicsSystemEx : public QGraphicsSystemEx +{ +public: + virtual void releaseCachedGpuResources(); + virtual void releaseAllGpuResources(); + virtual bool hasBCM2727(); + virtual void forceToRaster(QWidget *window); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/gui/painting/qpaintengine_mac.cpp b/src/gui/painting/qpaintengine_mac.cpp index c3aac1b..b07053e 100644 --- a/src/gui/painting/qpaintengine_mac.cpp +++ b/src/gui/painting/qpaintengine_mac.cpp @@ -969,7 +969,7 @@ void QCoreGraphicsPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, co return; bool differentSize = (QRectF(0, 0, pm.width(), pm.height()) != sr), doRestore = false; - CGRect rect = CGRectMake(qRound(r.x()), qRound(r.y()), qRound(r.width()), qRound(r.height())); + CGRect rect = CGRectMake(r.x(), r.y(), r.width(), r.height()); QCFType<CGImageRef> image; bool isBitmap = (pm.depth() == 1); if (isBitmap) { diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 76ac7db..3735e7c 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -95,10 +95,10 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const const 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); +Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(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) { @@ -5937,9 +5937,9 @@ void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText } d->extended->drawStaticTextItem(item); - drawDecorationForGlyphs(this, item->glyphs, item->glyphPositions, - item->numGlyphs, item->fontEngine(), staticText_d->font, - QTextCharFormat()); + qt_draw_decoration_for_glyphs(this, item->glyphs, item->glyphPositions, + item->numGlyphs, item->fontEngine(), staticText_d->font, + QTextCharFormat()); } if (currentColor != oldPen.color()) setPen(oldPen); @@ -6383,10 +6383,10 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const 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) +Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(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; @@ -8097,12 +8097,16 @@ start_lengthVariant: QTextLine line = textLayout.lineAt(i); qreal advance = line.horizontalAdvance(); - if (tf & Qt::AlignRight) - xoff = r.width() - advance; + xoff = 0; + if (tf & Qt::AlignRight) { + QTextEngine *eng = textLayout.engine(); + xoff = r.width() - advance - + eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal(); + } else if (tf & Qt::AlignHCenter) - xoff = (r.width() - advance)/2; + xoff = (r.width() - advance) / 2; - line.draw(painter, QPointF(r.x() + xoff + line.x(), r.y() + yoff)); + line.draw(painter, QPointF(r.x() + xoff, r.y() + yoff)); } if (restore) { diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 0bb2901..4744cb5 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -628,10 +628,14 @@ void QPainterPath::moveTo(const QPointF &p) #ifdef QPP_DEBUG printf("QPainterPath::moveTo() (%.2f,%.2f)\n", p.x(), p.y()); #endif + + if (!qt_is_finite(p.x()) || !qt_is_finite(p.y())) { #ifndef QT_NO_DEBUG - if (qt_is_nan(p.x()) || qt_is_nan(p.y())) - qWarning("QPainterPath::moveTo: Adding point where x or y is NaN, results are undefined"); + qWarning("QPainterPath::moveTo: Adding point where x or y is NaN or Inf, ignoring call"); #endif + return; + } + ensureData(); detach(); @@ -674,10 +678,14 @@ void QPainterPath::lineTo(const QPointF &p) #ifdef QPP_DEBUG printf("QPainterPath::lineTo() (%.2f,%.2f)\n", p.x(), p.y()); #endif + + if (!qt_is_finite(p.x()) || !qt_is_finite(p.y())) { #ifndef QT_NO_DEBUG - if (qt_is_nan(p.x()) || qt_is_nan(p.y())) - qWarning("QPainterPath::lineTo: Adding point where x or y is NaN, results are undefined"); + qWarning("QPainterPath::lineTo: Adding point where x or y is NaN or Inf, ignoring call"); #endif + return; + } + ensureData(); detach(); @@ -729,11 +737,15 @@ void QPainterPath::cubicTo(const QPointF &c1, const QPointF &c2, const QPointF & printf("QPainterPath::cubicTo() (%.2f,%.2f), (%.2f,%.2f), (%.2f,%.2f)\n", c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y()); #endif + + if (!qt_is_finite(c1.x()) || !qt_is_finite(c1.y()) || !qt_is_finite(c2.x()) || !qt_is_finite(c2.y()) + || !qt_is_finite(e.x()) || !qt_is_finite(e.y())) { #ifndef QT_NO_DEBUG - if (qt_is_nan(c1.x()) || qt_is_nan(c1.y()) || qt_is_nan(c2.x()) || qt_is_nan(c2.y()) - || qt_is_nan(e.x()) || qt_is_nan(e.y())) - qWarning("QPainterPath::cubicTo: Adding point where x or y is NaN, results are undefined"); + qWarning("QPainterPath::cubicTo: Adding point where x or y is NaN or Inf, ignoring call"); #endif + return; + } + ensureData(); detach(); @@ -782,10 +794,14 @@ void QPainterPath::quadTo(const QPointF &c, const QPointF &e) printf("QPainterPath::quadTo() (%.2f,%.2f), (%.2f,%.2f)\n", c.x(), c.y(), e.x(), e.y()); #endif + + if (!qt_is_finite(c.x()) || !qt_is_finite(c.y()) || !qt_is_finite(e.x()) || !qt_is_finite(e.y())) { #ifndef QT_NO_DEBUG - if (qt_is_nan(c.x()) || qt_is_nan(c.y()) || qt_is_nan(e.x()) || qt_is_nan(e.y())) - qWarning("QPainterPath::quadTo: Adding point where x or y is NaN, results are undefined"); + qWarning("QPainterPath::quadTo: Adding point where x or y is NaN or Inf, ignoring call"); #endif + return; + } + ensureData(); detach(); @@ -849,11 +865,15 @@ void QPainterPath::arcTo(const QRectF &rect, qreal startAngle, qreal sweepLength printf("QPainterPath::arcTo() (%.2f, %.2f, %.2f, %.2f, angle=%.2f, sweep=%.2f\n", rect.x(), rect.y(), rect.width(), rect.height(), startAngle, sweepLength); #endif + + if (!qt_is_finite(rect.x()) && !qt_is_finite(rect.y()) || !qt_is_finite(rect.width()) || !qt_is_finite(rect.height()) + || !qt_is_finite(startAngle) || !qt_is_finite(sweepLength)) { #ifndef QT_NO_DEBUG - if (qt_is_nan(rect.x()) || qt_is_nan(rect.y()) || qt_is_nan(rect.width()) || qt_is_nan(rect.height()) - || qt_is_nan(startAngle) || qt_is_nan(sweepLength)) - qWarning("QPainterPath::arcTo: Adding arc where a parameter is NaN, results are undefined"); + qWarning("QPainterPath::arcTo: Adding arc where a parameter is NaN or Inf, ignoring call"); #endif + return; + } + if (rect.isNull()) return; @@ -952,10 +972,13 @@ QPointF QPainterPath::currentPosition() const */ void QPainterPath::addRect(const QRectF &r) { + if (!qt_is_finite(r.x()) || !qt_is_finite(r.y()) || !qt_is_finite(r.width()) || !qt_is_finite(r.height())) { #ifndef QT_NO_DEBUG - if (qt_is_nan(r.x()) || qt_is_nan(r.y()) || qt_is_nan(r.width()) || qt_is_nan(r.height())) - qWarning("QPainterPath::addRect: Adding rect where a parameter is NaN, results are undefined"); + qWarning("QPainterPath::addRect: Adding rect where a parameter is NaN or Inf, ignoring call"); #endif + return; + } + if (r.isNull()) return; @@ -1032,11 +1055,14 @@ void QPainterPath::addPolygon(const QPolygonF &polygon) */ void QPainterPath::addEllipse(const QRectF &boundingRect) { + if (!qt_is_finite(boundingRect.x()) || !qt_is_finite(boundingRect.y()) + || !qt_is_finite(boundingRect.width()) || !qt_is_finite(boundingRect.height())) { #ifndef QT_NO_DEBUG - if (qt_is_nan(boundingRect.x()) || qt_is_nan(boundingRect.y()) - || qt_is_nan(boundingRect.width()) || qt_is_nan(boundingRect.height())) - qWarning("QPainterPath::addEllipse: Adding ellipse where a parameter is NaN, results are undefined"); + qWarning("QPainterPath::addEllipse: Adding ellipse where a parameter is NaN or Inf, ignoring call"); #endif + return; + } + if (boundingRect.isNull()) return; @@ -2358,10 +2384,12 @@ QDataStream &operator>>(QDataStream &s, QPainterPath &p) s >> x; s >> y; Q_ASSERT(type >= 0 && type <= 3); + if (!qt_is_finite(x) || !qt_is_finite(y)) { #ifndef QT_NO_DEBUG - if (qt_is_nan(x) || qt_is_nan(y)) - qWarning("QDataStream::operator>>: Adding a NaN element to path, results are undefined"); + qWarning("QDataStream::operator>>: NaN or Inf element found in path, skipping it"); #endif + continue; + } QPainterPath::Element elm = { x, y, QPainterPath::ElementType(type) }; p.d_func()->elements.append(elm); } diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index 2420f31..3918ffc 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -178,7 +178,7 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g) const { #if defined(Q_WS_X11) - if (m_transform.type() > QTransform::TxTranslate) { + if (m_transform.type() > QTransform::TxTranslate && m_current_fontengine->type() == QFontEngine::Freetype) { QFontEngineFT::GlyphFormat format = QFontEngineFT::Format_None; QImage::Format imageFormat = QImage::Format_Invalid; switch (m_type) { diff --git a/src/gui/s60framework/qs60mainappui.cpp b/src/gui/s60framework/qs60mainappui.cpp index b5b8b81..4842bc5 100644 --- a/src/gui/s60framework/qs60mainappui.cpp +++ b/src/gui/s60framework/qs60mainappui.cpp @@ -61,6 +61,7 @@ //Animated wallpapers in Qt applications are not supported. const TInt KAknDisableAnimationBackground = 0x02000000; +const TInt KAknSingleClickCompatible = 0x01000000; QT_BEGIN_NAMESPACE @@ -117,8 +118,12 @@ void QS60MainAppUi::ConstructL() // After 5th Edition S60, native side supports animated wallpapers. // However, there is no support for that feature on Qt side, so indicate to // native UI framework that this application will not support background animations. - if (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0) - flags |= KAknDisableAnimationBackground; + + // Also, add support for single touch for post 5th edition platforms. + // This has only impact when launching native dialogs/menus from inside QApplication. + if (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0) { + flags |= (KAknDisableAnimationBackground | KAknSingleClickCompatible); + } #endif BaseConstructL(flags); } diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index da1528e..9958316 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -72,6 +72,7 @@ #include "qcheckbox.h" #include "qdesktopwidget.h" #include "qprogressbar.h" +#include "qlabel.h" #include "private/qtoolbarextension_p.h" #include "private/qcombobox_p.h" @@ -683,6 +684,13 @@ void QS60StylePrivate::setThemePalette(QWidget *widget) if (header->viewport()) header->viewport()->setPalette(widgetPalette); QApplication::setPalette(widgetPalette, "QHeaderView"); + } else if (qobject_cast<QLabel *>(widget)) { + if (widget->window() && widget->window()->windowType() == Qt::Dialog) { + QPalette widgetPalette = widget->palette(); + widgetPalette.setColor(QPalette::WindowText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 19, 0)); + widget->setPalette(widgetPalette); + } } } @@ -957,6 +965,17 @@ bool QS60StylePrivate::isWidgetPressed(const QWidget *widget) return (widget && widget == m_pressedWidget); } +// Generates 1*1 white pixmap as a placeholder for real texture. +// The actual theme texture is drawn in qt_s60_fill_background(). +QPixmap QS60StylePrivate::placeHolderTexture() +{ + if (!m_placeHolderTexture) { + m_placeHolderTexture = new QPixmap(1,1); + m_placeHolderTexture->fill(Qt::green); + } + return *m_placeHolderTexture; +} + /*! \class QS60Style \brief The QS60Style class provides a look and feel suitable for applications on S60. @@ -1542,8 +1561,10 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, skinElement==QS60StylePrivate::SE_TabBarTabWestActive) { const int borderThickness = QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth); - const int tabOverlap = - QS60StylePrivate::pixelMetric(PM_TabBarTabOverlap) - borderThickness; + int tabOverlap = pixelMetric(PM_TabBarTabOverlap); + if (tabOverlap > borderThickness) + tabOverlap -= borderThickness; + const bool usesScrollButtons = (widget) ? (qobject_cast<const QTabBar*>(widget))->usesScrollButtons() : false; const int roomForScrollButton = @@ -1582,9 +1603,11 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, QStyleOptionTabV3 optionTab = *tab; QRect tr = optionTab.rect; const bool directionMirrored = (optionTab.direction == Qt::RightToLeft); - const int borderThickness = QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth); - const int tabOverlap = - QS60StylePrivate::pixelMetric(PM_TabBarTabOverlap) - borderThickness; + const int borderThickness = + QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth); + int tabOverlap = pixelMetric(PM_TabBarTabOverlap); + if (tabOverlap > borderThickness) + tabOverlap -= borderThickness; const bool usesScrollButtons = (widget) ? (qobject_cast<const QTabBar*>(widget))->usesScrollButtons() : false; const int roomForScrollButton = @@ -2282,8 +2305,9 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti //Need extra check since dialogs have their own theme background if (QS60StylePrivate::canDrawThemeBackground(option->palette.base(), widget) && QS60StylePrivate::equalToThemePalette(option->palette.window().texture().cacheKey(), QPalette::Window)) { + const bool comboMenu = qobject_cast<const QComboBoxListView *>(widget); // Add margin area to the background, to avoid background being cut for first and last item. - const int verticalMenuAdjustment = QS60StylePrivate::pixelMetric(PM_MenuVMargin); + const int verticalMenuAdjustment = comboMenu ? QS60StylePrivate::pixelMetric(PM_MenuVMargin) : 0; const QRect adjustedMenuRect = option->rect.adjusted(0, -verticalMenuAdjustment, 0, verticalMenuAdjustment); QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_PopupBackground, painter, adjustedMenuRect, flags); } else { @@ -2532,6 +2556,11 @@ int QS60Style::pixelMetric(PixelMetric metric, const QStyleOption *option, const //without having to define custom pixel metric metricValue *= 2; +#if defined(Q_WS_S60) + if (metric == PM_TabBarTabOverlap && (QSysInfo::s60Version() > QSysInfo::SV_S60_5_2)) + metricValue = 0; +#endif + return metricValue; } @@ -2641,13 +2670,11 @@ QSize QS60Style::sizeFromContents(ContentsType ct, const QStyleOption *opt, case CT_ItemViewItem: if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) { if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { - sz = QSize(menuItem->rect.width(), 1); + sz = QSize(menuItem->rect.width() - 2 * pixelMetric(PM_MenuHMargin) - 2 * QS60StylePrivate::pixelMetric(PM_FrameCornerWidth), 1); break; } } sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget); - //native items have small empty areas at the beginning and end of menu item - sz.setWidth(sz.width() + 2 * pixelMetric(PM_MenuHMargin) + 2 * QS60StylePrivate::pixelMetric(PM_FrameCornerWidth)); if (QS60StylePrivate::isTouchSupported()) { //Make itemview easier to use in touch devices sz.setHeight(sz.height() + 2 * pixelMetric(PM_FocusFrameVMargin)); @@ -3006,10 +3033,11 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con ret = QCommonStyle::subElementRect(element, opt, widget); if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) { - const int tabOverlapNoBorder = - QS60StylePrivate::pixelMetric(PM_TabBarTabOverlap); - const int tabOverlap = - tabOverlapNoBorder - QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth); + const int borderThickness = + QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth); + int tabOverlap = pixelMetric(PM_TabBarTabOverlap); + if (tabOverlap > borderThickness) + tabOverlap -= borderThickness; const QTabWidget *tab = qobject_cast<const QTabWidget *>(widget); int gain = (tab) ? tabOverlap * tab->count() : 0; switch (twf->shape) { @@ -3027,7 +3055,7 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con if ((ret.right() + gain) > widget->rect().right()) gain = widget->rect().right() - ret.right(); ret.adjust(0, 0, gain, 0); - } + } } break; } @@ -3115,7 +3143,7 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con } break; case SE_ItemViewItemCheckIndicator: - if (const QStyleOptionViewItemV2 *vopt = qstyleoption_cast<const QStyleOptionViewItemV2 *>(opt)) { + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(opt)) { const QAbstractItemView *listItem = qobject_cast<const QAbstractItemView *>(widget); const bool singleSelection = listItem && @@ -3123,7 +3151,7 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con listItem->selectionMode() == QAbstractItemView::NoSelection); const bool checkBoxOnly = (vopt->features & QStyleOptionViewItemV2::HasCheckIndicator) && listItem && - singleSelection; + singleSelection && vopt->text.isEmpty() && vopt->icon.isNull(); // Selection check mark rect. const int indicatorWidth = QS60StylePrivate::pixelMetric(PM_IndicatorWidth); diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp index 6a7158c..7f19c35 100644 --- a/src/gui/styles/qs60style_s60.cpp +++ b/src/gui/styles/qs60style_s60.cpp @@ -89,17 +89,25 @@ enum TSupportRelease { ES60_5_0 = 0x0004, ES60_5_1 = 0x0008, ES60_5_2 = 0x0010, + ES60_5_3 = 0x0020, ES60_3_X = ES60_3_1 | ES60_3_2, // Releases before Symbian Foundation ES60_PreSF = ES60_3_1 | ES60_3_2 | ES60_5_0, + // Releases before the S60 5.2 + ES60_Pre52 = ES60_3_1 | ES60_3_2 | ES60_5_0 | ES60_5_1, + // Releases before S60 5.3 + ES60_Pre53 = ES60_3_1 | ES60_3_2 | ES60_5_0 | ES60_5_1 | ES60_5_2, // Add all new releases here - ES60_All = ES60_3_1 | ES60_3_2 | ES60_5_0 | ES60_5_1 | ES60_5_2 + ES60_All = ES60_3_1 | ES60_3_2 | ES60_5_0 | ES60_5_1 | ES60_5_2 | ES60_5_3 }; typedef struct { - const TAknsItemID &skinID; - TDrawType drawType; - int supportInfo; + const TAknsItemID &skinID; // Determines default theme graphics ID. + TDrawType drawType; // Determines which native drawing routine is used to draw this item. + int supportInfo; // Defines the S60 versions that use the default graphics. + // These two, define new graphics that are used in releases other than partMapEntry.supportInfo defined releases. + // In general, these are given in numeric form to allow style compilation in earlier + // native releases that do not contain the new graphics. int newMajorSkinId; int newMinorSkinId; } partMapEntry; @@ -188,12 +196,14 @@ const partMapEntry QS60StyleModeSpecifics::m_partMap[] = { /* SP_QgnGrafScrollArrowLeft */ {KAknsIIDQgnGrafScrollArrowLeft, EDrawGulIcon, ES60_All, -1,-1}, /* SP_QgnGrafScrollArrowRight */ {KAknsIIDQgnGrafScrollArrowRight, EDrawGulIcon, ES60_All, -1,-1}, /* SP_QgnGrafScrollArrowUp */ {KAknsIIDQgnGrafScrollArrowUp, EDrawGulIcon, ES60_All, -1,-1}, - /* SP_QgnGrafTabActiveL */ {KAknsIIDQgnGrafTabActiveL, EDrawIcon, ES60_All, -1,-1}, - /* SP_QgnGrafTabActiveM */ {KAknsIIDQgnGrafTabActiveM, EDrawIcon, ES60_All, -1,-1}, - /* SP_QgnGrafTabActiveR */ {KAknsIIDQgnGrafTabActiveR, EDrawIcon, ES60_All, -1,-1}, - /* SP_QgnGrafTabPassiveL */ {KAknsIIDQgnGrafTabPassiveL, EDrawIcon, ES60_All, -1,-1}, - /* SP_QgnGrafTabPassiveM */ {KAknsIIDQgnGrafTabPassiveM, EDrawIcon, ES60_All, -1,-1}, - /* SP_QgnGrafTabPassiveR */ {KAknsIIDQgnGrafTabPassiveR, EDrawIcon, ES60_All, -1,-1}, + + // In S60 5.3 there is a new tab graphic + /* SP_QgnGrafTabActiveL */ {KAknsIIDQgnGrafTabActiveL, EDrawIcon, ES60_Pre53, EAknsMajorSkin, 0x2219}, //KAknsIIDQtgFrTabActiveNormalL + /* SP_QgnGrafTabActiveM */ {KAknsIIDQgnGrafTabActiveM, EDrawIcon, ES60_Pre53, EAknsMajorSkin, 0x221b}, //KAknsIIDQtgFrTabActiveNormalC + /* SP_QgnGrafTabActiveR */ {KAknsIIDQgnGrafTabActiveR, EDrawIcon, ES60_Pre53, EAknsMajorSkin, 0x221a}, //KAknsIIDQtgFrTabActiveNormalR + /* SP_QgnGrafTabPassiveL */ {KAknsIIDQgnGrafTabPassiveL, EDrawIcon, ES60_Pre53, EAknsMajorSkin, 0x2221}, //KAknsIIDQtgFrTabPassiveNormalL + /* SP_QgnGrafTabPassiveM */ {KAknsIIDQgnGrafTabPassiveM, EDrawIcon, ES60_Pre53, EAknsMajorSkin, 0x2223}, //KAknsIIDQtgFrTabPassiveNormalC + /* SP_QgnGrafTabPassiveR */ {KAknsIIDQgnGrafTabPassiveR, EDrawIcon, ES60_Pre53, EAknsMajorSkin, 0x2222}, //KAknsIIDQtgFrTabPassiveNormalR // In 3.1 there is no slider groove. /* SP_QgnGrafNsliderEndLeft */ {KAknsIIDNone, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x19cf /* KAknsIIDQgnGrafNsliderEndLeft */}, @@ -1140,7 +1150,8 @@ bool QS60StyleModeSpecifics::checkSupport(const int supportedRelease) (currentRelease == QSysInfo::SV_S60_3_2 && supportedRelease & ES60_3_2) || (currentRelease == QSysInfo::SV_S60_5_0 && supportedRelease & ES60_5_0) || (currentRelease == QSysInfo::SV_S60_5_1 && supportedRelease & ES60_5_1) || - (currentRelease == QSysInfo::SV_S60_5_2 && supportedRelease & ES60_5_2)); + (currentRelease == QSysInfo::SV_S60_5_2 && supportedRelease & ES60_5_2) || + (currentRelease == QSysInfo::SV_S60_5_3 && supportedRelease & ES60_5_3) ); } TAknsItemID QS60StyleModeSpecifics::partSpecificThemeId(int part) @@ -1429,17 +1440,6 @@ QPixmap QS60StylePrivate::backgroundTexture(bool skipCreation) return *m_background; } -// Generates 1*1 white pixmap as a placeholder for real texture. -// The actual theme texture is drawn in qt_s60_fill_background(). -QPixmap QS60StylePrivate::placeHolderTexture() -{ - if (!m_placeHolderTexture) { - m_placeHolderTexture = new QPixmap(1,1); - m_placeHolderTexture->fill(Qt::white); - } - return *m_placeHolderTexture; -} - QSize QS60StylePrivate::screenSize() { return QSize(S60->screenWidthInPixels, S60->screenHeightInPixels); diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index a4e7c38..369a0f0 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -3339,6 +3339,13 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q } break; + case CE_FocusFrame: + if (!rule.hasNativeBorder()) { + rule.drawBorder(p, opt->rect); + return; + } + break; + case CE_PushButton: if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) { if (rule.hasDrawable() || rule.hasBox() || rule.hasPosition() || rule.hasPalette() || diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index e89b508..9c90964 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -1800,10 +1800,12 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matr } else { glyphSet = &defaultGlyphSet; } + bool needsDelete = false; Glyph * g = glyphSet->getGlyph(glyph); if (!g) { face = lockFace(); g = loadGlyphMetrics(glyphSet, glyph); + needsDelete = true; } if (g) { @@ -1812,6 +1814,8 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matr overall.width = g->width; overall.height = g->height; overall.xoff = g->advance; + if (needsDelete) + delete g; } else { int left = FLOOR(face->glyph->metrics.horiBearingX); int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width); diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm index 42b9402..05e3d3c 100644 --- a/src/gui/text/qfontengine_mac.mm +++ b/src/gui/text/qfontengine_mac.mm @@ -144,7 +144,7 @@ void qmacfontengine_gamma_correct(QImage *image) #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 -QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const ATSFontFamilyRef &, const ATSFontRef &atsFontRef, const QFontDef &fontDef, bool kerning) +QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const ATSFontFamilyRef &atsFamilyRef, const ATSFontRef &atsFontRef, const QFontDef &fontDef, bool kerning) : QFontEngineMulti(0) { this->fontDef = fontDef; @@ -162,6 +162,8 @@ QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const ATSFontFamilyRef &, con QCFString name; ATSFontGetName(atsFontRef, kATSOptionFlagsDefault, &name); + if (QString(name).isEmpty()) + ATSFontFamilyGetName(atsFamilyRef, kATSOptionFlagsDefault, &name); transform = CGAffineTransformIdentity; if (fontDef.stretch != 100) { diff --git a/src/gui/text/qfragmentmap_p.h b/src/gui/text/qfragmentmap_p.h index 501bfff..4057142 100644 --- a/src/gui/text/qfragmentmap_p.h +++ b/src/gui/text/qfragmentmap_p.h @@ -195,6 +195,10 @@ public: head->root = new_root; } + inline bool isValid(uint n) const { + return n > 0 && n != head->freelist; + } + union { Header *head; Fragment *fragments; @@ -854,6 +858,7 @@ public: return data.fragment(index); } inline uint position(uint node, uint field = 0) const { return data.position(node, field); } + inline bool isValid(uint n) const { return data.isValid(n); } inline uint next(uint n) const { return data.next(n); } inline uint previous(uint n) const { return data.previous(n); } inline uint size(uint node, uint field = 0) const { return data.size(node, field); } diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index 1a81394..88e0573 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -676,7 +676,7 @@ void QTextControlPrivate::extendWordwiseSelection(int suggestedNewPosition, qrea const qreal wordEndX = line.cursorToX(curs.position() - blockPos) + blockCoordinates.x(); - if (mouseXPosition < wordStartX || mouseXPosition > wordEndX) + if (!wordSelectionEnabled && (mouseXPosition < wordStartX || mouseXPosition > wordEndX)) return; // keep the already selected word even when moving to the left @@ -1518,7 +1518,7 @@ void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, con const QTextCursor oldSelection = cursor; const int oldCursorPos = cursor.position(); - mousePressed = true; + mousePressed = (interactionFlags & Qt::TextSelectableByMouse); #ifndef QT_NO_DRAGANDDROP mightStartDrag = false; #endif @@ -1578,8 +1578,10 @@ void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, con emit q->cursorPositionChanged(); _q_updateCurrentCharFormatAndSelection(); } else { - if (cursor.position() != oldCursorPos) + if (cursor.position() != oldCursorPos) { emit q->cursorPositionChanged(); + emit q->microFocusChanged(); + } selectionChanged(); } repaintOldAndNewSelection(oldSelection); @@ -1607,13 +1609,11 @@ void QTextControlPrivate::mouseMoveEvent(QEvent *e, Qt::MouseButton button, cons if (!(buttons & Qt::LeftButton)) return; - const bool selectable = interactionFlags & Qt::TextSelectableByMouse; const bool editable = interactionFlags & Qt::TextEditable; - if (!selectable && !editable) - return; - if (!(mousePressed + || editable + || mightStartDrag || selectedWordOnDoubleClick.hasSelection() || selectedBlockOnTrippleClick.hasSelection())) return; @@ -1627,7 +1627,7 @@ void QTextControlPrivate::mouseMoveEvent(QEvent *e, Qt::MouseButton button, cons return; } - if (!selectable) + if (!mousePressed) return; const qreal mouseX = qreal(mousePos.x()); @@ -1695,10 +1695,8 @@ void QTextControlPrivate::mouseReleaseEvent(QEvent *e, Qt::MouseButton button, c if (mousePressed) { mousePressed = false; #ifndef QT_NO_CLIPBOARD - if (interactionFlags & Qt::TextSelectableByMouse) { - setClipboardSelection(); - selectionChanged(true); - } + setClipboardSelection(); + selectionChanged(true); } else if (button == Qt::MidButton && (interactionFlags & Qt::TextEditable) && QApplication::clipboard()->supportsSelection()) { @@ -1950,6 +1948,7 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e) if (isGettingInput) layout->setPreeditArea(cursor.position() - block.position(), e->preeditString()); QList<QTextLayout::FormatRange> overrides; + const int oldPreeditCursor = preeditCursor; preeditCursor = e->preeditString().length(); hideCursor = false; for (int i = 0; i < e->attributes().size(); ++i) { @@ -1970,6 +1969,8 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e) } layout->setAdditionalFormats(overrides); cursor.endEditBlock(); + if (oldPreeditCursor != preeditCursor) + emit q->microFocusChanged(); } QVariant QTextControl::inputMethodQuery(Qt::InputMethodQuery property) const diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 4378c62..4f86cff 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -2681,6 +2681,22 @@ void QTextEngine::resolveAdditionalFormats() const specialData->resolvedFormatIndices = indices; } +QFixed QTextEngine::leadingSpaceWidth(const QScriptLine &line) +{ + if (!line.hasTrailingSpaces + || (option.flags() & QTextOption::IncludeTrailingSpaces) + || !isRightToLeft()) + return QFixed(); + + int pos = line.length; + const HB_CharAttributes *attributes = this->attributes(); + if (!attributes) + return QFixed(); + while (pos > 0 && attributes[line.from + pos - 1].whiteSpace) + --pos; + return width(line.from + pos, line.length - pos); +} + QStackTextEngine::QStackTextEngine(const QString &string, const QFont &f) : QTextEngine(string, f), _layoutData(string, _memory, MemSize) diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 34723ab..67d7453 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -592,6 +592,7 @@ public: QString elidedText(Qt::TextElideMode mode, const QFixed &width, int flags = 0) const; void shapeLine(const QScriptLine &line); + QFixed leadingSpaceWidth(const QScriptLine &line); private: void setBoundary(int strPos) const; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 905f81b..692620f 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -64,23 +64,6 @@ QT_BEGIN_NAMESPACE #define SuppressText 0x5012 #define SuppressBackground 0x513 -static inline QFixed leadingSpaceWidth(QTextEngine *eng, const QScriptLine &line) -{ - if (!line.hasTrailingSpaces - || (eng->option.flags() & QTextOption::IncludeTrailingSpaces) - || !(eng->option.alignment() & Qt::AlignRight) - || !eng->isRightToLeft()) - return QFixed(); - - 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); -} - static QFixed alignLine(QTextEngine *eng, const QScriptLine &line) { QFixed x = 0; @@ -91,7 +74,7 @@ static QFixed alignLine(QTextEngine *eng, const QScriptLine &line) if (align & Qt::AlignJustify && eng->isRightToLeft()) align = Qt::AlignRight; if (align & Qt::AlignRight) - x = line.width - (line.textAdvance + leadingSpaceWidth(eng, line)); + x = line.width - (line.textAdvance + eng->leadingSpaceWidth(line)); else if (align & Qt::AlignHCenter) x = (line.width - line.textAdvance)/2; } diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp index 94f2fc7..2a93f67 100644 --- a/src/gui/text/qtextobject.cpp +++ b/src/gui/text/qtextobject.cpp @@ -1488,7 +1488,7 @@ QTextBlock::iterator QTextBlock::end() const */ QTextBlock QTextBlock::next() const { - if (!isValid()) + if (!isValid() || !p->blockMap().isValid(n)) return QTextBlock(); return QTextBlock(p, p->blockMap().next(n)); diff --git a/src/gui/util/qdesktopservices_s60.cpp b/src/gui/util/qdesktopservices_s60.cpp index 96860df..8caeb74 100644 --- a/src/gui/util/qdesktopservices_s60.cpp +++ b/src/gui/util/qdesktopservices_s60.cpp @@ -314,7 +314,7 @@ static bool handleUrl(const QUrl &url) if (!url.isValid()) return false; - QString urlString(url.toString()); + QString urlString(url.toEncoded()); TPtrC urlPtr(qt_QString2TPtrC(urlString)); TRAPD( err, handleUrlL(urlPtr)); return err ? false : true; diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp index c1ae3f9..04ab801 100644 --- a/src/gui/widgets/qcombobox.cpp +++ b/src/gui/widgets/qcombobox.cpp @@ -398,7 +398,7 @@ void QComboBoxPrivateContainer::leaveEvent(QEvent *) #ifdef Q_WS_MAC QStyleOptionComboBox opt = comboStyleOption(); if (combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo)) - view->setCurrentIndex(QModelIndex()); + view->clearSelection(); #endif } @@ -671,8 +671,8 @@ bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e) if (vector.manhattanLength() > 9 && blockMouseReleaseTimer.isActive()) blockMouseReleaseTimer.stop(); QModelIndex indexUnderMouse = view->indexAt(m->pos()); - if (indexUnderMouse.isValid() && indexUnderMouse != view->currentIndex() - && !QComboBoxDelegate::isSeparator(indexUnderMouse)) { + if (indexUnderMouse.isValid() + && !QComboBoxDelegate::isSeparator(indexUnderMouse)) { view->setCurrentIndex(indexUnderMouse); } } @@ -704,11 +704,13 @@ void QComboBoxPrivateContainer::hideEvent(QHideEvent *) { emit resetButton(); combo->update(); +#ifndef QT_NO_GRAPHICSVIEW // QGraphicsScenePrivate::removePopup closes the combo box popup, it hides it non-explicitly. // Hiding/showing the QComboBox after this will unexpectedly show the popup as well. // Re-hiding the popup container makes sure it is explicitly hidden. if (QGraphicsProxyWidget *proxy = graphicsProxyWidget()) proxy->hide(); +#endif } void QComboBoxPrivateContainer::mousePressEvent(QMouseEvent *e) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 5a281ad..8d4a90e 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -254,12 +254,20 @@ void QLineControl::setSelection(int start, int length) m_selstart = start; m_selend = qMin(start + length, (int)m_text.length()); m_cursor = m_selend; - } else { + } else if (length < 0){ if (start == m_selend && start + length == m_selstart) return; m_selstart = qMax(start + length, 0); m_selend = start; m_cursor = m_selstart; + } else if (m_selstart != m_selend) { + m_selstart = 0; + m_selend = 0; + m_cursor = start; + } else { + m_cursor = start; + emitCursorPositionChanged(); + return; } emit selectionChanged(); emitCursorPositionChanged(); @@ -427,6 +435,8 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) c += event->commitString().length() - qMin(-event->replacementStart(), event->replacementLength()); m_cursor += event->replacementStart(); + if (m_cursor < 0) + m_cursor = 0; // insert commit string if (event->replacementLength()) { @@ -435,11 +445,11 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) removeSelectedText(); } if (!event->commitString().isEmpty()) { - insert(event->commitString()); + internalInsert(event->commitString()); cursorPositionChanged = true; } - m_cursor = qMin(c, m_text.length()); + m_cursor = qBound(0, c, m_text.length()); for (int i = 0; i < event->attributes().size(); ++i) { const QInputMethodEvent::Attribute &a = event->attributes().at(i); diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp index d8f8e91..0db5bba 100644 --- a/src/gui/widgets/qmainwindow.cpp +++ b/src/gui/widgets/qmainwindow.cpp @@ -78,7 +78,6 @@ public: : layout(0), explicitIconSize(false), toolButtonStyle(Qt::ToolButtonIconOnly) #ifdef Q_WS_MAC , useHIToolBar(false) - , activateUnifiedToolbarAfterFullScreen(false) #endif #if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR) , hasOldCursor(false) , cursorAdjusted(false) @@ -90,7 +89,6 @@ public: Qt::ToolButtonStyle toolButtonStyle; #ifdef Q_WS_MAC bool useHIToolBar; - bool activateUnifiedToolbarAfterFullScreen; #endif void init(); QList<int> hoverSeparator; diff --git a/src/gui/widgets/qmainwindowlayout.cpp b/src/gui/widgets/qmainwindowlayout.cpp index 6bc07e1..51267c1 100644 --- a/src/gui/widgets/qmainwindowlayout.cpp +++ b/src/gui/widgets/qmainwindowlayout.cpp @@ -1695,6 +1695,7 @@ QMainWindowLayout::QMainWindowLayout(QMainWindow *mainwindow, QLayout *parentLay , gapIndicator(new QRubberBand(QRubberBand::Rectangle, mainwindow)) #endif //QT_NO_RUBBERBAND #ifdef Q_WS_MAC + , activateUnifiedToolbarAfterFullScreen(false) , blockVisiblityCheck(false) #endif { diff --git a/src/gui/widgets/qmainwindowlayout_p.h b/src/gui/widgets/qmainwindowlayout_p.h index 489e913..289a49c 100644 --- a/src/gui/widgets/qmainwindowlayout_p.h +++ b/src/gui/widgets/qmainwindowlayout_p.h @@ -334,7 +334,6 @@ public: void removeFromMacToolbar(QToolBar *toolbar); void cleanUpMacToolbarItems(); void fixSizeInUnifiedToolbar(QToolBar *tb) const; - bool useHIToolBar; bool activateUnifiedToolbarAfterFullScreen; void syncUnifiedToolbarVisibility(); bool blockVisiblityCheck; diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp index 2f4bb4b..d573ebf 100644 --- a/src/gui/widgets/qmenu.cpp +++ b/src/gui/widgets/qmenu.cpp @@ -82,6 +82,10 @@ # include <private/qt_cocoa_helpers_mac_p.h> #endif +#ifdef Q_WS_S60 +# include "private/qt_s60_p.h" +#endif + QT_BEGIN_NAMESPACE @@ -172,6 +176,14 @@ void QMenuPrivate::init() q->addAction(selectAction); q->addAction(cancelAction); #endif + +#ifdef Q_WS_S60 + if (S60->avkonComponentsSupportTransparency) { + bool noSystemBackground = q->testAttribute(Qt::WA_NoSystemBackground); + q->setAttribute(Qt::WA_TranslucentBackground); // also sets WA_NoSystemBackground + q->setAttribute(Qt::WA_NoSystemBackground, noSystemBackground); // restore system background attribute + } +#endif } int QMenuPrivate::scrollerHeight() const |