diff options
Diffstat (limited to 'src/gui')
77 files changed, 877 insertions, 531 deletions
diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp index 9ff2ad8..fb0dba4 100644 --- a/src/gui/dialogs/qdialog.cpp +++ b/src/gui/dialogs/qdialog.cpp @@ -648,13 +648,14 @@ void QDialog::contextMenuEvent(QContextMenuEvent *e) while (w && w->whatsThis().size() == 0 && !w->testAttribute(Qt::WA_CustomWhatsThis)) w = w->isWindow() ? 0 : w->parentWidget(); if (w) { - QMenu p(this); - QAction *wt = p.addAction(tr("What's This?")); - if (p.exec(e->globalPos()) == wt) { + QWeakPointer<QMenu> p = new QMenu(this); + QAction *wt = p.data()->addAction(tr("What's This?")); + if (p.data()->exec(e->globalPos()) == wt) { QHelpEvent e(QEvent::WhatsThis, w->rect().center(), w->mapToGlobal(w->rect().center())); QApplication::sendEvent(w, &e); } + delete p.data(); } #endif } diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp index 21650bb..089e04a 100644 --- a/src/gui/dialogs/qfiledialog.cpp +++ b/src/gui/dialogs/qfiledialog.cpp @@ -229,11 +229,10 @@ Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook \value ReadOnly Indicates that the model is readonly. \value HideNameFilterDetails Indicates if the is hidden or not. - This value is obsolete and does nothing since Qt 4.5: \value DontUseSheet In previous versions of Qt, the static functions would create a sheet by default if the static function - was given a parent. This is no longer supported in Qt 4.5, The + was given a parent. This is no longer supported and does nothing in Qt 4.5, The static functions will always be an application modal dialog. If you want to use sheets, use QFileDialog::open() instead. diff --git a/src/gui/dialogs/qfilesystemmodel.cpp b/src/gui/dialogs/qfilesystemmodel.cpp index 0e1837b..ba0a560 100644 --- a/src/gui/dialogs/qfilesystemmodel.cpp +++ b/src/gui/dialogs/qfilesystemmodel.cpp @@ -51,6 +51,9 @@ #ifdef Q_OS_WIN #include <qt_windows.h> #endif +#ifdef Q_OS_WIN32 +#include <QtCore/QVarLengthArray> +#endif QT_BEGIN_NAMESPACE @@ -278,53 +281,38 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QM return indexNode; } -#ifdef Q_OS_WIN +#ifdef Q_OS_WIN32 static QString qt_GetLongPathName(const QString &strShortPath) { - QString longPath; - int i = 0; - if (strShortPath == QLatin1String(".") - || (strShortPath.startsWith(QLatin1String("//"))) - || (strShortPath.startsWith(QLatin1String("\\\\")))) // unc + if (strShortPath.isEmpty() + || strShortPath == QLatin1String(".") || strShortPath == QLatin1String("..")) return strShortPath; - QString::const_iterator it = strShortPath.constBegin(); - QString::const_iterator constEnd = strShortPath.constEnd(); - do { - bool isSep = (*it == QLatin1Char('\\') || *it == QLatin1Char('/')); - if (isSep || it == constEnd) { - QString section = (it == constEnd ? strShortPath : strShortPath.left(i)); - // FindFirstFile does not handle volumes ("C:"), so we have to catch that ourselves. - if (section.endsWith(QLatin1Char(':'))) { - longPath.append(section.toUpper()); - } else { - HANDLE h; -#ifndef Q_OS_WINCE - //We add the extend length prefix to handle long path - QString longSection = QLatin1String("\\\\?\\")+QDir::toNativeSeparators(section); -#else - QString longSection = QDir::toNativeSeparators(section); -#endif - WIN32_FIND_DATA findData; - h = ::FindFirstFile((wchar_t*)longSection.utf16(), &findData); - if (h != INVALID_HANDLE_VALUE) { - longPath.append(QString::fromWCharArray(findData.cFileName)); - ::FindClose(h); - } else { - longPath.append(section); - break; - } - } - if (it != constEnd) - longPath.append(*it); - else - break; - } - ++it; - if (isSep && it == constEnd) // break out if the last character is a separator - break; - ++i; - } while (true); - return longPath; + if (strShortPath.length() == 2 && strShortPath.endsWith(QLatin1Char(':'))) + return strShortPath.toUpper(); + const QString absPath = QDir(strShortPath).absolutePath(); + if (absPath.startsWith(QLatin1String("//")) + || absPath.startsWith(QLatin1String("\\\\"))) // unc + return QDir::fromNativeSeparators(absPath); + if (absPath.startsWith(QLatin1Char('/'))) + return QString(); + const QString inputString = QLatin1String("\\\\?\\") + QDir::toNativeSeparators(absPath); + QVarLengthArray<TCHAR, MAX_PATH> buffer(MAX_PATH); + DWORD result = ::GetLongPathName((wchar_t*)inputString.utf16(), + buffer.data(), + buffer.size()); + if (result > DWORD(buffer.size())) { + buffer.resize(result); + result = ::GetLongPathName((wchar_t*)inputString.utf16(), + buffer.data(), + buffer.size()); + } + if (result > 4) { + QString longPath = QString::fromWCharArray(buffer.data() + 4); // ignoring prefix + longPath[0] = longPath.at(0).toUpper(); // capital drive letters + return QDir::fromNativeSeparators(longPath); + } else { + return QDir::fromNativeSeparators(strShortPath); + } } #endif @@ -342,7 +330,7 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS // Construct the nodes up to the new root path if they need to be built QString absolutePath; -#ifdef Q_OS_WIN +#ifdef Q_OS_WIN32 QString longPath = qt_GetLongPathName(path); #else QString longPath = path; @@ -1357,7 +1345,11 @@ QModelIndex QFileSystemModel::setRootPath(const QString &newPath) { Q_D(QFileSystemModel); #ifdef Q_OS_WIN - QString longNewPath = QDir::fromNativeSeparators(qt_GetLongPathName(newPath)); +#ifdef Q_OS_WIN32 + QString longNewPath = qt_GetLongPathName(newPath); +#else + QString longNewPath = QDir::fromNativeSeparators(newPath); +#endif #else QString longNewPath = newPath; #endif diff --git a/src/gui/dialogs/qmessagebox.cpp b/src/gui/dialogs/qmessagebox.cpp index d1b2e3f..ed437ff 100644 --- a/src/gui/dialogs/qmessagebox.cpp +++ b/src/gui/dialogs/qmessagebox.cpp @@ -92,8 +92,8 @@ public: { #ifndef QT_NO_CONTEXTMENU QMenu *menu = createStandardContextMenu(); - menu->exec(e->globalPos()); - delete menu; + menu->setAttribute(Qt::WA_DeleteOnClose); + menu->popup(e->globalPos()); #else Q_UNUSED(e); #endif diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index ed36f87..b4e19d1 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2569,6 +2569,7 @@ void QGraphicsItem::setOpacity(qreal opacity) if (newOpacity == d_ptr->opacity) return; + bool wasFullyTransparent = d_ptr->isOpacityNull(); d_ptr->opacity = newOpacity; // Notify change. @@ -2584,7 +2585,9 @@ void QGraphicsItem::setOpacity(qreal opacity) d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true, /*force=*/false, - /*ignoreOpacity=*/true); + /*ignoreOpacity=*/d_ptr->isOpacityNull()); + if (wasFullyTransparent) + d_ptr->paintedViewBoundingRectsNeedRepaint = 1; } if (d_ptr->isObject) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 5ad6cd5..b3ca3b5 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -358,14 +358,20 @@ public: return o; } + inline bool isOpacityNull() const + { return (opacity < qreal(0.001)); } + + static inline bool isOpacityNull(qreal opacity) + { return (opacity < qreal(0.001)); } + inline bool isFullyTransparent() const { - if (opacity < 0.001) + if (isOpacityNull()) return true; if (!parent) return false; - return calcEffectiveOpacity() < 0.001; + return isOpacityNull(calcEffectiveOpacity()); } inline qreal effectiveOpacity() const { diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 478669e..9a36d46 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -251,6 +251,7 @@ #endif #include <private/qgraphicseffect_p.h> #include <private/qgesturemanager_p.h> +#include <private/qpathclipper_p.h> // #define GESTURE_DEBUG #ifndef GESTURE_DEBUG @@ -372,7 +373,10 @@ void QGraphicsScenePrivate::_q_emitUpdated() } } } else { - updateAll = false; + if (views.isEmpty()) { + updateAll = false; + return; + } for (int i = 0; i < views.size(); ++i) views.at(i)->d_func()->processPendingUpdates(); // It's important that we update all views before we dispatch, hence two for-loops. @@ -4605,6 +4609,7 @@ void QGraphicsScenePrivate::drawItems(QPainter *painter, const QTransform *const if (!unpolishedItems.isEmpty()) _q_polishItems(); + updateAll = false; QRectF exposedSceneRect; if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) { exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1); @@ -4632,7 +4637,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * return; // Item has neither contents nor children!(?) const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity); - const bool itemIsFullyTransparent = (opacity < 0.0001); + const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity); if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) return; @@ -4752,7 +4757,7 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q qreal opacity, const QTransform *effectTransform, bool wasDirtyParentSceneTransform, bool drawItem) { - const bool itemIsFullyTransparent = (opacity < 0.0001); + const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity); const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); const bool itemHasChildren = !item->d_ptr->children.isEmpty(); @@ -4767,7 +4772,12 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q painter->setWorldTransform(*transformPtr * *effectTransform); else painter->setWorldTransform(*transformPtr); - painter->setClipPath(item->shape(), Qt::IntersectClip); + QRectF clipRect; + const QPainterPath clipPath(item->shape()); + if (QPathClipper::pathToRect(clipPath, &clipRect)) + painter->setClipRect(clipRect, Qt::IntersectClip); + else + painter->setClipPath(clipPath, Qt::IntersectClip); } // Draw children behind @@ -4803,8 +4813,14 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q painter->setWorldTransform(*transformPtr); } - if (itemClipsToShape) - painter->setClipPath(item->shape(), Qt::IntersectClip); + if (itemClipsToShape) { + QRectF clipRect; + const QPainterPath clipPath(item->shape()); + if (QPathClipper::pathToRect(clipPath, &clipRect)) + painter->setClipRect(clipRect, Qt::IntersectClip); + else + painter->setClipPath(clipPath, Qt::IntersectClip); + } painter->setOpacity(opacity); if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget) @@ -4982,7 +4998,8 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool } const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity); - const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity && opacity < 0.0001; + const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity + && QGraphicsItemPrivate::isOpacityNull(opacity); if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) { resetDirtyItem(item, /*recursive=*/itemHasChildren); return; @@ -5155,6 +5172,7 @@ void QGraphicsScene::drawItems(QPainter *painter, if (!d->unpolishedItems.isEmpty()) d->_q_polishItems(); + d->updateAll = false; QTransform viewTransform = painter->worldTransform(); Q_UNUSED(options); diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 043c4eb..707c71f 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -279,7 +279,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe return; const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity); - const bool itemIsFullyTransparent = (opacity < 0.0001); + const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity); const bool itemHasChildren = !item->d_ptr->children.isEmpty(); if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) return; @@ -554,7 +554,7 @@ QList<QGraphicsItem *> QGraphicsSceneIndex::estimateTopLevelItems(const QRectF & /*! \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(Qt::SortOrder order = Qt::DescendingOrder) const - + This pure virtual function all items in the index and sort them using \a order. */ diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 451f183..96b9373 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -2748,7 +2748,6 @@ bool QGraphicsView::viewportEvent(QEvent *event) } } } - d->scene->d_func()->updateAll = false; } break; case QEvent::TouchBegin: diff --git a/src/gui/image/qimagepixmapcleanuphooks.cpp b/src/gui/image/qimagepixmapcleanuphooks.cpp index 61d538f..ace4bb6 100644 --- a/src/gui/image/qimagepixmapcleanuphooks.cpp +++ b/src/gui/image/qimagepixmapcleanuphooks.cpp @@ -62,12 +62,12 @@ QImagePixmapCleanupHooks *QImagePixmapCleanupHooks::instance() return qt_image_and_pixmap_cleanup_hooks(); } -void QImagePixmapCleanupHooks::addPixmapModificationHook(_qt_pixmap_cleanup_hook_pm hook) +void QImagePixmapCleanupHooks::addPixmapDataModificationHook(_qt_pixmap_cleanup_hook_pmd hook) { pixmapModificationHooks.append(hook); } -void QImagePixmapCleanupHooks::addPixmapDestructionHook(_qt_pixmap_cleanup_hook_pm hook) +void QImagePixmapCleanupHooks::addPixmapDataDestructionHook(_qt_pixmap_cleanup_hook_pmd hook) { pixmapDestructionHooks.append(hook); } @@ -78,12 +78,12 @@ void QImagePixmapCleanupHooks::addImageHook(_qt_image_cleanup_hook_64 hook) imageHooks.append(hook); } -void QImagePixmapCleanupHooks::removePixmapModificationHook(_qt_pixmap_cleanup_hook_pm hook) +void QImagePixmapCleanupHooks::removePixmapDataModificationHook(_qt_pixmap_cleanup_hook_pmd hook) { pixmapModificationHooks.removeAll(hook); } -void QImagePixmapCleanupHooks::removePixmapDestructionHook(_qt_pixmap_cleanup_hook_pm hook) +void QImagePixmapCleanupHooks::removePixmapDataDestructionHook(_qt_pixmap_cleanup_hook_pmd hook) { pixmapDestructionHooks.removeAll(hook); } @@ -93,24 +93,24 @@ void QImagePixmapCleanupHooks::removeImageHook(_qt_image_cleanup_hook_64 hook) imageHooks.removeAll(hook); } -void QImagePixmapCleanupHooks::executePixmapModificationHooks(QPixmap* pm) +void QImagePixmapCleanupHooks::executePixmapDataModificationHooks(QPixmapData* pmd) { QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks(); for (int i = 0; i < h->pixmapModificationHooks.count(); ++i) - h->pixmapModificationHooks[i](pm); + h->pixmapModificationHooks[i](pmd); if (qt_pixmap_cleanup_hook_64) - qt_pixmap_cleanup_hook_64(pm->cacheKey()); + qt_pixmap_cleanup_hook_64(pmd->cacheKey()); } -void QImagePixmapCleanupHooks::executePixmapDestructionHooks(QPixmap* pm) +void QImagePixmapCleanupHooks::executePixmapDataDestructionHooks(QPixmapData* pmd) { QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks(); for (int i = 0; i < h->pixmapDestructionHooks.count(); ++i) - h->pixmapDestructionHooks[i](pm); + h->pixmapDestructionHooks[i](pmd); if (qt_pixmap_cleanup_hook_64) - qt_pixmap_cleanup_hook_64(pm->cacheKey()); + qt_pixmap_cleanup_hook_64(pmd->cacheKey()); } void QImagePixmapCleanupHooks::executeImageHooks(qint64 key) diff --git a/src/gui/image/qimagepixmapcleanuphooks_p.h b/src/gui/image/qimagepixmapcleanuphooks_p.h index 7176044..88dd3a6 100644 --- a/src/gui/image/qimagepixmapcleanuphooks_p.h +++ b/src/gui/image/qimagepixmapcleanuphooks_p.h @@ -58,7 +58,8 @@ QT_BEGIN_NAMESPACE typedef void (*_qt_image_cleanup_hook_64)(qint64); -typedef void (*_qt_pixmap_cleanup_hook_pm)(QPixmap*); +typedef void (*_qt_pixmap_cleanup_hook_pmd)(QPixmapData*); + class QImagePixmapCleanupHooks; @@ -71,27 +72,27 @@ public: static void enableCleanupHooks(const QPixmap &pixmap); static void enableCleanupHooks(QPixmapData *pixmapData); - // Gets called when a pixmap is about to be modified: - void addPixmapModificationHook(_qt_pixmap_cleanup_hook_pm); + // Gets called when a pixmap data is about to be modified: + void addPixmapDataModificationHook(_qt_pixmap_cleanup_hook_pmd); - // Gets called when a pixmap is about to be destroyed: - void addPixmapDestructionHook(_qt_pixmap_cleanup_hook_pm); + // Gets called when a pixmap data is about to be destroyed: + void addPixmapDataDestructionHook(_qt_pixmap_cleanup_hook_pmd); // Gets called when an image is about to be modified or destroyed: void addImageHook(_qt_image_cleanup_hook_64); - void removePixmapModificationHook(_qt_pixmap_cleanup_hook_pm); - void removePixmapDestructionHook(_qt_pixmap_cleanup_hook_pm); + void removePixmapDataModificationHook(_qt_pixmap_cleanup_hook_pmd); + void removePixmapDataDestructionHook(_qt_pixmap_cleanup_hook_pmd); void removeImageHook(_qt_image_cleanup_hook_64); - static void executePixmapModificationHooks(QPixmap*); - static void executePixmapDestructionHooks(QPixmap*); + static void executePixmapDataModificationHooks(QPixmapData*); + static void executePixmapDataDestructionHooks(QPixmapData*); static void executeImageHooks(qint64 key); private: QList<_qt_image_cleanup_hook_64> imageHooks; - QList<_qt_pixmap_cleanup_hook_pm> pixmapModificationHooks; - QList<_qt_pixmap_cleanup_hook_pm> pixmapDestructionHooks; + QList<_qt_pixmap_cleanup_hook_pmd> pixmapModificationHooks; + QList<_qt_pixmap_cleanup_hook_pmd> pixmapDestructionHooks; }; QT_END_NAMESPACE diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index e51d858..7cafbd0 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -320,8 +320,6 @@ QPixmap::QPixmap(const char * const xpm[]) QPixmap::~QPixmap() { Q_ASSERT(!data || data->ref >= 1); // Catch if ref-counting changes again - if (data && data->is_cached && data->ref == 1) // ref will be decrememnted after destructor returns - QImagePixmapCleanupHooks::executePixmapDestructionHooks(this); } /*! @@ -1025,12 +1023,8 @@ qint64 QPixmap::cacheKey() const if (isNull()) return 0; - int classKey = data->classId(); - if (classKey >= 1024) - classKey = -(classKey >> 10); - return ((((qint64) classKey) << 56) - | (((qint64) data->serialNumber()) << 32) - | ((qint64) (data->detach_no))); + Q_ASSERT(data); + return data->cacheKey(); } static void sendResizeEvents(QWidget *target) @@ -1963,7 +1957,7 @@ void QPixmap::detach() } if (data->is_cached && data->ref == 1) - QImagePixmapCleanupHooks::executePixmapModificationHooks(this); + QImagePixmapCleanupHooks::executePixmapDataModificationHooks(data.data()); #if defined(Q_WS_MAC) QMacPixmapData *macData = id == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(data.data()) : 0; diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp index 4de5bc4..b976376 100644 --- a/src/gui/image/qpixmap_x11.cpp +++ b/src/gui/image/qpixmap_x11.cpp @@ -68,6 +68,7 @@ #include "qx11info_x11.h" #include <private/qdrawhelper_p.h> #include <private/qimage_p.h> +#include <private/qimagepixmapcleanuphooks_p.h> #include <stdlib.h> @@ -1234,6 +1235,12 @@ void QX11PixmapData::fill(const QColor &fillColor) QX11PixmapData::~QX11PixmapData() { + // Cleanup hooks have to be called before the handles are freed + if (is_cached) { + QImagePixmapCleanupHooks::executePixmapDataDestructionHooks(this); + is_cached = false; + } + release(); } @@ -1242,8 +1249,13 @@ void QX11PixmapData::release() delete pengine; pengine = 0; - if (!X11) + if (!X11) { +#ifndef QT_NO_DEBUG + qWarning("~QX11PixmapData(): QPixmap objects must be destroyed before the QApplication" + " object, otherwise the native pixmap object will be leaked."); +#endif return; + } if (x11_mask) { #ifndef QT_NO_XRENDER diff --git a/src/gui/image/qpixmapdata.cpp b/src/gui/image/qpixmapdata.cpp index 65032da..ea4fe6b 100644 --- a/src/gui/image/qpixmapdata.cpp +++ b/src/gui/image/qpixmapdata.cpp @@ -45,6 +45,7 @@ #include <QtGui/qimagereader.h> #include <private/qgraphicssystem_p.h> #include <private/qapplication_p.h> +#include <private/qimagepixmapcleanuphooks_p.h> QT_BEGIN_NAMESPACE @@ -80,6 +81,16 @@ QPixmapData::QPixmapData(PixelType pixelType, int objectId) QPixmapData::~QPixmapData() { + // Sometimes the pixmap cleanup hooks will be called from derrived classes, which will + // then set is_cached to false. For example, on X11 QtOpenGL needs to delete the GLXPixmap + // or EGL Pixmap Surface for a given pixmap _before_ the native X11 pixmap is deleted, + // otherwise some drivers will leak the GL surface. In this case, QX11PixmapData will + // call the cleanup hooks itself before deleting the native pixmap and set is_cached to + // false. + if (is_cached) { + QImagePixmapCleanupHooks::executePixmapDataDestructionHooks(this); + is_cached = false; + } } QPixmapData *QPixmapData::createCompatiblePixmapData() const diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h index 1125515..827fa18 100644 --- a/src/gui/image/qpixmapdata_p.h +++ b/src/gui/image/qpixmapdata_p.h @@ -117,6 +117,14 @@ public: inline int colorCount() const { return metric(QPaintDevice::PdmNumColors); } inline int depth() const { return d; } inline bool isNull() const { return is_null; } + inline qint64 cacheKey() const { + int classKey = id; + if (classKey >= 1024) + classKey = -(classKey >> 10); + return ((((qint64) classKey) << 56) + | (((qint64) ser_no) << 32) + | ((qint64) detach_no)); + } #if defined(Q_OS_SYMBIAN) virtual void* toNativeType(NativeType type); diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index d5406cb..dd31834 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -50,8 +50,13 @@ #include <qvariant.h> #include <qvector.h> +#ifdef QT_USE_BUNDLED_LIBPNG +#include <../../3rdparty/libpng/png.h> +#include <../../3rdparty/libpng/pngconf.h> +#else #include <png.h> #include <pngconf.h> +#endif #ifdef Q_OS_WINCE #define CALLBACK_CALL_TYPE __cdecl @@ -162,11 +167,16 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre png_uint_32 height; int bit_depth; int color_type; + png_bytep trans_alpha = 0; + png_color_16p trans_color_p = 0; + int num_trans; + png_colorp palette = 0; + int num_palette; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); if (color_type == PNG_COLOR_TYPE_GRAY) { // Black & White or 8-bit grayscale - if (bit_depth == 1 && info_ptr->channels == 1) { + if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) { png_set_invert_mono(png_ptr); png_read_update_info(png_ptr, info_ptr); if (image.size() != QSize(width, height) || image.format() != QImage::Format_Mono) { @@ -207,20 +217,16 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre int c = i*255/(ncols-1); image.setColor(i, qRgba(c,c,c,0xff)); } - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { -#if PNG_LIBPNG_VER_MAJOR < 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 4) - const int g = info_ptr->trans_values.gray; -#else - const int g = info_ptr->trans_color.gray; -#endif + if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_color_p) { + const int g = trans_color_p->gray; if (g < ncols) { image.setColor(g, 0); } } } } else if (color_type == PNG_COLOR_TYPE_PALETTE - && png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE) - && info_ptr->num_palette <= 256) + && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette) + && num_palette <= 256) { // 1-bit and 8-bit color if (bit_depth != 1) @@ -233,29 +239,26 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre if (image.isNull()) return; } - image.setColorCount(info_ptr->num_palette); + png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); + image.setColorCount(num_palette); int i = 0; - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { - while (i < info_ptr->num_trans) { + if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_alpha) { + while (i < num_trans) { image.setColor(i, qRgba( - info_ptr->palette[i].red, - info_ptr->palette[i].green, - info_ptr->palette[i].blue, -#if PNG_LIBPNG_VER_MAJOR < 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 4) - info_ptr->trans[i] -#else - info_ptr->trans_alpha[i] -#endif + palette[i].red, + palette[i].green, + palette[i].blue, + trans_alpha[i] ) ); i++; } } - while (i < info_ptr->num_palette) { + while (i < num_palette) { image.setColor(i, qRgba( - info_ptr->palette[i].red, - info_ptr->palette[i].green, - info_ptr->palette[i].blue, + palette[i].red, + palette[i].green, + palette[i].blue, 0xff ) ); @@ -531,33 +534,36 @@ QImage::Format QPngHandlerPrivate::readImageFormat() QImage::Format format = QImage::Format_Invalid; png_uint_32 width, height; int bit_depth, color_type; - if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY) { + png_colorp palette; + int num_palette; + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); + if (color_type == PNG_COLOR_TYPE_GRAY) { // Black & White or 8-bit grayscale - if (info_ptr->bit_depth == 1 && info_ptr->channels == 1) { + if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) { format = QImage::Format_Mono; - } else if (info_ptr->bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { + } else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { format = QImage::Format_ARGB32; } else { format = QImage::Format_Indexed8; } - } else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE - && png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE) - && info_ptr->num_palette <= 256) + } else if (color_type == PNG_COLOR_TYPE_PALETTE + && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette) + && num_palette <= 256) { // 1-bit and 8-bit color - if (info_ptr->bit_depth != 1) + if (bit_depth != 1) png_set_packing(png_ptr); png_read_update_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8; } else { // 32-bit - if (info_ptr->bit_depth == 16) + if (bit_depth == 16) png_set_strip_16(png_ptr); format = QImage::Format_ARGB32; // Only add filler if no alpha, or we can get 5 channel data. - if (!(info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + if (!(color_type & PNG_COLOR_MASK_ALPHA) && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { // We want 4 bytes, but it isn't an alpha channel format = QImage::Format_RGB32; @@ -648,7 +654,7 @@ static void set_text(const QImage &image, png_structp png_ptr, png_infop info_pt text_ptr[i].text = qstrdup(value.constData()); text_ptr[i].text_length = 0; text_ptr[i].itxt_length = value.size(); - text_ptr[i].lang = "UTF-8"; + text_ptr[i].lang = const_cast<char*>("UTF-8"); text_ptr[i].lang_key = qstrdup(it.key().toUtf8().constData()); #endif ++i; @@ -735,64 +741,51 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image_in, png_set_compression_level(png_ptr, quality); } - if (gamma != 0.0) { - png_set_gAMA(png_ptr, info_ptr, 1.0/gamma); - } - png_set_write_fn(png_ptr, (void*)this, qpiw_write_fn, qpiw_flush_fn); - info_ptr->channels = - (image.depth() == 32) - ? (image.format() == QImage::Format_RGB32 ? 3 : 4) - : 1; - png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(), image.depth() == 1 ? 1 : 8 /* per channel */, image.depth() == 32 ? image.format() == QImage::Format_RGB32 ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGB_ALPHA - : PNG_COLOR_TYPE_PALETTE, 0, 0, 0); + : PNG_COLOR_TYPE_PALETTE, 0, 0, 0); // also sets #channels + if (gamma != 0.0) { + png_set_gAMA(png_ptr, info_ptr, 1.0/gamma); + } - //png_set_sBIT(png_ptr, info_ptr, 8); - info_ptr->sig_bit.red = 8; - info_ptr->sig_bit.green = 8; - info_ptr->sig_bit.blue = 8; + png_color_8 sig_bit; + sig_bit.red = 8; + sig_bit.green = 8; + sig_bit.blue = 8; + sig_bit.alpha = image.hasAlphaChannel() ? 8 : 0; + png_set_sBIT(png_ptr, info_ptr, &sig_bit); if (image.format() == QImage::Format_MonoLSB) png_set_packswap(png_ptr); - png_colorp palette = 0; - png_bytep copy_trans = 0; if (image.colorCount()) { // Paletted - int num_palette = image.colorCount(); - palette = new png_color[num_palette]; - png_set_PLTE(png_ptr, info_ptr, palette, num_palette); - int* trans = new int[num_palette]; + int num_palette = qMin(256, image.colorCount()); + png_color palette[256]; + png_byte trans[256]; int num_trans = 0; for (int i=0; i<num_palette; i++) { - QRgb rgb=image.color(i); - info_ptr->palette[i].red = qRed(rgb); - info_ptr->palette[i].green = qGreen(rgb); - info_ptr->palette[i].blue = qBlue(rgb); - trans[i] = rgb >> 24; + QRgb rgba=image.color(i); + palette[i].red = qRed(rgba); + palette[i].green = qGreen(rgba); + palette[i].blue = qBlue(rgba); + trans[i] = qAlpha(rgba); if (trans[i] < 255) { num_trans = i+1; } } + png_set_PLTE(png_ptr, info_ptr, palette, num_palette); + if (num_trans) { - copy_trans = new png_byte[num_trans]; - for (int i=0; i<num_trans; i++) - copy_trans[i] = trans[i]; - png_set_tRNS(png_ptr, info_ptr, copy_trans, num_trans, 0); + png_set_tRNS(png_ptr, info_ptr, trans, num_trans, 0); } - delete [] trans; - } - - if (image.format() != QImage::Format_RGB32) { - info_ptr->sig_bit.alpha = 8; } // Swap ARGB to RGBA (normal PNG format) before saving on @@ -868,11 +861,6 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image_in, png_write_end(png_ptr, info_ptr); frames_written++; - if (palette) - delete [] palette; - if (copy_trans) - delete [] copy_trans; - png_destroy_write_struct(&png_ptr, &info_ptr); return true; @@ -958,7 +946,8 @@ QVariant QPngHandler::option(ImageOption option) const else if (option == Description) return d->description; else if (option == Size) - return QSize(d->info_ptr->width, d->info_ptr->height); + return QSize(png_get_image_width(d->png_ptr, d->info_ptr), + png_get_image_height(d->png_ptr, d->info_ptr)); else if (option == ImageFormat) return d->readImageFormat(); return 0; diff --git a/src/gui/inputmethod/qcoefepinputcontext_p.h b/src/gui/inputmethod/qcoefepinputcontext_p.h index f5034fc..d5243c3 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_p.h +++ b/src/gui/inputmethod/qcoefepinputcontext_p.h @@ -96,7 +96,7 @@ protected: void timerEvent(QTimerEvent *timerEvent); private: - void commitCurrentString(bool triggeredBySymbian); + void commitCurrentString(bool cancelFepTransaction); void updateHints(bool mustUpdateInputCapabilities); void applyHints(Qt::InputMethodHints hints); void applyFormat(QList<QInputMethodEvent::Attribute> *attributes); @@ -127,7 +127,7 @@ public: private: void DoCommitFepInlineEditL(); MCoeFepAwareTextEditor_Extension1* Extension1(TBool& aSetToTrue); - void ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateEvent aEventType); + void ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateEvent aEventType); // From MCoeFepAwareTextEditor_Extension1 public: @@ -151,7 +151,6 @@ private: int m_inlinePosition; MFepInlineTextFormatRetriever *m_formatRetriever; MFepPointerEventHandlerDuringInlineEdit *m_pointerHandler; - int m_longPress; int m_cursorPos; QBasicTimer m_tempPreeditStringTimeout; bool m_hasTempPreeditString; diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index e5ab300..2b91711 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -71,7 +71,6 @@ QCoeFepInputContext::QCoeFepInputContext(QObject *parent) m_inlinePosition(0), m_formatRetriever(0), m_pointerHandler(0), - m_longPress(0), m_cursorPos(0), m_hasTempPreeditString(false) { @@ -101,7 +100,7 @@ QCoeFepInputContext::~QCoeFepInputContext() void QCoeFepInputContext::reset() { - commitCurrentString(false); + commitCurrentString(true); } void QCoeFepInputContext::ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateEvent aEventType) @@ -126,7 +125,7 @@ void QCoeFepInputContext::update() void QCoeFepInputContext::setFocusWidget(QWidget *w) { - commitCurrentString(false); + commitCurrentString(true); QInputContext::setFocusWidget(w); @@ -219,7 +218,7 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event) break; case Qt::Key_Select: if (!m_preeditString.isEmpty()) { - commitCurrentString(false); + commitCurrentString(true); return true; } break; @@ -231,10 +230,11 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event) && focusWidget()->inputMethodHints() & Qt::ImhHiddenText && !keyEvent->text().isEmpty()) { // Send some temporary preedit text in order to make text visible for a moment. + m_cursorPos = focusWidget()->inputMethodQuery(Qt::ImCursorPosition).toInt(); m_preeditString = keyEvent->text(); QList<QInputMethodEvent::Attribute> attributes; QInputMethodEvent imEvent(m_preeditString, attributes); - QApplication::sendEvent(focusWidget(), &imEvent); + sendEvent(imEvent); m_tempPreeditStringTimeout.start(1000, this); m_hasTempPreeditString = true; update(); @@ -293,7 +293,7 @@ void QCoeFepInputContext::mouseHandler( int x, QMouseEvent *event) Q_ASSERT(focusWidget()); if (event->type() == QEvent::MouseButtonPress && event->button() == Qt::LeftButton) { - commitCurrentString(false); + commitCurrentString(true); int pos = focusWidget()->inputMethodQuery(Qt::ImCursorPosition).toInt(); QList<QInputMethodEvent::Attribute> attributes; @@ -739,31 +739,33 @@ void QCoeFepInputContext::GetScreenCoordinatesForFepL(TPoint& aLeftSideOfBaseLin void QCoeFepInputContext::DoCommitFepInlineEditL() { - commitCurrentString(true); + commitCurrentString(false); } -void QCoeFepInputContext::commitCurrentString(bool triggeredBySymbian) +void QCoeFepInputContext::commitCurrentString(bool cancelFepTransaction) { + int longPress = 0; + if (m_preeditString.size() == 0) { QWidget *w = focusWidget(); - if (triggeredBySymbian && w) { + if (!cancelFepTransaction && w) { // We must replace the last character only if the input box has already accepted one if (w->inputMethodQuery(Qt::ImCursorPosition).toInt() != m_cursorPos) - m_longPress = 1; + longPress = 1; } return; } QList<QInputMethodEvent::Attribute> attributes; QInputMethodEvent event(QLatin1String(""), attributes); - event.setCommitString(m_preeditString, 0-m_longPress, m_longPress); + event.setCommitString(m_preeditString, 0-longPress, longPress); m_preeditString.clear(); sendEvent(event); m_hasTempPreeditString = false; - m_longPress = 0; + longPress = 0; - if (!triggeredBySymbian) { + if (cancelFepTransaction) { CCoeFep* fep = CCoeEnv::Static()->Fep(); if (fep) fep->CancelTransaction(); diff --git a/src/gui/kernel/qaction.cpp b/src/gui/kernel/qaction.cpp index 4b7d949..8ddd051 100644 --- a/src/gui/kernel/qaction.cpp +++ b/src/gui/kernel/qaction.cpp @@ -715,6 +715,10 @@ QActionGroup *QAction::actionGroup() const it is displayed to the left of the menu text. There is no default icon. + On Symbian the icons which are passed to softkeys, i.e. to actions with + softkey role, need to have pixmap alpha channel correctly set otherwise + drawing artifacts will appear when softkey is pressed down. + If a null icon (QIcon::isNull() is passed into this function, the icon of the action is cleared. */ diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 1fc1b45..bb6aca9 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -5707,7 +5707,6 @@ QGestureManager* QGestureManager::instance() return qAppPriv->gestureManager; } -#if defined(Q_WS_X11) || defined(Q_WS_WIN) // These pixmaps approximate the images in the Windows User Interface Guidelines. // XPM @@ -5929,7 +5928,6 @@ QPixmap QApplicationPrivate::getPixmapCursor(Qt::CursorShape cshape) } return QPixmap(); } -#endif QT_END_NAMESPACE diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index 3fba833..0199e87 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -1237,7 +1237,7 @@ void qt_init(QApplicationPrivate *priv, int) // Cocoa application delegate #ifdef QT_MAC_USE_COCOA - NSApplication *cocoaApp = [NSApplication sharedApplication]; + NSApplication *cocoaApp = [QNSApplication sharedApplication]; QMacCocoaAutoReleasePool pool; NSObject *oldDelegate = [cocoaApp delegate]; QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *newDelegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate]; diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 0764553..d19d86e 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -518,17 +518,13 @@ public: QGestureManager *gestureManager; QWidget *gestureWidget; -#if defined(Q_WS_X11) || defined(Q_WS_WIN) QPixmap *move_cursor; QPixmap *copy_cursor; QPixmap *link_cursor; -#endif #if defined(Q_WS_WIN) QPixmap *ignore_cursor; #endif -#if defined(Q_WS_X11) || defined(Q_WS_WIN) QPixmap getPixmapCursor(Qt::CursorShape cshape); -#endif QMap<int, QWeakPointer<QWidget> > widgetForTouchPointId; QMap<int, QTouchEvent::TouchPoint> appCurrentTouchPoints; diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 20b8030..87de602 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -924,8 +924,8 @@ void QSymbianControl::PositionChanged() cr.moveTopLeft(newPos); qwidget->data->crect = cr; QTLWExtra *top = qwidget->d_func()->maybeTopData(); - if (top) - top->normalGeometry = cr; + if (top && (qwidget->windowState() & (~Qt::WindowActive)) == Qt::WindowNoState) + top->normalGeometry.moveTopLeft(newPos); if (qwidget->isVisible()) { QMoveEvent e(newPos, oldPos); qt_sendSpontaneousEvent(qwidget, &e); @@ -960,15 +960,14 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) qwidget->d_func()->setWindowIcon_sys(true); qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle()); #ifdef Q_WS_S60 - // If widget is fullscreen, hide status pane and button container - // otherwise show them. + // If widget is fullscreen/minimized, hide status pane and button container otherwise show them. CEikStatusPane* statusPane = S60->statusPane(); CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer(); - bool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen; - if (statusPane && (bool)statusPane->IsVisible() == isFullscreen) - statusPane->MakeVisible(!isFullscreen); - if (buttonGroup && (bool)buttonGroup->IsVisible() == isFullscreen) - buttonGroup->MakeVisible(!isFullscreen); + TBool visible = !(qwidget->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized)); + if (statusPane) + statusPane->MakeVisible(visible); + if (buttonGroup) + buttonGroup->MakeVisible(visible); #endif } else if (QApplication::activeWindow() == qwidget->window()) { if (CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog()) { @@ -1647,6 +1646,9 @@ int QApplicationPrivate::symbianProcessWsEvent(const QSymbianEvent *symbianEvent if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::ENotVisible) { delete w->d_func()->topData()->backingStore; w->d_func()->topData()->backingStore = 0; + // In order to ensure that any resources used by the window surface + // are immediately freed, we flush the WSERV command buffer. + S60->wsSession().Flush(); } else if ((visChangedEvent->iFlags & TWsVisibilityChangedEvent::EPartiallyVisible) && !w->d_func()->maybeBackingStore()) { w->d_func()->topData()->backingStore = new QWidgetBackingStore(w); diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 3355272..2c6e246 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -2547,6 +2547,17 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam result = true; break; } +#ifndef QT_NO_CURSOR + case WM_SETCURSOR: { + QCursor *ovr = QApplication::overrideCursor(); + if (ovr) { + SetCursor(ovr->handle()); + RETURN(TRUE); + } + result = false; + break; + } +#endif default: result = false; // event was not processed break; diff --git a/src/gui/kernel/qcocoaapplication_mac.mm b/src/gui/kernel/qcocoaapplication_mac.mm index 5b98420..5629940 100644 --- a/src/gui/kernel/qcocoaapplication_mac.mm +++ b/src/gui/kernel/qcocoaapplication_mac.mm @@ -107,5 +107,50 @@ | NSFontPanelStrikethroughEffectModeMask; } + +- (void)qt_sendPostedMessage:(NSEvent *)event +{ + // WARNING: data1 and data2 is truncated to from 64-bit to 32-bit on OS 10.5! + // That is why we need to split the address in two parts: + quint64 lower = [event data1]; + quint64 upper = [event data2]; + QCocoaPostMessageArgs *args = reinterpret_cast<QCocoaPostMessageArgs *>(lower | (upper << 32)); + [args->target performSelector:args->selector]; + delete args; +} + +- (BOOL)qt_sendEvent:(NSEvent *)event +{ + if ([event type] == NSApplicationDefined) { + switch ([event subtype]) { + case QtCocoaEventSubTypePostMessage: + [NSApp qt_sendPostedMessage:event]; + return true; + default: + break; + } + } + return false; +} + @end + +@implementation QNSApplication + +// WARNING: If Qt did not create NSApplication (this can e.g. +// happend if Qt is used as a plugin from a 3rd-party cocoa +// application), QNSApplication::sendEvent will never be called. +// SO DO NOT RELY ON THIS FUNCTION BEING AVAILABLE. +// Plugin developers that _do_ control the NSApplication sub-class +// implementation of the 3rd-party application can call qt_sendEvent +// from the sub-class event handler (like we do here) to work around +// any issues. +- (void)sendEvent:(NSEvent *)event +{ + if (![self qt_sendEvent:event]) + [super sendEvent:event]; +} + +@end + #endif diff --git a/src/gui/kernel/qcocoaapplication_mac_p.h b/src/gui/kernel/qcocoaapplication_mac_p.h index e845d58..5569feb 100644 --- a/src/gui/kernel/qcocoaapplication_mac_p.h +++ b/src/gui/kernel/qcocoaapplication_mac_p.h @@ -99,5 +99,13 @@ QT_FORWARD_DECLARE_CLASS(QApplicationPrivate) - (QApplicationPrivate *)QT_MANGLE_NAMESPACE(qt_qappPrivate); - (QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader); - (int)QT_MANGLE_NAMESPACE(qt_validModesForFontPanel):(NSFontPanel *)fontPanel; + +- (void)qt_sendPostedMessage:(NSEvent *)event; +- (BOOL)qt_sendEvent:(NSEvent *)event; +@end + +@interface QNSApplication : NSApplication { +} @end + #endif diff --git a/src/gui/kernel/qcocoamenuloader_mac.mm b/src/gui/kernel/qcocoamenuloader_mac.mm index 18b3772..573b763 100644 --- a/src/gui/kernel/qcocoamenuloader_mac.mm +++ b/src/gui/kernel/qcocoamenuloader_mac.mm @@ -46,6 +46,7 @@ #include <private/qcocoamenuloader_mac_p.h> #include <private/qapplication_p.h> #include <private/qt_mac_p.h> +#include <private/qmenubar_p.h> #include <qmenubar.h> QT_FORWARD_DECLARE_CLASS(QCFString) @@ -208,6 +209,11 @@ QT_USE_NAMESPACE [NSApp hide:sender]; } +- (void)qtUpdateMenubar +{ + QMenuBarPrivate::macUpdateMenuBarImmediatly(); +} + - (IBAction)qtDispatcherToQAction:(id)sender { QScopedLoopLevelCounter loopLevelCounter(QApplicationPrivate::instance()->threadData); diff --git a/src/gui/kernel/qcocoamenuloader_mac_p.h b/src/gui/kernel/qcocoamenuloader_mac_p.h index 81c136e..2504b8c 100644 --- a/src/gui/kernel/qcocoamenuloader_mac_p.h +++ b/src/gui/kernel/qcocoamenuloader_mac_p.h @@ -85,6 +85,7 @@ - (IBAction)unhideAllApplications:(id)sender; - (IBAction)hide:(id)sender; - (IBAction)qtDispatcherToQAction:(id)sender; +- (void)qtUpdateMenubar; @end #endif // QT_MAC_USE_COCOA diff --git a/src/gui/kernel/qcocoapanel_mac.mm b/src/gui/kernel/qcocoapanel_mac.mm index 3012093..0b48efd 100644 --- a/src/gui/kernel/qcocoapanel_mac.mm +++ b/src/gui/kernel/qcocoapanel_mac.mm @@ -47,6 +47,9 @@ #import <private/qcocoaview_mac_p.h> #import <private/qcocoawindowcustomthemeframe_mac_p.h> #import <private/qcocoaapplication_mac_p.h> +#include <private/qapplication_p.h> +#include <private/qbackingstore_p.h> + #include <QtGui/QWidget> diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h index d8bbcd4..9fe5ae0 100644 --- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h +++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h @@ -51,6 +51,9 @@ NSPanel, while QCocoaWindow needs to inherit NSWindow rather than NSPanel). ****************************************************************************/ +// WARNING: Don't include any header files from within this file. Put them +// directly into qcocoawindow_mac_p.h and qcocoapanel_mac_p.h + QT_BEGIN_NAMESPACE extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp @@ -180,8 +183,18 @@ QT_END_NAMESPACE - (void)sendEvent:(NSEvent *)event { - QWidget *widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self]; + if ([event type] == NSApplicationDefined) { + switch ([event subtype]) { + case QtCocoaEventSubTypePostMessage: + [NSApp qt_sendPostedMessage:event]; + return; + default: + break; + } + return; + } + QWidget *widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self]; // Cocoa can hold onto the window after we've disavowed its knowledge. So, // if we get sent an event afterwards just have it go through the super's // version and don't do any stuff with Qt. @@ -205,7 +218,7 @@ QT_END_NAMESPACE qt_button_down = widget; handled = qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton); // Don't call super here. This prevents us from getting the mouseUp event, - // which we need to send even if the mouseDown event was not accepted. + // which we need to send even if the mouseDown event was not accepted. // (this is standard Qt behavior.) break; case NSRightMouseDown: @@ -303,9 +316,9 @@ QT_END_NAMESPACE { // The user dragged something into the window. Send a draggingEntered message // to the QWidget under the mouse. As the drag moves over the window, and over - // different widgets, we will handle enter and leave events from within + // different widgets, we will handle enter and leave events from within // draggingUpdated below. The reason why we handle this ourselves rather than - // subscribing for drag events directly in QCocoaView is that calling + // subscribing for drag events directly in QCocoaView is that calling // registerForDraggedTypes on the views will severly degrade initialization time // for an application that uses a lot of drag subscribing widgets. @@ -369,3 +382,18 @@ QT_END_NAMESPACE return dropResult; } +- (void)displayIfNeeded +{ + + QWidget *qwidget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self]; + if (qwidget == 0) { + [super displayIfNeeded]; + return; + } + + if (QApplicationPrivate::graphicsSystem() != 0) { + if (QWidgetBackingStore *bs = qt_widget_private(qwidget)->maybeBackingStore()) + bs->sync(qwidget, qwidget->rect()); + } + [super displayIfNeeded]; +} diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index aa00e97..c3fbaad 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -474,10 +474,11 @@ extern "C" { - (void)drawRect:(NSRect)aRect { if (QApplicationPrivate::graphicsSystem() != 0) { - if (QWidgetBackingStore *bs = qwidgetprivate->maybeBackingStore()) - bs->markDirty(qwidget->rect(), qwidget); - qwidgetprivate->syncBackingStore(qwidget->rect()); - return; + if (QWidgetBackingStore *bs = qwidgetprivate->maybeBackingStore()) { + // Drawing is handled on the window level + // See qcocoasharedwindowmethods_mac_p. + return; + } } CGContextRef cg = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; qwidgetprivate->hd = cg; diff --git a/src/gui/kernel/qcocoawindow_mac_p.h b/src/gui/kernel/qcocoawindow_mac_p.h index 403a1a5..21f82df 100644 --- a/src/gui/kernel/qcocoawindow_mac_p.h +++ b/src/gui/kernel/qcocoawindow_mac_p.h @@ -53,6 +53,9 @@ #ifdef QT_MAC_USE_COCOA #include "qmacdefines_mac.h" #import <Cocoa/Cocoa.h> +#include <private/qapplication_p.h> +#include <private/qbackingstore_p.h> + enum { QtMacCustomizeWindow = 1 << 21 }; // This will one day be run over by diff --git a/src/gui/kernel/qdesktopwidget_s60.cpp b/src/gui/kernel/qdesktopwidget_s60.cpp index 77745ea..84e3c5d 100644 --- a/src/gui/kernel/qdesktopwidget_s60.cpp +++ b/src/gui/kernel/qdesktopwidget_s60.cpp @@ -88,24 +88,20 @@ QDesktopWidgetPrivate::~QDesktopWidgetPrivate() void QDesktopWidgetPrivate::init(QDesktopWidget *that) { - int screenCount=0; +// int screenCount=0; - if (HAL::Get(0, HALData::EDisplayNumberOfScreens, screenCount) == KErrNone) - QDesktopWidgetPrivate::screenCount = screenCount; - else - QDesktopWidgetPrivate::screenCount = 0; + // ### TODO: Implement proper multi-display support + QDesktopWidgetPrivate::screenCount = 1; +// if (HAL::Get(0, HALData::EDisplayNumberOfScreens, screenCount) == KErrNone) +// QDesktopWidgetPrivate::screenCount = screenCount; +// else +// QDesktopWidgetPrivate::screenCount = 0; rects = new QVector<QRect>(); workrects = new QVector<QRect>(); rects->resize(QDesktopWidgetPrivate::screenCount); workrects->resize(QDesktopWidgetPrivate::screenCount); - - // ### TODO: Implement proper multi-display support - rects->resize(1); - rects->replace(0, that->rect()); - workrects->resize(1); - workrects->replace(0, that->rect()); } void QDesktopWidgetPrivate::cleanup() diff --git a/src/gui/kernel/qdnd.cpp b/src/gui/kernel/qdnd.cpp index 82708ef..2b3a3d0 100644 --- a/src/gui/kernel/qdnd.cpp +++ b/src/gui/kernel/qdnd.cpp @@ -167,7 +167,6 @@ QDragManager *QDragManager::self() return instance; } -#if defined(Q_WS_X11) || defined(Q_WS_WIN) QPixmap QDragManager::dragCursor(Qt::DropAction action) const { QDragPrivate * d = dragPrivate(); @@ -185,7 +184,6 @@ QPixmap QDragManager::dragCursor(Qt::DropAction action) const #endif return QPixmap(); } -#endif bool QDragManager::hasCustomDragCursors() const { diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h index 1eb85ed..033e6a6 100644 --- a/src/gui/kernel/qdnd_p.h +++ b/src/gui/kernel/qdnd_p.h @@ -244,9 +244,7 @@ public: bool willDrop; QEventLoop *eventLoop; -#if defined(Q_WS_X11) || defined(Q_WS_WIN) QPixmap dragCursor(Qt::DropAction action) const; -#endif bool hasCustomDragCursors() const; diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm index c7d042d..8a67dee 100644 --- a/src/gui/kernel/qeventdispatcher_mac.mm +++ b/src/gui/kernel/qeventdispatcher_mac.mm @@ -1064,10 +1064,9 @@ void QEventDispatcherMacPrivate::cancelWaitForMoreEvents() // In case the event dispatcher is waiting for more // events somewhere, we post a dummy event to wake it up: QMacCocoaAutoReleasePool pool; - static const short NSAppShouldStopForQt = SHRT_MAX; [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint modifierFlags:0 timestamp:0. windowNumber:0 context:0 - subtype:NSAppShouldStopForQt data1:0 data2:0] atStart:NO]; + subtype:QtCocoaEventSubTypeWakeup data1:0 data2:0] atStart:NO]; } #endif diff --git a/src/gui/kernel/qsoftkeymanager_s60.cpp b/src/gui/kernel/qsoftkeymanager_s60.cpp index 67ed8b0..af84a8f 100644 --- a/src/gui/kernel/qsoftkeymanager_s60.cpp +++ b/src/gui/kernel/qsoftkeymanager_s60.cpp @@ -49,7 +49,7 @@ #include "private/qsoftkeymanager_p.h" #include "private/qsoftkeymanager_s60_p.h" #include "private/qobject_p.h" -//#include <eiksoftkeyimage.h> +#include <eiksoftkeyimage.h> #include <eikcmbut.h> #ifndef QT_NO_SOFTKEYMANAGER @@ -64,6 +64,8 @@ QSoftKeyManagerPrivateS60::QSoftKeyManagerPrivateS60() { cachedCbaIconSize[0] = QSize(0,0); cachedCbaIconSize[1] = QSize(0,0); + cachedCbaIconSize[2] = QSize(0,0); + cachedCbaIconSize[3] = QSize(0,0); skipNextUpdate = false; } @@ -149,6 +151,39 @@ void QSoftKeyManagerPrivateS60::setNativeSoftkey(CEikButtonGroupContainer &cba, QT_TRAP_THROWING(cba.SetCommandL(position, command, text)); } +QPoint QSoftKeyManagerPrivateS60::softkeyIconPosition(int position, QSize sourceSize, QSize targetSize) +{ + QPoint iconPosition(0,0); + switch( AknLayoutUtils::CbaLocation() ) + { + case AknLayoutUtils::EAknCbaLocationBottom: + // RSK must be moved to right, LSK in on correct position by default + if (position == RSK_POSITION) + iconPosition.setX(targetSize.width() - sourceSize.width()); + break; + case AknLayoutUtils::EAknCbaLocationRight: + case AknLayoutUtils::EAknCbaLocationLeft: + // Already in correct position + default: + break; + } + + // Align horizontally to center + iconPosition.setY((targetSize.height() - sourceSize.height()) >> 1); + return iconPosition; +} + +QPixmap QSoftKeyManagerPrivateS60::prepareSoftkeyPixmap(QPixmap src, int position, QSize targetSize) +{ + QPixmap target(targetSize); + target.fill(Qt::transparent); + QPainter p; + p.begin(&target); + p.drawPixmap(softkeyIconPosition(position, src.size(), targetSize), src); + p.end(); + return target; +} + bool QSoftKeyManagerPrivateS60::isOrientationLandscape() { // Hard to believe that there is no public API in S60 to @@ -158,15 +193,11 @@ bool QSoftKeyManagerPrivateS60::isOrientationLandscape() QSize QSoftKeyManagerPrivateS60::cbaIconSize(CEikButtonGroupContainer *cba, int position) { - Q_UNUSED(cba); - Q_UNUSED(position); - // Will be implemented when EikSoftkeyImage usage license wise is OK -/* - const int index = isOrientationLandscape() ? 0 : 1; + int index = position; + index += isOrientationLandscape() ? 0 : 1; if(cachedCbaIconSize[index].isNull()) { // Only way I figured out to get CBA icon size without RnD SDK, was - // Only way I figured out to get CBA icon size without RnD SDK, was // to set some dummy icon to CBA first and then ask CBA button CCoeControl::Size() // The returned value is cached to avoid unnecessary icon setting every time. const bool left = (position == LSK_POSITION); @@ -178,38 +209,46 @@ QSize QSoftKeyManagerPrivateS60::cbaIconSize(CEikButtonGroupContainer *cba, int setNativeSoftkey(*cba, position, command, KNullDesC()); cachedCbaIconSize[index] = qt_TSize2QSize(cba->ControlOrNull(command)->Size()); EikSoftkeyImage::SetLabel(cba, left); + + if(cachedCbaIconSize[index] == QSize(138,72)) { + // Hack for S60 5.0 (5800) landscape orientation, which return wrong icon size + cachedCbaIconSize[index] = QSize(60,60); + } } } return cachedCbaIconSize[index]; -*/ - return QSize(); } bool QSoftKeyManagerPrivateS60::setSoftkeyImage(CEikButtonGroupContainer *cba, QAction &action, int position) { bool ret = false; - Q_UNUSED(cba); - Q_UNUSED(action); - Q_UNUSED(position); - // Will be implemented when EikSoftkeyImage usage license wise is OK - /* const bool left = (position == LSK_POSITION); if(position == LSK_POSITION || position == RSK_POSITION) { QIcon icon = action.icon(); if (!icon.isNull()) { - QPixmap pm = icon.pixmap(cbaIconSize(cba, position)); - pm = pm.scaled(cbaIconSize(cba, position)); - QBitmap mask = pm.mask(); - if (mask.isNull()) { - mask = QBitmap(pm.size()); - mask.fill(Qt::color1); + // Get size of CBA icon area based on button position and orientation + QSize requiredIconSize = cbaIconSize(cba, position); + // Get pixmap out of icon based on preferred size, the aspect ratio is kept + QPixmap pmWihtAspectRatio = icon.pixmap(requiredIconSize); + // Native softkeys require that pixmap size is exactly the same as requiredIconSize + // prepareSoftkeyPixmap creates a new pixmap with requiredIconSize and blits the 'pmWihtAspectRatio' + // to correct location of it + QPixmap softkeyPixmap = prepareSoftkeyPixmap(pmWihtAspectRatio, position, requiredIconSize); + + QPixmap softkeyAlpha = softkeyPixmap.alphaChannel(); + // Alpha channel in 5.1 and older devices need to be inverted + // TODO: Switch to use toSymbianCFbsBitmap with invert when available + if(QSysInfo::s60Version() <= QSysInfo::SV_S60_5_1) { + QImage alphaImage = softkeyAlpha.toImage(); + alphaImage.invertPixels(); + softkeyAlpha = QPixmap::fromImage(alphaImage); } - CFbsBitmap* nBitmap = pm.toSymbianCFbsBitmap(); - CFbsBitmap* nMask = mask.toSymbianCFbsBitmap(); + CFbsBitmap* nBitmap = softkeyPixmap.toSymbianCFbsBitmap(); + CFbsBitmap* nMask = softkeyAlpha.toSymbianCFbsBitmap(); CEikImage* myimage = new (ELeave) CEikImage; myimage->SetPicture( nBitmap, nMask ); // nBitmap and nMask ownership transfered @@ -221,7 +260,6 @@ bool QSoftKeyManagerPrivateS60::setSoftkeyImage(CEikButtonGroupContainer *cba, EikSoftkeyImage::SetLabel(cba, left); } } - */ return ret; } @@ -272,6 +310,7 @@ bool QSoftKeyManagerPrivateS60::setRightSoftkey(CEikButtonGroupContainer &cba) if (windowType != Qt::Dialog && windowType != Qt::Popup) { QString text(QSoftKeyManager::tr("Exit")); TPtrC nativeText = qt_QString2TPtrC(text); + EikSoftkeyImage::SetLabel(&cba, false); setNativeSoftkey(cba, RSK_POSITION, EAknSoftkeyExit, nativeText); return true; } @@ -303,7 +342,6 @@ void QSoftKeyManagerPrivateS60::setSoftkeys(CEikButtonGroupContainer &cba) void QSoftKeyManagerPrivateS60::updateSoftKeys_sys() { - //bool status = CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog(); if (skipCbaUpdate()) return; diff --git a/src/gui/kernel/qsoftkeymanager_s60_p.h b/src/gui/kernel/qsoftkeymanager_s60_p.h index 46e3596..f8bd6d9 100644 --- a/src/gui/kernel/qsoftkeymanager_s60_p.h +++ b/src/gui/kernel/qsoftkeymanager_s60_p.h @@ -84,6 +84,8 @@ private: QAction *highestPrioritySoftkey(QAction::SoftKeyRole role); static bool actionPriorityMoreThan(const QAction* item1, const QAction* item2); void setNativeSoftkey(CEikButtonGroupContainer &cba, TInt position, TInt command, const TDesC& text); + QPoint softkeyIconPosition(int position, QSize sourceSize, QSize targetSize); + QPixmap prepareSoftkeyPixmap(QPixmap src, int position, QSize targetSize); bool isOrientationLandscape(); QSize cbaIconSize(CEikButtonGroupContainer *cba, int position); bool setSoftkeyImage(CEikButtonGroupContainer *cba, QAction &action, int position); @@ -95,7 +97,7 @@ private: private: QHash<int, QAction*> realSoftKeyActions; - QSize cachedCbaIconSize[2]; + QSize cachedCbaIconSize[4]; bool skipNextUpdate; }; diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index 377e5a0..f2ec4af 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -83,6 +83,7 @@ #include <private/qt_cocoa_helpers_mac_p.h> #include <private/qt_mac_p.h> #include <private/qapplication_p.h> +#include <private/qcocoaapplication_mac_p.h> #include <private/qcocoawindow_mac_p.h> #include <private/qcocoaview_mac_p.h> #include <private/qkeymapper_p.h> @@ -1162,7 +1163,7 @@ CGContextRef qt_mac_graphicsContextFor(QWidget *widget) CGrafPtr port = GetWindowPort(qt_mac_window_for(widget)); QDBeginCGContext(port, &context); #else - CGContextRef context = (CGContextRef)[[NSGraphicsContext graphicsContextWithWindow:qt_mac_window_for(widget)] graphicsPort]; + CGContextRef context = reinterpret_cast<CGContextRef>([[qt_mac_window_for(widget) graphicsContext] graphicsPort]); #endif return context; } @@ -1279,22 +1280,42 @@ void qt_cocoaChangeOverrideCursor(const QCursor &cursor) QMacCocoaAutoReleasePool pool; [static_cast<NSCursor *>(qt_mac_nsCursorForQCursor(cursor)) set]; } -#endif -@implementation DebugNSApplication { -} -- (void)sendEvent:(NSEvent *)event +// WARNING: If Qt did not create NSApplication (e.g. in case it is +// used as a plugin), and at the same time, there is no window on +// screen (or the window that the event is sendt to becomes hidden etc +// before the event gets delivered), the message will not be performed. +bool qt_cocoaPostMessage(id target, SEL selector) { - NSLog(@"NSAppDebug: sendEvent: %@", event); - return [super sendEvent:event]; -} + if (!target) + return false; -- (BOOL)sendAction:(SEL)anAction to:(id)aTarget from:(id)sender -{ - NSLog(@"NSAppDebug: sendAction: %s to %@ from %@", anAction, aTarget, sender); - return [super sendAction:anAction to:aTarget from:sender]; + NSInteger windowNumber = 0; + if (![NSApp isMemberOfClass:[QNSApplication class]]) { + // INVARIANT: Cocoa is not using our NSApplication subclass. That means + // we don't control the main event handler either. So target the event + // for one of the windows on screen: + NSWindow *nswin = [NSApp mainWindow]; + if (!nswin) { + nswin = [NSApp keyWindow]; + if (!nswin) + return false; + } + windowNumber = [nswin windowNumber]; + } + + // WARNING: data1 and data2 is truncated to from 64-bit to 32-bit on OS 10.5! + // That is why we need to split the address in two parts: + QCocoaPostMessageArgs *args = new QCocoaPostMessageArgs(target, selector); + quint32 lower = quintptr(args); + quint32 upper = quintptr(args) >> 32; + NSEvent *e = [NSEvent otherEventWithType:NSApplicationDefined + location:NSZeroPoint modifierFlags:0 timestamp:0 windowNumber:windowNumber + context:nil subtype:QtCocoaEventSubTypePostMessage data1:lower data2:upper]; + [NSApp postEvent:e atStart:NO]; + return true; } -@end +#endif QMacCocoaAutoReleasePool::QMacCocoaAutoReleasePool() { diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h index ace8255..c43ea55 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h +++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h @@ -114,6 +114,12 @@ typedef struct CGPoint NSPoint; #endif QT_BEGIN_NAMESPACE + +enum { + QtCocoaEventSubTypeWakeup = SHRT_MAX, + QtCocoaEventSubTypePostMessage = SHRT_MAX-1 +}; + Qt::MouseButtons qt_mac_get_buttons(int buttons); Qt::MouseButton qt_mac_get_button(EventMouseButton button); void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds = 0.15); @@ -182,8 +188,23 @@ inline QString qt_mac_NSStringToQString(const NSString *nsstr) inline NSString *qt_mac_QStringToNSString(const QString &qstr) { return [reinterpret_cast<const NSString *>(QCFString::toCFStringRef(qstr)) autorelease]; } -@interface DebugNSApplication : NSApplication {} -@end +#ifdef QT_MAC_USE_COCOA +class QCocoaPostMessageArgs { +public: + id target; + SEL selector; + QCocoaPostMessageArgs(id target, SEL selector) : target(target), selector(selector) + { + [target retain]; + } + + ~QCocoaPostMessageArgs() + { + [target release]; + } +}; +bool qt_cocoaPostMessage(id target, SEL selector); +#endif #endif diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 884447d..2e951b6 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -1439,6 +1439,18 @@ QWidget::~QWidget() } #endif +#ifdef Q_OS_SYMBIAN + if (d->extra && d->extra->topextra && d->extra->topextra->backingStore) { + // Okay, we are about to destroy the top-level window that owns + // the backing store. Make sure we delete the backing store right away + // before the window handle is invalid. This is important because + // the backing store will delete its window surface, which may or may + // not have a reference to this widget that will be used later to + // notify the window it no longer has a surface. + delete d->extra->topextra->backingStore; + d->extra->topextra->backingStore = 0; + } +#endif if (QWidgetBackingStore *bs = d->maybeBackingStore()) { bs->removeDirtyWidget(this); if (testAttribute(Qt::WA_StaticContents)) @@ -1660,7 +1672,13 @@ void QWidgetPrivate::syncBackingStore() repaint_sys(dirty); dirty = QRegion(); } else if (QWidgetBackingStore *bs = maybeBackingStore()) { +#ifdef QT_MAC_USE_COCOA + Q_UNUSED(bs); + void qt_mac_set_needs_display(QWidget *, QRegion); + qt_mac_set_needs_display(q_func(), QRegion()); +#else bs->sync(); +#endif } } @@ -1668,8 +1686,15 @@ void QWidgetPrivate::syncBackingStore(const QRegion ®ion) { if (paintOnScreen()) repaint_sys(region); - else if (QWidgetBackingStore *bs = maybeBackingStore()) + else if (QWidgetBackingStore *bs = maybeBackingStore()) { +#ifdef QT_MAC_USE_COCOA + Q_UNUSED(bs); + void qt_mac_set_needs_display(QWidget *, QRegion); + qt_mac_set_needs_display(q_func(), region); +#else bs->sync(q_func(), region); +#endif + } } void QWidgetPrivate::setUpdatesEnabled_helper(bool enable) @@ -6422,6 +6447,8 @@ void QWidget::setTabOrder(QWidget* first, QWidget *second) first = fp; } + if (fp == second) + return; if (QWidget *sp = second->focusProxy()) second = sp; diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 878b776..a5633d3 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -565,6 +565,25 @@ inline static void qt_mac_set_window_group_to_popup(OSWindowRef window) } #endif +#ifdef QT_MAC_USE_COCOA +void qt_mac_set_needs_display(QWidget *widget, QRegion region) +{ + NSView *theNSView = qt_mac_nativeview_for(widget); + if (region.isEmpty()) { + [theNSView setNeedsDisplay:YES]; + return; + } + + QVector<QRect> rects = region.rects(); + for (int i = 0; i<rects.count(); ++i) { + const QRect &rect = rects.at(i); + NSRect nsrect = NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height()); + [theNSView setNeedsDisplayInRect:nsrect]; + } + +} +#endif + inline static bool updateRedirectedToGraphicsProxyWidget(QWidget *widget, const QRect &rect) { if (!widget) diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 00f2213..a844430 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -1046,96 +1046,48 @@ void QWidget::setWindowState(Qt::WindowStates newstate) return; if (isWindow()) { -#ifdef Q_WS_S60 - // Change window decoration visibility if switching to or from fullsccreen - // In addition decoration visibility is changed when the initial has been - // WindowNoState. - // The window decoration visibility has to be changed before doing actual - // window state change since in that order the availableGeometry will return - // directly the right size and we will avoid unnecessarty redraws - if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen) || - oldstate == Qt::WindowNoState) { - CEikStatusPane* statusPane = S60->statusPane(); - CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer(); - if (newstate & Qt::WindowFullScreen) { - if (statusPane) - statusPane->MakeVisible(false); - if (buttonGroup) - buttonGroup->MakeVisible(false); - } else { - if (statusPane) - statusPane->MakeVisible(true); - if (buttonGroup) - buttonGroup->MakeVisible(true); - } + QSymbianControl *window = static_cast<QSymbianControl *>(effectiveWinId()); + if (window && newstate & Qt::WindowMinimized) { + window->setFocusSafely(false); + window->MakeVisible(false); + } else if (window && oldstate & Qt::WindowMinimized) { + window->setFocusSafely(true); + window->MakeVisible(true); } + +#ifdef Q_WS_S60 + // Hide window decoration when switching to fullsccreen / 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 unnecessarty redraws + CEikStatusPane* statusPane = S60->statusPane(); + CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer(); + TBool visible = !(newstate & (Qt::WindowFullScreen | Qt::WindowMinimized)); + if (statusPane) + statusPane->MakeVisible(visible); + if (buttonGroup) + buttonGroup->MakeVisible(visible); #endif // Q_WS_S60 createWinId(); Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - QTLWExtra *top = d->topData(); - // Ensure the initial size is valid, since we store it as normalGeometry below. if (!testAttribute(Qt::WA_Resized) && !isVisible()) adjustSize(); - if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) { - if ((newstate & Qt::WindowMaximized)) { - const QRect normalGeometry = geometry(); + QTLWExtra *top = d->topData(); + const QRect normalGeometry = (top->normalGeometry.width() < 0) ? geometry() : top->normalGeometry; - const QRect r = top->normalGeometry; - setGeometry(qApp->desktop()->availableGeometry(this)); - top->normalGeometry = r; + if (newstate & Qt::WindowFullScreen) + setGeometry(qApp->desktop()->screenGeometry(this)); + else if (newstate & Qt::WindowMaximized) + setGeometry(qApp->desktop()->availableGeometry(this)); + else + setGeometry(normalGeometry); - if (top->normalGeometry.width() < 0) - top->normalGeometry = normalGeometry; - } else { - // restore original geometry - setGeometry(top->normalGeometry); - } - } - if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) { - if (newstate & Qt::WindowFullScreen) { - const QRect normalGeometry = geometry(); - const QRect r = top->normalGeometry; - setGeometry(qApp->desktop()->screenGeometry(this)); - - top->normalGeometry = r; - if (top->normalGeometry.width() < 0) - top->normalGeometry = normalGeometry; - } else { - if (newstate & Qt::WindowMaximized) { - const QRect r = top->normalGeometry; - setGeometry(qApp->desktop()->availableGeometry(this)); - top->normalGeometry = r; - } else { - setGeometry(top->normalGeometry); - } - } - } - if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) { - if (newstate & Qt::WindowMinimized) { - if (isVisible()) { - QSymbianControl *id = static_cast<QSymbianControl *>(effectiveWinId()); - if (id->IsFocused()) // Avoid unnecessary calls to FocusChanged() - id->setFocusSafely(false); - id->MakeVisible(false); - } - } else { - if (isVisible()) { - QSymbianControl *id = static_cast<QSymbianControl *>(effectiveWinId()); - id->MakeVisible(true); - if (!id->IsFocused()) // Avoid unnecessary calls to FocusChanged() - id->setFocusSafely(true); - } - const QRect normalGeometry = geometry(); - const QRect r = top->normalGeometry; - top->normalGeometry = r; - if (top->normalGeometry.width() < 0) - top->normalGeometry = normalGeometry; - } - } + //restore normal geometry + top->normalGeometry = normalGeometry; } data->window_state = newstate; @@ -1195,6 +1147,10 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) if (destroyWindow) { delete id; + // At this point the backing store should already be destroyed + // so we flush the command buffer to ensure that the freeing of + // those resources and deleting the window can happen "atomically" + S60->wsSession().Flush(); } } diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp index 4684bc1..10fb009 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -346,11 +346,6 @@ Q_GUI_EXPORT void qt_x11_enforce_cursor(QWidget * w) qt_x11_enforce_cursor(w, false); } -static Bool checkForConfigureAndExpose(Display *, XEvent *e, XPointer) -{ - return e->type == ConfigureNotify || e->type == Expose; -} - Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w) { if (!w || (!w->isWindow() && !w->internalWinId())) @@ -363,38 +358,60 @@ Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w) if (!w->testAttribute(Qt::WA_WState_Created)) return; - if (!(w->windowFlags() & Qt::X11BypassWindowManagerHint)) { - // if the window is not override-redirect, then the window manager - // will reparent us to the frame decoration window. - while (!XCheckTypedWindowEvent(X11->display, w->effectiveWinId(), ReparentNotify, &ev)) { - if (t.elapsed() > maximumWaitTime) - return; - qApp->syncX(); // non-busy wait - } - } + WId winid = w->internalWinId(); - while (!XCheckTypedWindowEvent(X11->display, w->effectiveWinId(), MapNotify, &ev)) { - if (t.elapsed() > maximumWaitTime) - return; - qApp->syncX(); // non-busy wait - } + // first deliver events that are already in the local queue + QApplication::sendPostedEvents(); - qApp->x11ProcessEvent(&ev); + // the normal sequence is: + // ... ConfigureNotify ... ReparentNotify ... MapNotify ... Expose + // with X11BypassWindowManagerHint: + // ConfigureNotify ... MapNotify ... Expose - // ok, seems like the window manager successfully reparented us, we'll wait - // for the first paint event to arrive, while handling ConfigureNotify in - // the arrival order - while(1) - { - if (XCheckIfEvent(X11->display, &ev, checkForConfigureAndExpose, 0)) { + enum State { + Initial, Reparented, Mapped + } state = Initial; + + do { + if (XEventsQueued(X11->display, QueuedAlready)) { + XNextEvent(X11->display, &ev); qApp->x11ProcessEvent(&ev); - if (ev.type == Expose) - return; + + if (w->windowFlags() & Qt::X11BypassWindowManagerHint) { + switch (state) { + case Initial: + case Reparented: + if (ev.type == MapNotify && ev.xany.window == winid) + state = Mapped; + break; + case Mapped: + if (ev.type == Expose && ev.xany.window == winid) + return; + break; + } + } else { + switch (state) { + case Initial: + if (ev.type == ReparentNotify && ev.xany.window == winid) + state = Reparented; + break; + case Reparented: + if (ev.type == MapNotify && ev.xany.window == winid) + state = Mapped; + break; + case Mapped: + if (ev.type == Expose && ev.xany.window == winid) + return; + break; + } + } + } else { + if (!XEventsQueued(X11->display, QueuedAfterFlush)) + qApp->syncX(); // non-busy wait } if (t.elapsed() > maximumWaitTime) return; - qApp->syncX(); // non-busy wait - } + } while(1); } void qt_change_net_wm_state(const QWidget* w, bool set, Atom one, Atom two = 0) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 194dda3..660a2a8 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -2408,7 +2408,11 @@ static inline int soft_light_op(int dst, int src, int da, int sa) else if (4 * dst <= da) return (dst * sa * 255 + da * (src2 - sa) * ((((16 * dst_np - 12 * 255) * dst_np + 3 * 65025) * dst_np) / 65025) + temp) / 65025; else { +# ifdef Q_CC_RVCT // needed to avoid compiler crash in RVCT 2.2 + return (dst * sa * 255 + da * (src2 - sa) * (qIntSqrtInt(dst_np * 255) - dst_np) + temp) / 65025; +# else return (dst * sa * 255 + da * (src2 - sa) * (int(sqrt(qreal(dst_np * 255))) - dst_np) + temp) / 65025; +# endif } } diff --git a/src/gui/painting/qmath_p.h b/src/gui/painting/qmath_p.h index cd9f5ea..8a5f5ab 100644 --- a/src/gui/painting/qmath_p.h +++ b/src/gui/painting/qmath_p.h @@ -54,6 +54,7 @@ // #include <math.h> +#include <qmath.h> QT_BEGIN_NAMESPACE @@ -61,6 +62,11 @@ static const qreal Q_PI = qreal(3.14159265358979323846); // pi static const qreal Q_2PI = qreal(6.28318530717958647693); // 2*pi static const qreal Q_PI2 = qreal(1.57079632679489661923); // pi/2 +inline int qIntSqrtInt(int v) +{ + return static_cast<int>(qSqrt(static_cast<qreal>(v))); +} + QT_END_NAMESPACE #endif // QMATH_P_H diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index cde6a2d..bf12c6b 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -7509,7 +7509,7 @@ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset) return widgetPrivate->redirected(offset); } - if (*globalRedirectionAtomic() == 0) + if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0) return 0; QMutexLocker locker(globalRedirectionsMutex()); @@ -7529,7 +7529,7 @@ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset) void qt_painter_removePaintDevice(QPaintDevice *dev) { - if (*globalRedirectionAtomic() == 0) + if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0) return; QMutex *mutex = 0; diff --git a/src/gui/painting/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp index 7997e77..bc81514 100644 --- a/src/gui/painting/qpathclipper.cpp +++ b/src/gui/painting/qpathclipper.cpp @@ -90,8 +90,6 @@ static QPointF normalize(const QPointF &p) return p / qSqrt(p.x() * p.x() + p.y() * p.y()); } -static bool pathToRect(const QPainterPath &path, QRectF *rect = 0); - struct QIntersection { qreal alphaA; @@ -1660,7 +1658,7 @@ static bool fuzzyCompare(qreal a, qreal b) return qFuzzyCompare(a, b); } -static bool pathToRect(const QPainterPath &path, QRectF *rect) +bool QPathClipper::pathToRect(const QPainterPath &path, QRectF *rect) { if (path.elementCount() != 5) return false; @@ -1693,7 +1691,7 @@ static bool pathToRect(const QPainterPath &path, QRectF *rect) return false; if (rect) - *rect = QRectF(QPointF(x1, y1), QPointF(x2, y2)); + rect->setCoords(x1, y1, x2, y2); return true; } diff --git a/src/gui/painting/qpathclipper_p.h b/src/gui/painting/qpathclipper_p.h index 0d2c049..b900862 100644 --- a/src/gui/painting/qpathclipper_p.h +++ b/src/gui/painting/qpathclipper_p.h @@ -86,6 +86,8 @@ public: bool intersect(); bool contains(); + static bool pathToRect(const QPainterPath &path, QRectF *rect = 0); + private: Q_DISABLE_COPY(QPathClipper) diff --git a/src/gui/painting/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp index a0d2b9b..eee6bef 100644 --- a/src/gui/painting/qwindowsurface_raster.cpp +++ b/src/gui/painting/qwindowsurface_raster.cpp @@ -295,10 +295,8 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi CGContextRestoreGState(context); #ifndef QT_MAC_USE_COCOA QDEndCGContext(port, &context); -#else - CGContextFlush(context); -#endif #endif +#endif // Q_WS_MAC #ifdef Q_OS_SYMBIAN Q_UNUSED(widget); diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp index 3132dd1..7f9b058 100644 --- a/src/gui/styles/qcommonstyle.cpp +++ b/src/gui/styles/qcommonstyle.cpp @@ -1149,10 +1149,10 @@ void QCommonStylePrivate::tabLayout(const QStyleOptionTabV3 *opt, const QWidget int vpadding = proxyStyle->pixelMetric(QStyle::PM_TabBarTabVSpace, opt, widget) / 2; if (opt->shape == QTabBar::RoundedSouth || opt->shape == QTabBar::TriangularSouth) verticalShift = -verticalShift; - tr.adjust(hpadding, vpadding, horizontalShift - hpadding, verticalShift - vpadding); + tr.adjust(hpadding, verticalShift - vpadding, horizontalShift - hpadding, vpadding); bool selected = opt->state & QStyle::State_Selected; if (selected) { - tr.setBottom(tr.bottom() - verticalShift); + tr.setTop(tr.top() - verticalShift); tr.setRight(tr.right() - horizontalShift); } diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm index a077cf0..40ee31d 100644 --- a/src/gui/styles/qmacstyle_mac.mm +++ b/src/gui/styles/qmacstyle_mac.mm @@ -3391,8 +3391,14 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter if (tb->toolButtonStyle != Qt::ToolButtonIconOnly) { needText = true; if (tb->toolButtonStyle == Qt::ToolButtonTextUnderIcon) { - pr.setHeight(pixmap.size().height()); - cr.adjust(0, pr.bottom() + 1, 0, 1); + QMainWindow *mw = qobject_cast<QMainWindow *>(w->window()); + if (mw && mw->unifiedTitleAndToolBarOnMac()) { + pr.setHeight(pixmap.size().height()); + cr.adjust(0, pr.bottom() + 1, 0, 1); + } else { + pr.setHeight(pixmap.size().height() + 6); + cr.adjust(0, pr.bottom(), 0, -3); + } alignment |= Qt::AlignCenter; } else { pr.setWidth(pixmap.width() + 8); diff --git a/src/gui/styles/qs60style_simulated.cpp b/src/gui/styles/qs60style_simulated.cpp index f87cf28..3f09ebc 100644 --- a/src/gui/styles/qs60style_simulated.cpp +++ b/src/gui/styles/qs60style_simulated.cpp @@ -94,12 +94,12 @@ bool saveThemeToBlob(const QString &themeBlob, dataOut << color; } - const int picturesCount = partPictures.count(); - dataOut << picturesCount; - foreach (const QString &key, partPictures.keys()) { - const QPicture picture = partPictures.value(key); - dataOut << key; - dataOut << picture; + dataOut << partPictures.count(); + QHashIterator<QString, QPicture> i(partPictures); + while (i.hasNext()) { + i.next(); + dataOut << i.key(); + dataOut << i.value(); // the QPicture } QDataStream blobOut(&blob); diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index 9002172..1f9fc32 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -1125,6 +1125,7 @@ void QRenderRule::fixupBorder(int nativeWidth) void QRenderRule::drawBorderImage(QPainter *p, const QRect& rect) { + setClip(p, rect); static const Qt::TileRule tileMode2TileRule[] = { Qt::StretchTile, Qt::RoundTile, Qt::StretchTile, Qt::RepeatTile, Qt::StretchTile }; @@ -1142,6 +1143,7 @@ void QRenderRule::drawBorderImage(QPainter *p, const QRect& rect) QRect(QPoint(), borderImageData->pixmap.size()), sourceMargins, QTileRules(tileMode2TileRule[borderImageData->horizStretch], tileMode2TileRule[borderImageData->vertStretch])); p->setRenderHint(QPainter::SmoothPixmapTransform, wasSmoothPixmapTransform); + unsetClip(p); } QRect QRenderRule::originRect(const QRect &rect, Origin origin) const diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp index 3ae6fe9..87a73df 100644 --- a/src/gui/text/qfontdatabase_s60.cpp +++ b/src/gui/text/qfontdatabase_s60.cpp @@ -246,8 +246,8 @@ static void initializeDb() QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); const int numTypeFaces = QS60Data::screenDevice()->NumTypefaces(); - const QFontDatabaseS60StoreImplementation *store = dynamic_cast<const QFontDatabaseS60StoreImplementation*>(db->s60Store); - Q_ASSERT(store); + const QFontDatabaseS60StoreImplementation *store = + static_cast<const QFontDatabaseS60StoreImplementation*>(db->s60Store); bool fontAdded = false; for (int i = 0; i < numTypeFaces; i++) { TTypefaceSupport typefaceSupport; @@ -258,8 +258,7 @@ static void initializeDb() continue; if (font->TypeUid() == KCFbsFontUid) { TOpenFontFaceAttrib faceAttrib; - const CFbsFont *cfbsFont = dynamic_cast<const CFbsFont *>(font); - Q_ASSERT(cfbsFont); + const CFbsFont *cfbsFont = static_cast<const CFbsFont *>(font); cfbsFont->GetFaceAttrib(faceAttrib); QtFontStyle::Key styleKey; @@ -390,8 +389,8 @@ QFontEngine *QFontDatabase::findFont(int script, const QFontPrivate *, const QFo QFontDef request = req; request.family = fontFamily; #if defined(QT_NO_FREETYPE) - const QFontDatabaseS60StoreImplementation *store = dynamic_cast<const QFontDatabaseS60StoreImplementation*>(db->s60Store); - Q_ASSERT(store); + const QFontDatabaseS60StoreImplementation *store = + static_cast<const QFontDatabaseS60StoreImplementation*>(db->s60Store); const QFontEngineS60Extensions *extension = store->extension(fontFamily); fe = new QFontEngineS60(request, extension); #else diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index aaaa3ca..8d3923f 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -1762,8 +1762,8 @@ void QTextControlPrivate::contextMenuEvent(const QPoint &screenPos, const QPoint QMenu *menu = q->createStandardContextMenu(docPos, contextWidget); if (!menu) return; - menu->exec(screenPos); - delete menu; + menu->setAttribute(Qt::WA_DeleteOnClose); + menu->popup(screenPos); #endif } diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index b8c9b94..80931c9 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -436,6 +436,23 @@ void QTextDocument::redo(QTextCursor *cursor) } /*! + \since 4.7 + Clears the specified stacks. + + This method clears any commands on the undo stack, the redo stack, or both (the + default). If any commands got cleared, the appropriate signals + (\a QTextDocument::undoAvailable or \a QTextDocument::redoAvailable) get + emitted. + + \sa QTextDocument::undoAvailable QTextDocument::redoAvailable +*/ +void QTextDocument::clearUndoRedoStacks(Stacks stacksToClear) +{ + Q_D(QTextDocument); + d->clearUndoRedoStacks(stacksToClear, true); +} + +/*! \overload */ diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h index b5bcb41..0140772 100644 --- a/src/gui/text/qtextdocument.h +++ b/src/gui/text/qtextdocument.h @@ -256,6 +256,13 @@ public: void undo(QTextCursor *cursor); void redo(QTextCursor *cursor); + enum Stacks { + UndoStack = 0x01, + RedoStack = 0x02, + UndoAndRedoStacks = UndoStack | RedoStack + }; + void clearUndoRedoStacks(Stacks historyToClear = UndoAndRedoStacks); + int maximumBlockCount() const; void setMaximumBlockCount(int maximum); diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp index 372b9dc..969d5b4 100644 --- a/src/gui/text/qtextdocument_p.cpp +++ b/src/gui/text/qtextdocument_p.cpp @@ -259,8 +259,7 @@ void QTextDocumentPrivate::clear() objects.clear(); title.clear(); - undoState = 0; - truncateUndoStack(); + clearUndoRedoStacks(QTextDocument::UndoAndRedoStacks); text = QString(); unreachableCharacterCount = 0; modifiedState = 0; @@ -292,7 +291,7 @@ QTextDocumentPrivate::~QTextDocumentPrivate() cursors.clear(); undoState = 0; undoEnabled = true; - truncateUndoStack(); + clearUndoRedoStacks(QTextDocument::RedoStack); } void QTextDocumentPrivate::setLayout(QAbstractTextDocumentLayout *layout) @@ -1027,7 +1026,7 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c) if (!undoEnabled) return; if (undoState < undoStack.size()) - truncateUndoStack(); + clearUndoRedoStacks(QTextDocument::RedoStack); if (!undoStack.isEmpty() && modified) { QTextUndoCommand &last = undoStack[undoState - 1]; @@ -1050,26 +1049,46 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c) emit document()->undoCommandAdded(); } -void QTextDocumentPrivate::truncateUndoStack() +void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToClear, + bool emitSignals) { - if (undoState == undoStack.size()) - return; - - for (int i = undoState; i < undoStack.size(); ++i) { - QTextUndoCommand c = undoStack[i]; - if (c.command & QTextUndoCommand::Removed) { - // ######## -// QTextFragment *f = c.fragment_list; -// while (f) { -// QTextFragment *n = f->right; -// delete f; -// f = n; -// } - } else if (c.command & QTextUndoCommand::Custom) { - delete c.custom; + bool undoCommandsAvailable = undoState != 0; + bool redoCommandsAvailable = undoState != undoStack.size(); + if (stacksToClear == QTextDocument::UndoStack && undoCommandsAvailable) { + for (int i = 0; i < undoState; ++i) { + QTextUndoCommand c = undoStack[undoState]; + if (c.command & QTextUndoCommand::Custom) + delete c.custom; } + undoStack.remove(0, undoState); + undoStack.resize(undoStack.size() - undoState); + undoState = 0; + if (emitSignals) + emitUndoAvailable(false); + } else if (stacksToClear == QTextDocument::RedoStack + && redoCommandsAvailable) { + for (int i = undoState; i < undoStack.size(); ++i) { + QTextUndoCommand c = undoStack[i]; + if (c.command & QTextUndoCommand::Custom) + delete c.custom; + } + undoStack.resize(undoState); + if (emitSignals) + emitRedoAvailable(false); + } else if (stacksToClear == QTextDocument::UndoAndRedoStacks + && !undoStack.isEmpty()) { + for (int i = 0; i < undoStack.size(); ++i) { + QTextUndoCommand c = undoStack[i]; + if (c.command & QTextUndoCommand::Custom) + delete c.custom; + } + undoState = 0; + undoStack.resize(0); + if (emitSignals && undoCommandsAvailable) + emitUndoAvailable(false); + if (emitSignals && redoCommandsAvailable) + emitRedoAvailable(false); } - undoStack.resize(undoState); } void QTextDocumentPrivate::emitUndoAvailable(bool available) @@ -1097,7 +1116,7 @@ void QTextDocumentPrivate::enableUndoRedo(bool enable) if (!enable) { undoState = 0; - truncateUndoStack(); + clearUndoRedoStacks(QTextDocument::RedoStack); emitUndoAvailable(false); emitRedoAvailable(false); } diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h index 4ecc2fa..ac5ed3c 100644 --- a/src/gui/text/qtextdocument_p.h +++ b/src/gui/text/qtextdocument_p.h @@ -252,10 +252,11 @@ public: inline QFont defaultFont() const { return formats.defaultFont(); } inline void setDefaultFont(const QFont &f) { formats.setDefaultFont(f); } + void clearUndoRedoStacks(QTextDocument::Stacks stacksToClear, bool emitSignals = false); + private: bool split(int pos); bool unite(uint f); - void truncateUndoStack(); void insert_string(int pos, uint strPos, uint length, int format, QTextUndoCommand::Operation op); int insert_block(int pos, uint strPos, int format, int blockformat, QTextUndoCommand::Operation op, int command); diff --git a/src/gui/text/qzip.cpp b/src/gui/text/qzip.cpp index 2fc1940..d30c996 100644 --- a/src/gui/text/qzip.cpp +++ b/src/gui/text/qzip.cpp @@ -54,10 +54,13 @@ #include <zlib.h> #if defined(Q_OS_WIN) -#undef S_IFREG -#define S_IFREG 0100000 +# undef S_IFREG +# define S_IFREG 0100000 +# ifndef S_IFDIR +# define S_IFDIR 0040000 +# endif # ifndef S_ISDIR -# define S_ISDIR(x) ((x) & 0040000) > 0 +# define S_ISDIR(x) ((x) & S_IFDIR) > 0 # endif # ifndef S_ISREG # define S_ISREG(x) ((x) & 0170000) == S_IFREG diff --git a/src/gui/text/qzipreader_p.h b/src/gui/text/qzipreader_p.h index 1086464..67a2ace 100644 --- a/src/gui/text/qzipreader_p.h +++ b/src/gui/text/qzipreader_p.h @@ -49,7 +49,7 @@ // ------------- // // This file is not part of the Qt API. It exists for the convenience -// of the QLibrary class. This header file may change from +// of the QZipReader class. This header file may change from // version to version without notice, or even be removed. // // We mean it. diff --git a/src/gui/text/qzipwriter_p.h b/src/gui/text/qzipwriter_p.h index 7b97937..9322f4a 100644 --- a/src/gui/text/qzipwriter_p.h +++ b/src/gui/text/qzipwriter_p.h @@ -47,7 +47,7 @@ // ------------- // // This file is not part of the Qt API. It exists for the convenience -// of the QLibrary class. This header file may change from +// of the QZipWriter class. This header file may change from // version to version without notice, or even be removed. // // We mean it. diff --git a/src/gui/widgets/qabstractscrollarea.cpp b/src/gui/widgets/qabstractscrollarea.cpp index 87f6c83..1d496d5 100644 --- a/src/gui/widgets/qabstractscrollarea.cpp +++ b/src/gui/widgets/qabstractscrollarea.cpp @@ -1134,13 +1134,10 @@ void QAbstractScrollArea::mouseMoveEvent(QMouseEvent *e) void QAbstractScrollArea::wheelEvent(QWheelEvent *e) { Q_D(QAbstractScrollArea); - QScrollBar *const bars[2] = { d->hbar, d->vbar }; - int idx = (e->orientation() == Qt::Vertical) ? 1 : 0; - int other = (idx + 1) % 2; - if (!bars[idx]->isVisible() && bars[other]->isVisible()) - idx = other; // If the scrollbar of the event orientation is hidden, fallback to the other. - - QApplication::sendEvent(bars[idx], e); + if (static_cast<QWheelEvent*>(e)->orientation() == Qt::Horizontal) + QApplication::sendEvent(d->hbar, e); + else + QApplication::sendEvent(d->vbar, e); } #endif diff --git a/src/gui/widgets/qabstractslider.cpp b/src/gui/widgets/qabstractslider.cpp index 2874647..73c17db 100644 --- a/src/gui/widgets/qabstractslider.cpp +++ b/src/gui/widgets/qabstractslider.cpp @@ -214,8 +214,8 @@ QT_BEGIN_NAMESPACE */ QAbstractSliderPrivate::QAbstractSliderPrivate() - : minimum(0), maximum(99), singleStep(1), pageStep(10), - value(0), position(0), pressValue(-1), offset_accumulated(0), tracking(true), + : minimum(0), maximum(99), pageStep(10), value(0), position(0), pressValue(-1), + singleStep(1), offset_accumulated(0), tracking(true), blocktracking(false), pressed(false), invertedAppearance(false), invertedControls(false), orientation(Qt::Horizontal), repeatAction(QAbstractSlider::SliderNoAction) @@ -688,51 +688,62 @@ void QAbstractSlider::sliderChange(SliderChange) update(); } - -/*! - \reimp -*/ -#ifndef QT_NO_WHEELEVENT -void QAbstractSlider::wheelEvent(QWheelEvent * e) +bool QAbstractSliderPrivate::scrollByDelta(Qt::Orientation orientation, Qt::KeyboardModifiers modifiers, int delta) { - Q_D(QAbstractSlider); - e->ignore(); - + Q_Q(QAbstractSlider); int stepsToScroll = 0; - qreal offset = qreal(e->delta()) / 120; + // in Qt scrolling to the right gives negative values. + if (orientation == Qt::Horizontal) + delta = -delta; + qreal offset = qreal(delta) / 120; - if ((e->modifiers() & Qt::ControlModifier) || (e->modifiers() & Qt::ShiftModifier)) { + if ((modifiers & Qt::ControlModifier) || (modifiers & Qt::ShiftModifier)) { // Scroll one page regardless of delta: - stepsToScroll = qBound(-d->pageStep, int(offset * d->pageStep), d->pageStep); - d->offset_accumulated = 0; + stepsToScroll = qBound(-pageStep, int(offset * pageStep), pageStep); + offset_accumulated = 0; } else { // Calculate how many lines to scroll. Depending on what delta is (and // offset), we might end up with a fraction (e.g. scroll 1.3 lines). We can // only scroll whole lines, so we keep the reminder until next event. - qreal stepsToScrollF = offset * QApplication::wheelScrollLines() * d->effectiveSingleStep(); + qreal stepsToScrollF = offset * QApplication::wheelScrollLines() * effectiveSingleStep(); // Check if wheel changed direction since last event: - if (d->offset_accumulated != 0 && (offset / d->offset_accumulated) < 0) - d->offset_accumulated = 0; + if (offset_accumulated != 0 && (offset / offset_accumulated) < 0) + offset_accumulated = 0; - d->offset_accumulated += stepsToScrollF; - stepsToScroll = qBound(-d->pageStep, int(d->offset_accumulated), d->pageStep); - d->offset_accumulated -= int(d->offset_accumulated); + offset_accumulated += stepsToScrollF; + stepsToScroll = qBound(-pageStep, int(offset_accumulated), pageStep); + offset_accumulated -= int(offset_accumulated); if (stepsToScroll == 0) - return; + return false; } - if (d->invertedControls) + if (invertedControls) stepsToScroll = -stepsToScroll; - int prevValue = d->value; - d->position = d->overflowSafeAdd(stepsToScroll); // value will be updated by triggerAction() - triggerAction(SliderMove); + int prevValue = value; + position = overflowSafeAdd(stepsToScroll); // value will be updated by triggerAction() + q->triggerAction(QAbstractSlider::SliderMove); + + if (prevValue == value) { + offset_accumulated = 0; + return false; + } + return true; +} - if (prevValue == d->value) - d->offset_accumulated = 0; - else +/*! + \reimp +*/ +#ifndef QT_NO_WHEELEVENT +void QAbstractSlider::wheelEvent(QWheelEvent * e) +{ + Q_D(QAbstractSlider); + e->ignore(); + int delta = e->delta(); + if (d->scrollByDelta(e->orientation(), e->modifiers(), delta)) e->accept(); } + #endif #ifdef QT_KEYPAD_NAVIGATION /*! diff --git a/src/gui/widgets/qabstractslider_p.h b/src/gui/widgets/qabstractslider_p.h index 6cde468..6e6ff6e 100644 --- a/src/gui/widgets/qabstractslider_p.h +++ b/src/gui/widgets/qabstractslider_p.h @@ -138,6 +138,7 @@ public: } q->triggerAction(repeatAction); } + bool scrollByDelta(Qt::Orientation orientation, Qt::KeyboardModifiers modifiers, int delta); }; QT_END_NAMESPACE diff --git a/src/gui/widgets/qdialogbuttonbox.cpp b/src/gui/widgets/qdialogbuttonbox.cpp index 48d7022..cc74a53 100644 --- a/src/gui/widgets/qdialogbuttonbox.cpp +++ b/src/gui/widgets/qdialogbuttonbox.cpp @@ -103,7 +103,7 @@ QT_BEGIN_NAMESPACE You can mix and match normal buttons and standard buttons. Currently the buttons are laid out in the following way if the button box is horizontal: - \table 100% + \table \row \o \inlineimage buttonbox-gnomelayout-horizontal.png GnomeLayout Horizontal \o Button box laid out in horizontal GnomeLayout \row \o \inlineimage buttonbox-kdelayout-horizontal.png KdeLayout Horizontal @@ -116,25 +116,23 @@ QT_BEGIN_NAMESPACE The buttons are laid out the following way if the button box is vertical: - \table 100% + \table + \row \o GnomeLayout + \o KdeLayout + \o MacLayout + \o WinLayout \row \o \inlineimage buttonbox-gnomelayout-vertical.png GnomeLayout Vertical - \o Button box laid out in vertical GnomeLayout - \row \o \inlineimage buttonbox-kdelayout-vertical.png KdeLayout Vertical - \o Button box laid out in vertical KdeLayout - \row \o \inlineimage buttonbox-maclayout-vertical.png MacLayout Vertical - \o Button box laid out in vertical MacLayout - \row \o \inlineimage buttonbox-winlayout-vertical.png WinLayout Vertical - \o Button box laid out in vertical WinLayout + \o \inlineimage buttonbox-kdelayout-vertical.png KdeLayout Vertical + \o \inlineimage buttonbox-maclayout-vertical.png MacLayout Vertical + \o \inlineimage buttonbox-winlayout-vertical.png WinLayout Vertical \endtable Additionally, button boxes that contain only buttons with ActionRole or - HelpRole can be considered modeless and have an alternate look on the mac: + HelpRole can be considered modeless and have an alternate look on Mac OS X: - \table 100% - \row \o \inlineimage buttonbox-mac-modeless-horizontal.png Screenshot of modeless horizontal MacLayout - \o modeless horizontal MacLayout - \row \o \inlineimage buttonbox-mac-modeless-vertical.png Screenshot of modeless vertical MacLayout - \o modeless vertical MacLayout + \table + \row \o modeless horizontal MacLayout + \o \inlineimage buttonbox-mac-modeless-horizontal.png Screenshot of modeless horizontal MacLayout \endtable When a button is clicked in the button box, the clicked() signal is emitted @@ -1017,6 +1015,8 @@ void QDialogButtonBox::removeButton(QAbstractButton *button) If the button has already been added, it is removed and added again with the new role. + \note The button box takes ownership of the button. + \sa removeButton(), clear() */ void QDialogButtonBox::addButton(QAbstractButton *button, ButtonRole role) diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp index d754800..13f31df 100644 --- a/src/gui/widgets/qdockarealayout.cpp +++ b/src/gui/widgets/qdockarealayout.cpp @@ -220,15 +220,17 @@ static quintptr tabId(const QDockAreaLayoutItem &item) } #endif +static const int zero = 0; + QDockAreaLayoutInfo::QDockAreaLayoutInfo() - : sep(0), dockPos(QInternal::LeftDock), o(Qt::Horizontal), mainWindow(0) + : sep(&zero), dockPos(QInternal::LeftDock), o(Qt::Horizontal), mainWindow(0) #ifndef QT_NO_TABBAR , tabbed(false), tabBar(0), tabBarShape(QTabBar::RoundedSouth), tabBarVisible(false) #endif { } -QDockAreaLayoutInfo::QDockAreaLayoutInfo(int _sep, QInternal::DockPosition _dockPos, +QDockAreaLayoutInfo::QDockAreaLayoutInfo(const int *_sep, QInternal::DockPosition _dockPos, Qt::Orientation _o, int tbshape, QMainWindow *window) : sep(_sep), dockPos(_dockPos), o(_o), mainWindow(window) @@ -281,7 +283,7 @@ QSize QDockAreaLayoutInfo::minimumSize() const #endif { if (!first) - a += sep; + a += *sep; a += pick(o, min_size); } b = qMax(b, perp(o, min_size)); @@ -349,7 +351,7 @@ QSize QDockAreaLayoutInfo::maximumSize() const #endif { if (!first) - a += sep; + a += *sep; a += pick(o, max_size); } b = qMin(b, perp(o, max_size)); @@ -415,7 +417,7 @@ QSize QDockAreaLayoutInfo::sizeHint() const { if (previous && !gap && !(previous->flags & QDockAreaLayoutItem::GapItem) && !previous->hasFixedSize(o)) { - a += sep; + a += *sep; } a += gap ? item.size : pick(o, size_hint); } @@ -491,7 +493,7 @@ static int realMinSize(const QDockAreaLayoutInfo &info) min = pick(info.o, item.minimumSize()); if (!first) - result += info.sep; + result += *info.sep; result += min; first = false; @@ -516,7 +518,7 @@ static int realMaxSize(const QDockAreaLayoutInfo &info) max = pick(info.o, item.maximumSize()); if (!first) - result += info.sep; + result += *info.sep; result += max; if (result >= QWIDGETSIZE_MAX) @@ -555,7 +557,7 @@ void QDockAreaLayoutInfo::fitItems() if (!(previous->flags & QDockAreaLayoutItem::GapItem)) { QLayoutStruct &ls = layout_struct_list[j++]; ls.init(); - ls.minimumSize = ls.maximumSize = ls.sizeHint = previous->hasFixedSize(o) ? 0 : sep; + ls.minimumSize = ls.maximumSize = ls.sizeHint = previous->hasFixedSize(o) ? 0 : *sep; ls.empty = false; } } @@ -938,7 +940,7 @@ int QDockAreaLayoutInfo::separatorMove(int index, int delta) if (item.skip()) { ls.empty = true; } else { - const int separatorSpace = item.hasFixedSize(o) ? 0 : sep; + const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep; ls.empty = false; ls.pos = item.pos; ls.size = item.size + separatorSpace; @@ -956,7 +958,7 @@ int QDockAreaLayoutInfo::separatorMove(int index, int delta) if (item.skip()) continue; QLayoutStruct &ls = list[i]; - const int separatorSpace = item.hasFixedSize(o) ? 0 : sep; + const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep; item.size = ls.size - separatorSpace; item.pos = ls.pos; if (item.subinfo != 0) { @@ -1041,11 +1043,11 @@ QLayoutItem *QDockAreaLayoutInfo::plug(const QList<int> &path) int next = this->next(index); if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) { - item.pos += sep; - item.size -= sep; + item.pos += *sep; + item.size -= *sep; } if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem)) - item.size -= sep; + item.size -= *sep; QPoint pos; rpick(o, pos) = item.pos; @@ -1083,11 +1085,11 @@ QLayoutItem *QDockAreaLayoutInfo::unplug(const QList<int> &path) #endif { if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) { - item.pos -= sep; - item.size += sep; + item.pos -= *sep; + item.size += *sep; } if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem)) - item.size += sep; + item.size += *sep; } return item.widgetItem; @@ -1255,9 +1257,9 @@ bool QDockAreaLayoutInfo::insertGap(const QList<int> &path, QLayoutItem *dockWid QRect r = dockedGeometry(dockWidgetItem->widget()); gap_size = pick(o, r.size()); if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) - sep_size += sep; + sep_size += *sep; if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem)) - sep_size += sep; + sep_size += *sep; } if (gap_size + sep_size > space) gap_size = pick(o, gap_item.minimumSize()); @@ -1364,7 +1366,7 @@ QRect QDockAreaLayoutInfo::separatorRect(int index) const QPoint pos = rect.topLeft(); rpick(o, pos) = item.pos + item.size; QSize s = rect.size(); - rpick(o, s) = sep; + rpick(o, s) = *sep; return QRect(pos, s); } @@ -1413,7 +1415,7 @@ QList<int> QDockAreaLayoutInfo::findSeparator(const QPoint &_pos) const continue; QRect sepRect = separatorRect(i); - if (!sepRect.isNull() && sep == 1) + if (!sepRect.isNull() && *sep == 1) sepRect.adjust(-2, -2, 2, 2); //we also make sure we don't find a separator that's not there if (sepRect.contains(_pos) && !item.hasFixedSize(o)) { @@ -1560,7 +1562,7 @@ void QDockAreaLayoutInfo::apply(bool animate) } } #ifndef QT_NO_TABBAR - if (sep == 1) + if (*sep == 1) updateSeparatorWidgets(); #endif //QT_NO_TABBAR } @@ -2010,7 +2012,7 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*> updateTabBar(); setCurrentTabId(tabId(item_list.at(index))); } - if (!testing && sep == 1) + if (!testing && *sep == 1) updateSeparatorWidgets(); #endif @@ -2273,13 +2275,13 @@ QDockAreaLayout::QDockAreaLayout(QMainWindow *win) : fallbackToSizeHints(true) const int tabShape = 0; #endif docks[QInternal::LeftDock] - = QDockAreaLayoutInfo(sep, QInternal::LeftDock, Qt::Vertical, tabShape, win); + = QDockAreaLayoutInfo(&sep, QInternal::LeftDock, Qt::Vertical, tabShape, win); docks[QInternal::RightDock] - = QDockAreaLayoutInfo(sep, QInternal::RightDock, Qt::Vertical, tabShape, win); + = QDockAreaLayoutInfo(&sep, QInternal::RightDock, Qt::Vertical, tabShape, win); docks[QInternal::TopDock] - = QDockAreaLayoutInfo(sep, QInternal::TopDock, Qt::Horizontal, tabShape, win); + = QDockAreaLayoutInfo(&sep, QInternal::TopDock, Qt::Horizontal, tabShape, win); docks[QInternal::BottomDock] - = QDockAreaLayoutInfo(sep, QInternal::BottomDock, Qt::Horizontal, tabShape, win); + = QDockAreaLayoutInfo(&sep, QInternal::BottomDock, Qt::Horizontal, tabShape, win); centralWidgetItem = 0; @@ -3028,7 +3030,7 @@ void QDockAreaLayout::addDockWidget(QInternal::DockPosition pos, QDockWidget *do #else int tbshape = 0; #endif - QDockAreaLayoutInfo new_info(sep, pos, orientation, tbshape, mainWindow); + QDockAreaLayoutInfo new_info(&sep, pos, orientation, tbshape, mainWindow); new_info.item_list.append(new QDockAreaLayoutInfo(info)); new_info.item_list.append(dockWidgetItem); info = new_info; @@ -3324,6 +3326,12 @@ void QDockAreaLayout::keepSize(QDockWidget *w) item.flags |= QDockAreaLayoutItem::KeepSize; } +void QDockAreaLayout::styleChangedEvent() +{ + sep = mainWindow->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent, 0, mainWindow); + fitLayout(); +} + QT_END_NAMESPACE #endif // QT_NO_DOCKWIDGET diff --git a/src/gui/widgets/qdockarealayout_p.h b/src/gui/widgets/qdockarealayout_p.h index 0bc1aa9..0088f00 100644 --- a/src/gui/widgets/qdockarealayout_p.h +++ b/src/gui/widgets/qdockarealayout_p.h @@ -128,7 +128,7 @@ class Q_AUTOTEST_EXPORT QDockAreaLayoutInfo { public: QDockAreaLayoutInfo(); - QDockAreaLayoutInfo(int _sep, QInternal::DockPosition _dockPos, Qt::Orientation _o, + QDockAreaLayoutInfo(const int *_sep, QInternal::DockPosition _dockPos, Qt::Orientation _o, int tbhape, QMainWindow *window); QSize minimumSize() const; @@ -189,7 +189,7 @@ public: QMainWindowLayout *mainWindowLayout() const; - int sep; + const int *sep; mutable QVector<QWidget*> separatorWidgets; QInternal::DockPosition dockPos; Qt::Orientation o; @@ -300,6 +300,7 @@ public: QSet<QTabBar*> usedTabBars() const; QSet<QWidget*> usedSeparatorWidgets() const; #endif //QT_NO_TABBAR + void styleChangedEvent(); }; QT_END_NAMESPACE diff --git a/src/gui/widgets/qlabel.cpp b/src/gui/widgets/qlabel.cpp index c779312..b81f04f 100644 --- a/src/gui/widgets/qlabel.cpp +++ b/src/gui/widgets/qlabel.cpp @@ -951,8 +951,8 @@ void QLabel::contextMenuEvent(QContextMenuEvent *ev) return; } ev->accept(); - menu->exec(ev->globalPos()); - delete menu; + menu->setAttribute(Qt::WA_DeleteOnClose); + menu->popup(ev->globalPos()); #endif } diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 2d2df92..141f844 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -2046,9 +2046,9 @@ void QLineEdit::dropEvent(QDropEvent* e) */ void QLineEdit::contextMenuEvent(QContextMenuEvent *event) { - QPointer<QMenu> menu = createStandardContextMenu(); - menu->exec(event->globalPos()); - delete menu; + QMenu *menu = createStandardContextMenu(); + menu->setAttribute(Qt::WA_DeleteOnClose); + menu->popup(event->globalPos()); } #if defined(Q_WS_WIN) diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp index 269cd12..a63f3bf 100644 --- a/src/gui/widgets/qmainwindow.cpp +++ b/src/gui/widgets/qmainwindow.cpp @@ -1393,6 +1393,7 @@ bool QMainWindow::event(QEvent *event) #endif // QT_NO_STATUSTIP case QEvent::StyleChange: + d->layout->layoutState.dockAreaLayout.styleChangedEvent(); if (!d->explicitIconSize) setIconSize(QSize()); break; @@ -1554,11 +1555,15 @@ void QMainWindow::contextMenuEvent(QContextMenuEvent *event) #ifndef QT_NO_MENU QMenu *popup = createPopupMenu(); - if (popup && !popup->isEmpty()) { - popup->exec(event->globalPos()); - event->accept(); + if (popup) { + if (!popup->isEmpty()) { + popup->setAttribute(Qt::WA_DeleteOnClose); + popup->popup(event->globalPos()); + event->accept(); + } else { + delete popup; + } } - delete popup; #endif } #endif // QT_NO_CONTEXTMENU diff --git a/src/gui/widgets/qmainwindowlayout.cpp b/src/gui/widgets/qmainwindowlayout.cpp index d1e7285..fc75c92 100644 --- a/src/gui/widgets/qmainwindowlayout.cpp +++ b/src/gui/widgets/qmainwindowlayout.cpp @@ -1627,6 +1627,13 @@ void QMainWindowLayout::animationFinished(QWidget *widget) tb->d_func()->plug(currentGapRect); #endif + savedState.clear(); + currentGapPos.clear(); + pluggingWidget = 0; + //applying the state will make sure that the currentGap is updated correctly + //and all the geometries (especially the one from the central widget) is correct + layoutState.apply(false); + #ifndef QT_NO_DOCKWIDGET #ifndef QT_NO_TABBAR if (qobject_cast<QDockWidget*>(widget) != 0) { @@ -1637,13 +1644,6 @@ void QMainWindowLayout::animationFinished(QWidget *widget) } #endif #endif - - savedState.clear(); - currentGapPos.clear(); - pluggingWidget = 0; - //applying the state will make sure that the currentGap is updated correctly - //and all the geometries (especially the one from the central widget) is correct - layoutState.apply(false); } if (!widgetAnimator.animating()) { diff --git a/src/gui/widgets/qmenu_mac.mm b/src/gui/widgets/qmenu_mac.mm index 658a020..99c550f 100644 --- a/src/gui/widgets/qmenu_mac.mm +++ b/src/gui/widgets/qmenu_mac.mm @@ -2030,6 +2030,18 @@ void qt_mac_clear_menubar() */ bool QMenuBar::macUpdateMenuBar() { +#ifdef QT_MAC_USE_COCOA + QMacCocoaAutoReleasePool pool; + if (!qt_cocoaPostMessage(getMenuLoader(), @selector(qtUpdateMenubar))) + return QMenuBarPrivate::macUpdateMenuBarImmediatly(); + return true; +#else + return QMenuBarPrivate::macUpdateMenuBarImmediatly(); +#endif +} + +bool QMenuBarPrivate::macUpdateMenuBarImmediatly() +{ bool ret = false; cancelAllMenuTracking(); QWidget *w = findWindowThatShouldDisplayMenubar(); @@ -2095,8 +2107,9 @@ bool QMenuBar::macUpdateMenuBar() } } - if(!ret) + if (!ret) { qt_mac_clear_menubar(); + } return ret; } diff --git a/src/gui/widgets/qmenubar_p.h b/src/gui/widgets/qmenubar_p.h index f2e5357..819aee4 100644 --- a/src/gui/widgets/qmenubar_p.h +++ b/src/gui/widgets/qmenubar_p.h @@ -196,6 +196,7 @@ public: return 0; } } *mac_menubar; + static bool macUpdateMenuBarImmediatly(); bool macWidgetHasNativeMenubar(QWidget *widget); void macCreateMenuBar(QWidget *); void macDestroyMenuBar(); diff --git a/src/gui/widgets/qscrollbar.cpp b/src/gui/widgets/qscrollbar.cpp index 73ce122..3eed3a9 100644 --- a/src/gui/widgets/qscrollbar.cpp +++ b/src/gui/widgets/qscrollbar.cpp @@ -521,6 +521,22 @@ bool QScrollBar::event(QEvent *event) if (const QHoverEvent *he = static_cast<const QHoverEvent *>(event)) d_func()->updateHoverControl(he->pos()); break; + case QEvent::Wheel: { + // override wheel event without adding virtual function override + QWheelEvent *ev = static_cast<QWheelEvent *>(event); + int delta = ev->delta(); + // scrollbar is a special case - in vertical mode it reaches minimum + // value in the upper position, however QSlider's minimum value is on + // the bottom. So we need to invert a value, but since the scrollbar is + // inverted by default, we need to inverse the delta value for the + // horizontal orientation. + if (ev->orientation() == Qt::Horizontal) + delta = -delta; + Q_D(QScrollBar); + if (d->scrollByDelta(ev->orientation(), ev->modifiers(), delta)) + event->accept(); + return true; + } default: break; } diff --git a/src/gui/widgets/qtoolbar.cpp b/src/gui/widgets/qtoolbar.cpp index 7782448..7ed27ea 100644 --- a/src/gui/widgets/qtoolbar.cpp +++ b/src/gui/widgets/qtoolbar.cpp @@ -441,8 +441,7 @@ void QToolBarPrivate::plug(const QRect &r) When a QToolBar is not a child of a QMainWindow, it looses the ability to populate the extension pop up with widgets added to the toolbar using addWidget(). Please use widget actions created by inheriting QWidgetAction - and implementing QWidgetAction::createWidget() instead. This is a known - issue which will be fixed in a future release. + and implementing QWidgetAction::createWidget() instead. \sa QToolButton, QMenu, QAction, {Application Example} */ |