diff options
Diffstat (limited to 'src/widgets')
85 files changed, 1771 insertions, 3419 deletions
diff --git a/src/widgets/configure.json b/src/widgets/configure.json index cc9019dfdd..0a68f082a2 100644 --- a/src/widgets/configure.json +++ b/src/widgets/configure.json @@ -378,6 +378,7 @@ "label": "QScroller", "purpose": "Enables kinetic scrolling for any scrolling widget or graphics item.", "section": "Widgets", + "condition": "features.easingcurve", "output": [ "publicFeature" ] }, "graphicsview": { @@ -626,12 +627,6 @@ "condition": "features.listview", "output": [ "publicFeature", "feature" ] }, - "paint_debug": { - "label": "Painting Debug Utilities", - "purpose": "Enabled debugging painting with the environment variables QT_FLUSH_UPDATE and QT_FLUSH_PAINT.", - "section": "Painting", - "output": [ "publicFeature", "feature" ] - }, "completer": { "label": "QCompleter", "purpose": "Provides completions based on an item model.", diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index c85b56d4f5..a1b9003c1c 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -2379,10 +2379,10 @@ QList<QUrl> QFileDialog::getOpenFileUrls(QWidget *parent, It can also be used on other platforms, where it will fall back to using QFileDialog. The function is asynchronous and returns immediately. The \a fileOpenCompleted - callback will be called when a file has been selected and its contents has been + callback will be called when a file has been selected and its contents have been read into memory. - \snippet code/src_gui_dialogs_qfiledialog.cpp 14 + \snippet code/src_gui_dialogs_qfiledialog.cpp 15 \since 5.13 */ void QFileDialog::getOpenFileContent(const QString &nameFilter, const std::function<void(const QString &, const QByteArray &)> &fileOpenCompleted) @@ -2448,6 +2448,51 @@ void QFileDialog::getOpenFileContent(const QString &nameFilter, const std::funct } /*! + This is a convenience static function that saves \a fileContent to a file, using + a file name and location chosen by the user. \a fileNameHint can be provided to + suggest a file name to the user. + + This function is used to save files to the local file system on Qt for WebAssembly, where + the web sandbox places restrictions on how such access may happen. Its implementation will + make the browser display a native file dialog, where the user makes the file selection. + + It can also be used on other platforms, where it will fall back to using QFileDialog. + + The function is asynchronous and returns immediately. + + \snippet code/src_gui_dialogs_qfiledialog.cpp 16 + \since 5.14 +*/ +void QFileDialog::saveFileContent(const QByteArray &fileContent, const QString &fileNameHint) +{ +#ifdef Q_OS_WASM + QWasmLocalFileAccess::saveFile(fileContent.constData(), fileContent.size(), fileNameHint.toStdString()); +#else + QFileDialog *dialog = new QFileDialog(); + dialog->setAcceptMode(QFileDialog::AcceptSave); + dialog->setFileMode(QFileDialog::AnyFile); + dialog->selectFile(fileNameHint); + + auto fileSelected = [=](const QString &fileName) { + if (!fileName.isNull()) { + QFile selectedFile(fileName); + if (selectedFile.open(QIODevice::WriteOnly)) + selectedFile.write(fileContent); + } + }; + + auto dialogClosed = [=](int code) { + Q_UNUSED(code); + delete dialog; + }; + + connect(dialog, &QFileDialog::fileSelected, fileSelected); + connect(dialog, &QFileDialog::finished, dialogClosed); + dialog->show(); +#endif +} + +/*! This is a convenience static function that will return a file name selected by the user. The file does not have to exist. diff --git a/src/widgets/dialogs/qfiledialog.h b/src/widgets/dialogs/qfiledialog.h index 354a1f928b..790f52f2e7 100644 --- a/src/widgets/dialogs/qfiledialog.h +++ b/src/widgets/dialogs/qfiledialog.h @@ -284,6 +284,7 @@ public: static void getOpenFileContent(const QString &nameFilter, const std::function<void(const QString &, const QByteArray &)> &fileContentsReady); + static void saveFileContent(const QByteArray &fileContent, const QString &fileNameHint = QString()); protected: QFileDialog(const QFileDialogArgs &args); diff --git a/src/widgets/dialogs/qfileinfogatherer.cpp b/src/widgets/dialogs/qfileinfogatherer.cpp index 9ab75e0b0a..0beca82f28 100644 --- a/src/widgets/dialogs/qfileinfogatherer.cpp +++ b/src/widgets/dialogs/qfileinfogatherer.cpp @@ -82,21 +82,6 @@ QFileInfoGatherer::QFileInfoGatherer(QObject *parent) : QThread(parent) , m_iconProvider(&defaultProvider) { -#if QT_CONFIG(filesystemwatcher) - watcher = new QFileSystemWatcher(this); - connect(watcher, SIGNAL(directoryChanged(QString)), this, SLOT(list(QString))); - connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(updateFile(QString))); - -# if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) - const QVariant listener = watcher->property("_q_driveListener"); - if (listener.canConvert<QObject *>()) { - if (QObject *driveListener = listener.value<QObject *>()) { - connect(driveListener, SIGNAL(driveAdded()), this, SLOT(driveAdded())); - connect(driveListener, SIGNAL(driveRemoved()), this, SLOT(driveRemoved())); - } - } -# endif // Q_OS_WIN && !Q_OS_WINRT -#endif start(LowPriority); } @@ -177,8 +162,8 @@ void QFileInfoGatherer::fetchExtendedInformation(const QString &path, const QStr if (files.isEmpty() && !path.isEmpty() && !path.startsWith(QLatin1String("//")) /*don't watch UNC path*/) { - if (!watcher->directories().contains(path)) - watcher->addPath(path); + if (!watchedDirectories().contains(path)) + watchPaths(QStringList(path)); } #endif } @@ -195,6 +180,91 @@ void QFileInfoGatherer::updateFile(const QString &filePath) fetchExtendedInformation(dir, QStringList(fileName)); } +QStringList QFileInfoGatherer::watchedFiles() const +{ +#if QT_CONFIG(filesystemwatcher) + if (m_watcher) + return m_watcher->files(); +#endif + return {}; +} + +QStringList QFileInfoGatherer::watchedDirectories() const +{ +#if QT_CONFIG(filesystemwatcher) + if (m_watcher) + return m_watcher->directories(); +#endif + return {}; +} + +void QFileInfoGatherer::createWatcher() +{ +#if QT_CONFIG(filesystemwatcher) + m_watcher = new QFileSystemWatcher(this); + connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, &QFileInfoGatherer::list); + connect(m_watcher, &QFileSystemWatcher::fileChanged, this, &QFileInfoGatherer::updateFile); +# if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) + const QVariant listener = m_watcher->property("_q_driveListener"); + if (listener.canConvert<QObject *>()) { + if (QObject *driveListener = listener.value<QObject *>()) { + connect(driveListener, SIGNAL(driveAdded()), this, SLOT(driveAdded())); + connect(driveListener, SIGNAL(driveRemoved()), this, SLOT(driveRemoved())); + } + } +# endif // Q_OS_WIN && !Q_OS_WINRT +#endif +} + +void QFileInfoGatherer::watchPaths(const QStringList &paths) +{ +#if QT_CONFIG(filesystemwatcher) + if (m_watching) { + if (m_watcher == nullptr) + createWatcher(); + m_watcher->addPaths(paths); + } +#else + Q_UNUSED(paths); +#endif +} + +void QFileInfoGatherer::unwatchPaths(const QStringList &paths) +{ +#if QT_CONFIG(filesystemwatcher) + if (m_watcher) + m_watcher->removePaths(paths); +#else + Q_UNUSED(paths); +#endif +} + +bool QFileInfoGatherer::isWatching() const +{ + bool result = false; +#if QT_CONFIG(filesystemwatcher) + QMutexLocker locker(&mutex); + result = m_watching; +#endif + return result; +} + +void QFileInfoGatherer::setWatching(bool v) +{ +#if QT_CONFIG(filesystemwatcher) + QMutexLocker locker(&mutex); + if (v != m_watching) { + if (!v) { + delete m_watcher; + m_watcher = nullptr; + } + m_watching = v; + } +#else + Q_UNUSED(v); +#endif +} + /* List all files in \a directoryPath @@ -204,8 +274,8 @@ void QFileInfoGatherer::clear() { #if QT_CONFIG(filesystemwatcher) QMutexLocker locker(&mutex); - watcher->removePaths(watcher->files()); - watcher->removePaths(watcher->directories()); + unwatchPaths(watchedFiles()); + unwatchPaths(watchedDirectories()); #endif } @@ -218,7 +288,7 @@ void QFileInfoGatherer::removePath(const QString &path) { #if QT_CONFIG(filesystemwatcher) QMutexLocker locker(&mutex); - watcher->removePath(path); + unwatchPaths(QStringList(path)); #else Q_UNUSED(path); #endif @@ -265,12 +335,13 @@ QExtendedInformation QFileInfoGatherer::getInfo(const QFileInfo &fileInfo) const static const bool watchFiles = qEnvironmentVariableIsSet("QT_FILESYSTEMMODEL_WATCH_FILES"); if (watchFiles) { if (!fileInfo.exists() && !fileInfo.isSymLink()) { - watcher->removePath(fileInfo.absoluteFilePath()); + const_cast<QFileInfoGatherer *>(this)-> + unwatchPaths(QStringList(fileInfo.absoluteFilePath())); } else { const QString path = fileInfo.absoluteFilePath(); if (!path.isEmpty() && fileInfo.exists() && fileInfo.isFile() && fileInfo.isReadable() - && !watcher->files().contains(path)) { - watcher->addPath(path); + && !watchedFiles().contains(path)) { + const_cast<QFileInfoGatherer *>(this)->watchPaths(QStringList(path)); } } } diff --git a/src/widgets/dialogs/qfileinfogatherer_p.h b/src/widgets/dialogs/qfileinfogatherer_p.h index 829c620c1e..3d30a98d04 100644 --- a/src/widgets/dialogs/qfileinfogatherer_p.h +++ b/src/widgets/dialogs/qfileinfogatherer_p.h @@ -169,12 +169,13 @@ public: explicit QFileInfoGatherer(QObject *parent = nullptr); ~QFileInfoGatherer(); -#if QT_CONFIG(filesystemwatcher) && defined(Q_OS_WIN) - QStringList watchedFiles() const { return watcher->files(); } - QStringList watchedDirectories() const { return watcher->directories(); } - void watchPaths(const QStringList &paths) { watcher->addPaths(paths); } - void unwatchPaths(const QStringList &paths) { watcher->removePaths(paths); } -#endif // filesystemwatcher && Q_OS_WIN + QStringList watchedFiles() const; + QStringList watchedDirectories() const; + void watchPaths(const QStringList &paths); + void unwatchPaths(const QStringList &paths); + + bool isWatching() const; + void setWatching(bool v); // only callable from this->thread(): void clear(); @@ -201,6 +202,8 @@ private: void fetch(const QFileInfo &info, QElapsedTimer &base, bool &firstTime, QVector<QPair<QString, QFileInfo> > &updatedFiles, const QString &path); private: + void createWatcher(); + mutable QMutex mutex; // begin protected by mutex QWaitCondition condition; @@ -210,13 +213,16 @@ private: QAtomicInt abort; #if QT_CONFIG(filesystemwatcher) - QFileSystemWatcher *watcher = nullptr; + QFileSystemWatcher *m_watcher = nullptr; #endif QFileIconProvider *m_iconProvider; // not accessed by run() QFileIconProvider defaultProvider; #ifdef Q_OS_WIN bool m_resolveSymlinks = true; // not accessed by run() #endif +#if QT_CONFIG(filesystemwatcher) + bool m_watching = true; +#endif }; QT_END_NAMESPACE diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index 820fc6e220..e9e49e0c33 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -1264,6 +1264,107 @@ Qt::DropActions QFileSystemModel::supportedDropActions() const } /*! + \enum QFileSystemModel::Option + \since 5.14 + + \value DontWatchForChanges Do not add file watchers to the paths. + This reduces overhead when using the model for simple tasks + like line edit completion. + + \value DontResolveSymlinks Don't resolve symlinks in the file + system model. By default, symlinks are resolved. + + \value DontUseCustomDirectoryIcons Always use the default directory icon. + Some platforms allow the user to set a different icon. Custom icon lookup + causes a big performance impact over network or removable drives. + This sets the QFileIconProvider::DontUseCustomDirectoryIcons + option in the icon provider accordingly. + + \sa resolveSymlinks +*/ + +/*! + \since 5.14 + Sets the given \a option to be enabled if \a on is true; otherwise, + clears the given \a option. + + Options should be set before changing properties. + + \sa options, testOption() +*/ +void QFileSystemModel::setOption(Option option, bool on) +{ + QFileSystemModel::Options previousOptions = options(); + setOptions(previousOptions.setFlag(option, on)); +} + +/*! + \since 5.14 + + Returns \c true if the given \a option is enabled; otherwise, returns + false. + + \sa options, setOption() +*/ +bool QFileSystemModel::testOption(Option option) const +{ + return options().testFlag(option); +} + +/*! + \property QFileSystemModel::options + \brief the various options that affect the model + \since 5.14 + + By default, all options are disabled. + + Options should be set before changing properties. + + \sa setOption(), testOption() +*/ +void QFileSystemModel::setOptions(Options options) +{ + const Options changed = (options ^ QFileSystemModel::options()); + + if (changed.testFlag(DontResolveSymlinks)) + setResolveSymlinks(!options.testFlag(DontResolveSymlinks)); + +#if QT_CONFIG(filesystemwatcher) + Q_D(QFileSystemModel); + if (changed.testFlag(DontWatchForChanges)) + d->fileInfoGatherer.setWatching(!options.testFlag(DontWatchForChanges)); +#endif + + if (changed.testFlag(DontUseCustomDirectoryIcons)) { + if (auto provider = iconProvider()) { + QFileIconProvider::Options providerOptions = provider->options(); + providerOptions.setFlag(QFileIconProvider::DontUseCustomDirectoryIcons, + options.testFlag(QFileSystemModel::DontUseCustomDirectoryIcons)); + provider->setOptions(providerOptions); + } else { + qWarning("Setting QFileSystemModel::DontUseCustomDirectoryIcons has no effect when no provider is used"); + } + } +} + +QFileSystemModel::Options QFileSystemModel::options() const +{ + QFileSystemModel::Options result; + result.setFlag(DontResolveSymlinks, !resolveSymlinks()); +#if QT_CONFIG(filesystemwatcher) + Q_D(const QFileSystemModel); + result.setFlag(DontWatchForChanges, !d->fileInfoGatherer.isWatching()); +#else + result.setFlag(DontWatchForChanges); +#endif + if (auto provider = iconProvider()) { + result.setFlag(DontUseCustomDirectoryIcons, + provider->options().testFlag(QFileIconProvider::DontUseCustomDirectoryIcons)); + } + return result; +} + +/*! Returns the path of the item stored in the model under the \a index given. */ @@ -1509,6 +1610,8 @@ QDir::Filters QFileSystemModel::filter() const This is only relevant on Windows. By default, this property is \c true. + + \sa QFileSystemModel::Options */ void QFileSystemModel::setResolveSymlinks(bool enable) { diff --git a/src/widgets/dialogs/qfilesystemmodel.h b/src/widgets/dialogs/qfilesystemmodel.h index c2c8b8818e..b0f289dfcd 100644 --- a/src/widgets/dialogs/qfilesystemmodel.h +++ b/src/widgets/dialogs/qfilesystemmodel.h @@ -61,6 +61,7 @@ class Q_WIDGETS_EXPORT QFileSystemModel : public QAbstractItemModel Q_PROPERTY(bool resolveSymlinks READ resolveSymlinks WRITE setResolveSymlinks) Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly) Q_PROPERTY(bool nameFilterDisables READ nameFilterDisables WRITE setNameFilterDisables) + Q_PROPERTY(Options options READ options WRITE setOptions) Q_SIGNALS: void rootPathChanged(const QString &newPath); @@ -75,6 +76,15 @@ public: FilePermissions = Qt::UserRole + 3 }; + enum Option + { + DontWatchForChanges = 0x00000001, + DontResolveSymlinks = 0x00000002, + DontUseCustomDirectoryIcons = 0x00000004 + }; + Q_ENUM(Option) + Q_DECLARE_FLAGS(Options, Option) + explicit QFileSystemModel(QObject *parent = nullptr); ~QFileSystemModel(); @@ -129,6 +139,11 @@ public: void setNameFilters(const QStringList &filters); QStringList nameFilters() const; + void setOption(Option option, bool on = true); + bool testOption(Option option) const; + void setOptions(Options options); + Options options() const; + QString filePath(const QModelIndex &index) const; bool isDir(const QModelIndex &index) const; qint64 size(const QModelIndex &index) const; @@ -165,6 +180,8 @@ inline QString QFileSystemModel::fileName(const QModelIndex &aindex) const inline QIcon QFileSystemModel::fileIcon(const QModelIndex &aindex) const { return qvariant_cast<QIcon>(aindex.data(Qt::DecorationRole)); } +Q_DECLARE_OPERATORS_FOR_FLAGS(QFileSystemModel::Options) + QT_END_NAMESPACE #endif // QFILESYSTEMMODEL_H diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp index 4d28dda7c7..7558054da5 100644 --- a/src/widgets/dialogs/qwizard.cpp +++ b/src/widgets/dialogs/qwizard.cpp @@ -1336,7 +1336,7 @@ void QWizardPrivate::updateMinMaxSizes(const QWizardLayoutInfo &info) int extraHeight = 0; #if QT_CONFIG(style_windowsvista) if (isVistaThemeEnabled()) - extraHeight = vistaHelper->titleBarSize() + vistaHelper->topOffset(); + extraHeight = vistaHelper->titleBarSize() + vistaHelper->topOffset(q); #endif QSize minimumSize = mainLayout->totalMinimumSize() + QSize(0, extraHeight); QSize maximumSize = mainLayout->totalMaximumSize(); @@ -1595,8 +1595,8 @@ bool QWizardPrivate::handleAeroStyleChange() bool vistaMargins = false; if (isVistaThemeEnabled()) { - const int topOffset = vistaHelper->topOffset(); - const int topPadding = vistaHelper->topPadding(); + const int topOffset = vistaHelper->topOffset(q); + const int topPadding = vistaHelper->topPadding(q); if (isVistaThemeEnabled(QVistaHelper::VistaAero)) { if (isWindow) { vistaHelper->setDWMTitleBar(QVistaHelper::ExtendedTitleBar); @@ -2892,7 +2892,7 @@ void QWizard::setPixmap(WizardPixmap which, const QPixmap &pixmap) Returns the pixmap set for role \a which. By default, the only pixmap that is set is the BackgroundPixmap on - \macos. + \macos version 10.13 and earlier. \sa QWizardPage::pixmap(), {Elements of a Wizard Page} */ @@ -3214,7 +3214,7 @@ void QWizard::resizeEvent(QResizeEvent *event) int heightOffset = 0; #if QT_CONFIG(style_windowsvista) if (d->isVistaThemeEnabled()) { - heightOffset = d->vistaHelper->topOffset(); + heightOffset = d->vistaHelper->topOffset(this); if (d->isVistaThemeEnabled(QVistaHelper::VistaAero)) heightOffset += d->vistaHelper->titleBarSize(); } @@ -3246,7 +3246,7 @@ void QWizard::paintEvent(QPaintEvent * event) if (d->isVistaThemeEnabled(QVistaHelper::VistaBasic)) { QPainter painter(this); QColor color = d->vistaHelper->basicWindowFrameColor(); - painter.fillRect(0, 0, width(), QVistaHelper::topOffset(), color); + painter.fillRect(0, 0, width(), QVistaHelper::topOffset(this), color); } d->vistaHelper->paintEvent(event); } diff --git a/src/widgets/dialogs/qwizard_win.cpp b/src/widgets/dialogs/qwizard_win.cpp index 95f8f6a878..47ac41a791 100644 --- a/src/widgets/dialogs/qwizard_win.cpp +++ b/src/widgets/dialogs/qwizard_win.cpp @@ -87,7 +87,7 @@ QVistaBackButton::QVistaBackButton(QWidget *widget) QSize QVistaBackButton::sizeHint() const { ensurePolished(); - int size = int(QStyleHelper::dpiScaled(32)); + int size = int(QStyleHelper::dpiScaled(32, this)); int width = size, height = size; return QSize(width, height); } @@ -156,7 +156,7 @@ QVistaHelper::QVistaHelper(QWizard *wizard) backButton_ = new QVistaBackButton(wizard); backButton_->hide(); - iconSpacing = QStyleHelper::dpiScaled(7); + iconSpacing = QStyleHelper::dpiScaled(7, wizard); } QVistaHelper::~QVistaHelper() @@ -229,7 +229,7 @@ bool QVistaHelper::setDWMTitleBar(TitleBarChangeType type) if (type == NormalTitleBar) mar.cyTopHeight = 0; else - mar.cyTopHeight = (titleBarSize() + topOffset()) * QVistaHelper::m_devicePixelRatio; + mar.cyTopHeight = (titleBarSize() + topOffset(wizard)) * QVistaHelper::m_devicePixelRatio; if (const HWND wizardHandle = wizardHWND()) if (SUCCEEDED(DwmExtendFrameIntoClientArea(wizardHandle, &mar))) value = true; @@ -275,7 +275,7 @@ void QVistaHelper::drawTitleBar(QPainter *painter) if (vistaState() == VistaAero && isWindow) drawBlackRect(QRect(0, 0, wizard->width(), - titleBarSize() + topOffset()), hdc); + titleBarSize() + topOffset(wizard)), hdc); // The button is positioned in QWizardPrivate::handleAeroStyleChange(), // all calculation is relative to it. const int btnTop = backButton_->mapToParent(QPoint()).y(); @@ -293,7 +293,7 @@ void QVistaHelper::drawTitleBar(QPainter *painter) int glowOffset = 0; if (vistaState() == VistaAero) { - glowOffset = glowSize(); + glowOffset = glowSize(wizard); textHeight += 2 * glowOffset; textWidth += 2 * glowOffset; } @@ -314,10 +314,10 @@ void QVistaHelper::drawTitleBar(QPainter *painter) const QIcon windowIcon = wizard->windowIcon(); if (!windowIcon.isNull()) { - const int size = QVistaHelper::iconSize(); + const int size = QVistaHelper::iconSize(wizard); const int iconLeft = (wizard->layoutDirection() == Qt::LeftToRight - ? leftMargin() - : wizard->width() - leftMargin() - size); + ? leftMargin(wizard) + : wizard->width() - leftMargin(wizard) - size); const QPoint pos(origin.x() + iconLeft, origin.y() + verticalCenter - size / 2); const QPoint posDp = pos * QVistaHelper::m_devicePixelRatio; @@ -427,7 +427,7 @@ void QVistaHelper::resizeEvent(QResizeEvent * event) { Q_UNUSED(event); rtTop = QRect (0, 0, wizard->width(), frameSize()); - int height = captionSize() + topOffset(); + int height = captionSize() + topOffset(wizard); if (vistaState() == VistaBasic) height -= titleBarSize(); rtTitle = QRect (0, frameSize(), wizard->width(), height); @@ -637,7 +637,7 @@ bool QVistaHelper::drawTitleText(QPainter *painter, const QString &text, const Q RECT rctext ={0,0, rectDp.width(), rectDp.height()}; dto.dwFlags = DTT_COMPOSITED|DTT_GLOWSIZE; - dto.iGlowSize = glowSize(); + dto.iGlowSize = glowSize(wizard); DrawThemeTextEx(hTheme, dcMem, 0, 0, reinterpret_cast<LPCWSTR>(text.utf16()), -1, uFormat, &rctext, &dto ); BitBlt(hdc, rectDp.left(), rectDp.top(), rectDp.width(), rectDp.height(), dcMem, 0, 0, SRCCOPY); @@ -714,27 +714,27 @@ int QVistaHelper::captionSizeDp() int QVistaHelper::titleOffset() { - int iconOffset = wizard ->windowIcon().isNull() ? 0 : iconSize() + iconSpacing; - return leftMargin() + iconOffset; + int iconOffset = wizard ->windowIcon().isNull() ? 0 : iconSize(wizard) + iconSpacing; + return leftMargin(wizard) + iconOffset; } -int QVistaHelper::iconSize() +int QVistaHelper::iconSize(const QPaintDevice *device) { - return QStyleHelper::dpiScaled(16); // Standard Aero + return QStyleHelper::dpiScaled(16, device); // Standard Aero } -int QVistaHelper::glowSize() +int QVistaHelper::glowSize(const QPaintDevice *device) { - return QStyleHelper::dpiScaled(10); + return QStyleHelper::dpiScaled(10, device); } -int QVistaHelper::topOffset() +int QVistaHelper::topOffset(const QPaintDevice *device) { if (vistaState() != VistaAero) return titleBarSize() + 3; static const int aeroOffset = QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8 ? - QStyleHelper::dpiScaled(4) : QStyleHelper::dpiScaled(13); + QStyleHelper::dpiScaled(4, device) : QStyleHelper::dpiScaled(13, device); return aeroOffset + titleBarSize(); } diff --git a/src/widgets/dialogs/qwizard_win_p.h b/src/widgets/dialogs/qwizard_win_p.h index b3796e3f48..2469496b61 100644 --- a/src/widgets/dialogs/qwizard_win_p.h +++ b/src/widgets/dialogs/qwizard_win_p.h @@ -108,10 +108,10 @@ public: static VistaState vistaState(); static int titleBarSize() { return QVistaHelper::titleBarSizeDp() / QVistaHelper::m_devicePixelRatio; } static int titleBarSizeDp() { return QVistaHelper::frameSizeDp() + QVistaHelper::captionSizeDp(); } - static int topPadding() { // padding under text - return int(QStyleHelper::dpiScaled(4)); + static int topPadding(const QPaintDevice *device) { // padding under text + return int(QStyleHelper::dpiScaled(4, device)); } - static int topOffset(); + static int topOffset(const QPaintDevice *device); static HDC backingStoreDC(const QWidget *wizard, QPoint *offset); @@ -125,10 +125,12 @@ private: static int captionSize() { return QVistaHelper::captionSizeDp() / QVistaHelper::m_devicePixelRatio; } static int captionSizeDp(); - static int backButtonSize() { return int(QStyleHelper::dpiScaled(30)); } - static int iconSize(); - static int glowSize(); - int leftMargin() { return backButton_->isVisible() ? backButtonSize() + iconSpacing : 0; } + static int backButtonSize(const QPaintDevice *device) + { return int(QStyleHelper::dpiScaled(30, device)); } + static int iconSize(const QPaintDevice *device); + static int glowSize(const QPaintDevice *device); + int leftMargin(const QPaintDevice *device) + { return backButton_->isVisible() ? backButtonSize(device) + iconSpacing : 0; } int titleOffset(); void drawTitleBar(QPainter *painter); diff --git a/src/widgets/doc/snippets/code/doc_src_styles.cpp b/src/widgets/doc/snippets/code/doc_src_styles.cpp index a70ed6b11d..3536be6e7b 100644 --- a/src/widgets/doc/snippets/code/doc_src_styles.cpp +++ b/src/widgets/doc/snippets/code/doc_src_styles.cpp @@ -81,11 +81,6 @@ state |= QStyle::State_MouseOver; if (widget->window()->isActiveWindow()) state |= QStyle::State_Active; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - extern bool qt_mac_can_clickThrough(const QWidget *w); //qwidget_mac.cpp - if (!(state & QStyle::State_Active) && !qt_mac_can_clickThrough(widget)) - state &= ~QStyle::State_Enabled; -#endif #ifdef QT_KEYPAD_NAVIGATION if (widget->hasEditFocus()) state |= QStyle::State_HasEditFocus; diff --git a/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp b/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp index 1e9daf824b..7ccd827a04 100644 --- a/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp +++ b/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp @@ -145,8 +145,8 @@ dialog.exec(); "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)" //! [14] -//! [14] -auto fileOpenCompleted = [](const QSting &fileName, const QByteArray &fileContent) { +//! [15] +auto fileOpenCompleted = [](const QString &fileName, const QByteArray &fileContent) { if (fileName.isEmpty()) { // No file was selected } else { @@ -154,4 +154,9 @@ auto fileOpenCompleted = [](const QSting &fileName, const QByteArray &fileConten } } QFileDialog::getOpenFileContent("Images (*.png *.xpm *.jpg)", fileContentReady); -//! [14] +//! [15] + +//! [16] +QByteArray imageData; // obtained from e.g. QImage::save() +QFileDialog::saveFile("myimage.png", imageData); +//! [16] diff --git a/src/widgets/doc/snippets/macmainwindow.mm b/src/widgets/doc/snippets/macmainwindow.mm deleted file mode 100644 index c63796a3f2..0000000000 --- a/src/widgets/doc/snippets/macmainwindow.mm +++ /dev/null @@ -1,290 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "macmainwindow.h" -#import <AppKit/AppKit.h> -#include <QtGui> - - -#if 0 // Used to be included in Qt4 for Q_WS_MAC - -//![0] -SearchWidget::SearchWidget(QWidget *parent) - : QMacCocoaViewContainer(0, parent) -{ - // Many Cocoa objects create temporary autorelease objects, - // so create a pool to catch them. - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - // Create the NSSearchField, set it on the QCocoaViewContainer. - NSSearchField *search = [[NSSearchField alloc] init]; - setCocoaView(search); - - // Use a Qt menu for the search field menu. - QMenu *qtMenu = createMenu(this); - NSMenu *nsMenu = qtMenu->macMenu(0); - [[search cell] setSearchMenuTemplate:nsMenu]; - - // Release our reference, since our super class takes ownership and we - // don't need it anymore. - [search release]; - - // Clean up our pool as we no longer need it. - [pool release]; -} -//![0] - -SearchWidget::~SearchWidget() -{ -} - -QSize SearchWidget::sizeHint() const -{ - return QSize(150, 40); -} - -QMenu *createMenu(QWidget *parent) -{ - QMenu *searchMenu = new QMenu(parent); - - QAction * indexAction = searchMenu->addAction("Index Search"); - indexAction->setCheckable(true); - indexAction->setChecked(true); - - QAction * fulltextAction = searchMenu->addAction("Full Text Search"); - fulltextAction->setCheckable(true); - - QActionGroup *searchActionGroup = new QActionGroup(parent); - searchActionGroup->addAction(indexAction); - searchActionGroup->addAction(fulltextAction); - searchActionGroup->setExclusive(true); - - return searchMenu; -} - -SearchWrapper::SearchWrapper(QWidget *parent) -:QWidget(parent) -{ - s = new SearchWidget(this); - s->move(2,2); - setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); -} - -QSize SearchWrapper::sizeHint() const -{ - return s->sizeHint() + QSize(6, 2); -} - -Spacer::Spacer(QWidget *parent) -:QWidget(parent) -{ - QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - setSizePolicy(sizePolicy); -} - -QSize Spacer::sizeHint() const -{ - return QSize(1, 1); -} - -MacSplitterHandle::MacSplitterHandle(Qt::Orientation orientation, QSplitter *parent) -: QSplitterHandle(orientation, parent) { } - -// Paint the horizontal handle as a gradient, paint -// the vertical handle as a line. -void MacSplitterHandle::paintEvent(QPaintEvent *) -{ - QPainter painter(this); - - QColor topColor(145, 145, 145); - QColor bottomColor(142, 142, 142); - QColor gradientStart(252, 252, 252); - QColor gradientStop(223, 223, 223); - - if (orientation() == Qt::Vertical) { - painter.setPen(topColor); - painter.drawLine(0, 0, width(), 0); - painter.setPen(bottomColor); - painter.drawLine(0, height() - 1, width(), height() - 1); - - QLinearGradient linearGrad(QPointF(0, 0), QPointF(0, height() -3)); - linearGrad.setColorAt(0, gradientStart); - linearGrad.setColorAt(1, gradientStop); - painter.fillRect(QRect(QPoint(0,1), size() - QSize(0, 2)), QBrush(linearGrad)); - } else { - painter.setPen(topColor); - painter.drawLine(0, 0, 0, height()); - } -} - -QSize MacSplitterHandle::sizeHint() const -{ - QSize parent = QSplitterHandle::sizeHint(); - if (orientation() == Qt::Vertical) { - return parent + QSize(0, 3); - } else { - return QSize(1, parent.height()); - } -} - -QSplitterHandle *MacSplitter::createHandle() -{ - return new MacSplitterHandle(orientation(), this); -} - -MacMainWindow::MacMainWindow() -{ - QSettings settings; - restoreGeometry(settings.value("Geometry").toByteArray()); - - setWindowTitle("Mac Main Window"); - - splitter = new MacSplitter(); - - // Set up the left-hand side blue side bar. - sidebar = new QTreeView(); - sidebar->setFrameStyle(QFrame::NoFrame); - sidebar->setAttribute(Qt::WA_MacShowFocusRect, false); - sidebar->setAutoFillBackground(true); - - // Set the palette. - QPalette palette = sidebar->palette(); - QColor macSidebarColor(231, 237, 246); - QColor macSidebarHighlightColor(168, 183, 205); - palette.setColor(QPalette::Base, macSidebarColor); - palette.setColor(QPalette::Highlight, macSidebarHighlightColor); - sidebar->setPalette(palette); - - sidebar->setModel(createItemModel()); - sidebar->header()->hide(); - sidebar->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - sidebar->setTextElideMode(Qt::ElideMiddle); - - splitter->addWidget(sidebar); - - horizontalSplitter = new MacSplitter(); - horizontalSplitter->setOrientation(Qt::Vertical); - splitter->addWidget(horizontalSplitter); - - splitter->setStretchFactor(0, 0); - splitter->setStretchFactor(1, 1); - - // Set up the top document list view. - documents = new QListView(); - documents->setFrameStyle(QFrame::NoFrame); - documents->setAttribute(Qt::WA_MacShowFocusRect, false); - documents->setModel(createDocumentModel()); - documents->setAlternatingRowColors(true); - documents->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - horizontalSplitter->addWidget(documents); - horizontalSplitter->setStretchFactor(0, 0); - - // Set up the text view. - textedit = new QTextEdit(); - textedit->setFrameStyle(QFrame::NoFrame); - textedit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - textedit->setText("<br><br><br><br><br><br><center><b>This demo shows how to create a \ - Qt main window application that has the same appearance as other \ - OS X applications such as Mail or iTunes. This includes \ - customizing the item views and QSplitter and wrapping native widgets \ - such as the search field.</b></center>"); - - horizontalSplitter->addWidget(textedit); - - setCentralWidget(splitter); - - toolBar = addToolBar(tr("Search")); - toolBar->addWidget(new Spacer()); - toolBar->addWidget(new SearchWrapper()); - - setUnifiedTitleAndToolBarOnMac(true); -} - -MacMainWindow::~MacMainWindow() -{ - QSettings settings; - settings.setValue("Geometry", saveGeometry()); -} - -QAbstractItemModel *MacMainWindow::createItemModel() -{ - QStandardItemModel *model = new QStandardItemModel(); - QStandardItem *parentItem = model->invisibleRootItem(); - - QStandardItem *documentationItem = new QStandardItem("Documentation"); - parentItem->appendRow(documentationItem); - - QStandardItem *assistantItem = new QStandardItem("Qt MainWindow Manual"); - documentationItem->appendRow(assistantItem); - - QStandardItem *designerItem = new QStandardItem("Qt Designer Manual"); - documentationItem->appendRow(designerItem); - - QStandardItem *qtItem = new QStandardItem("Qt Reference Documentation"); - qtItem->appendRow(new QStandardItem("Classes")); - qtItem->appendRow(new QStandardItem("Overviews")); - qtItem->appendRow(new QStandardItem("Tutorial & Examples")); - documentationItem->appendRow(qtItem); - - QStandardItem *bookmarksItem = new QStandardItem("Bookmarks"); - parentItem->appendRow(bookmarksItem); - bookmarksItem->appendRow(new QStandardItem("QWidget")); - bookmarksItem->appendRow(new QStandardItem("QObject")); - bookmarksItem->appendRow(new QStandardItem("QWizard")); - - return model; -} - -void MacMainWindow::resizeEvent(QResizeEvent *) -{ - if (toolBar) - toolBar->updateGeometry(); -} - -QAbstractItemModel *MacMainWindow::createDocumentModel() -{ - QStandardItemModel *model = new QStandardItemModel(); - QStandardItem *parentItem = model->invisibleRootItem(); - parentItem->appendRow(new QStandardItem("QWidget Class Reference")); - parentItem->appendRow(new QStandardItem("QObject Class Reference")); - parentItem->appendRow(new QStandardItem("QListView Class Reference")); - - return model; -} - -#endif diff --git a/src/widgets/graphicsview/graphicsview.pri b/src/widgets/graphicsview/graphicsview.pri index 7d10244634..d69a6f5c3f 100644 --- a/src/widgets/graphicsview/graphicsview.pri +++ b/src/widgets/graphicsview/graphicsview.pri @@ -4,7 +4,6 @@ qtConfig(graphicsview) { HEADERS += graphicsview/qgraphicsgridlayout.h \ graphicsview/qgraphicsitem.h \ graphicsview/qgraphicsitem_p.h \ - graphicsview/qgraphicsitemanimation.h \ graphicsview/qgraphicslayout.h \ graphicsview/qgraphicslayout_p.h \ graphicsview/qgraphicslayoutitem.h \ @@ -34,7 +33,6 @@ HEADERS += graphicsview/qgraphicsgridlayout.h \ SOURCES += graphicsview/qgraphicsgridlayout.cpp \ graphicsview/qgraphicsitem.cpp \ - graphicsview/qgraphicsitemanimation.cpp \ graphicsview/qgraphicslayout.cpp \ graphicsview/qgraphicslayout_p.cpp \ graphicsview/qgraphicslayoutitem.cpp \ @@ -55,4 +53,9 @@ SOURCES += graphicsview/qgraphicsgridlayout.cpp \ graphicsview/qsimplex_p.cpp \ graphicsview/qgraphicsanchorlayout_p.cpp \ graphicsview/qgraphicsanchorlayout.cpp + + qtConfig(easingcurve) { + HEADERS += graphicsview/qgraphicsitemanimation.h + SOURCES += graphicsview/qgraphicsitemanimation.cpp + } } diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp index ca30c72db5..bb00db4c01 100644 --- a/src/widgets/graphicsview/qgraphicsitem.cpp +++ b/src/widgets/graphicsview/qgraphicsitem.cpp @@ -7566,19 +7566,6 @@ void QGraphicsItem::setInputMethodHints(Qt::InputMethodHints hints) */ void QGraphicsItem::updateMicroFocus() { -#if !defined(QT_NO_IM) && 0 /* Used to be included in Qt4 for Q_WS_X11 */ - if (QWidget *fw = QApplication::focusWidget()) { - if (scene()) { - for (int i = 0 ; i < scene()->views().count() ; ++i) { - if (scene()->views().at(i) == fw) { - if (qApp) - QGuiApplication::inputMethod()->update(Qt::ImQueryAll); - break; - } - } - } - } -#endif } /*! @@ -11536,9 +11523,11 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemChange change) case QGraphicsItem::ItemFlagsHaveChanged: str = "ItemFlagsHaveChanged"; break; +#if QT_DEPRECATED_SINCE(5, 14) case QGraphicsItem::ItemMatrixChange: str = "ItemMatrixChange"; break; +#endif case QGraphicsItem::ItemParentChange: str = "ItemParentChange"; break; diff --git a/src/widgets/graphicsview/qgraphicsitem.h b/src/widgets/graphicsview/qgraphicsitem.h index 7dd4441ae9..d66a4917e5 100644 --- a/src/widgets/graphicsview/qgraphicsitem.h +++ b/src/widgets/graphicsview/qgraphicsitem.h @@ -110,8 +110,10 @@ public: enum GraphicsItemChange { ItemPositionChange, - ItemMatrixChange, - ItemVisibleChange, +#if QT_DEPRECATED_SINCE(5, 14) + ItemMatrixChange Q_DECL_ENUMERATOR_DEPRECATED_X("Use ItemTransformChange instead"), +#endif + ItemVisibleChange = 2, ItemEnabledChange, ItemSelectedChange, ItemParentChange, diff --git a/src/widgets/graphicsview/qgraphicsproxywidget.cpp b/src/widgets/graphicsview/qgraphicsproxywidget.cpp index 2b6712075f..7413a26261 100644 --- a/src/widgets/graphicsview/qgraphicsproxywidget.cpp +++ b/src/widgets/graphicsview/qgraphicsproxywidget.cpp @@ -404,7 +404,7 @@ void QGraphicsProxyWidgetPrivate::_q_removeWidgetSlot() { Q_Q(QGraphicsProxyWidget); if (!widget.isNull()) { - if (QWExtra *extra = widget->d_func()->extra) + if (const auto &extra = widget->d_func()->extra) extra->proxyWidget = 0; } widget = 0; @@ -477,8 +477,8 @@ void QGraphicsProxyWidgetPrivate::updateProxyInputMethodAcceptanceFromWidget() */ void QGraphicsProxyWidgetPrivate::embedSubWindow(QWidget *subWin) { - QWExtra *extra; - if (!((extra = subWin->d_func()->extra) && extra->proxyWidget)) { + const auto &extra = subWin->d_func()->extra; + if (!extra || !extra->proxyWidget) { QGraphicsProxyWidget *subProxy = new QGraphicsProxyWidget(q_func(), subWin->windowFlags()); subProxy->d_func()->setWidget_helper(subWin, false); } @@ -631,7 +631,7 @@ void QGraphicsProxyWidgetPrivate::setWidget_helper(QWidget *newWidget, bool auto if (!newWidget) return; if (!newWidget->isWindow()) { - QWExtra *extra = newWidget->parentWidget()->d_func()->extra; + const auto &extra = newWidget->parentWidget()->d_func()->extra; if (!extra || !extra->proxyWidget) { qWarning("QGraphicsProxyWidget::setWidget: cannot embed widget %p " "which is not a toplevel widget, and is not a child of an embedded widget", newWidget); @@ -641,10 +641,10 @@ void QGraphicsProxyWidgetPrivate::setWidget_helper(QWidget *newWidget, bool auto // Register this proxy within the widget's private. // ### This is a bit backdoorish - QWExtra *extra = newWidget->d_func()->extra; + QWExtra *extra = newWidget->d_func()->extra.get(); if (!extra) { newWidget->d_func()->createExtra(); - extra = newWidget->d_func()->extra; + extra = newWidget->d_func()->extra.get(); } QGraphicsProxyWidget **proxyWidget = &extra->proxyWidget; if (*proxyWidget) { diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp index 313939e638..1208adfd17 100644 --- a/src/widgets/graphicsview/qgraphicsscene.cpp +++ b/src/widgets/graphicsview/qgraphicsscene.cpp @@ -4170,14 +4170,6 @@ void QGraphicsScene::wheelEvent(QGraphicsSceneWheelEvent *wheelEvent) wheelEvent->scenePos(), wheelEvent->widget()); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // On Mac, ignore the event if the first item under the mouse is not the last opened - // popup (or one of its descendant) - if (!d->popupWidgets.isEmpty() && !wheelCandidates.isEmpty() && wheelCandidates.first() != d->popupWidgets.back() && !d->popupWidgets.back()->isAncestorOf(wheelCandidates.first())) { - wheelEvent->accept(); - return; - } -#else // Find the first popup under the mouse (including the popup's descendants) starting from the last. // Remove all popups after the one found, or all or them if no popup is under the mouse. // Then continue with the event. @@ -4187,7 +4179,6 @@ void QGraphicsScene::wheelEvent(QGraphicsSceneWheelEvent *wheelEvent) break; d->removePopup(*iter); } -#endif bool hasSetFocus = false; for (QGraphicsItem *item : wheelCandidates) { @@ -4409,11 +4400,7 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte QGraphicsItem::CacheMode cacheMode = QGraphicsItem::CacheMode(itemd->cacheMode); // Render directly, using no cache. - if (cacheMode == QGraphicsItem::NoCache -#if 0 // Used to be included in Qt4 for Q_WS_X11 - || !X11->use_xrender -#endif - ) { + if (cacheMode == QGraphicsItem::NoCache) { _q_paintItem(static_cast<QGraphicsWidget *>(item), painter, option, widget, true, painterStateProtection); return; } diff --git a/src/widgets/graphicsview/qgraphicsview.cpp b/src/widgets/graphicsview/qgraphicsview.cpp index 7f14218720..57be850829 100644 --- a/src/widgets/graphicsview/qgraphicsview.cpp +++ b/src/widgets/graphicsview/qgraphicsview.cpp @@ -3476,11 +3476,7 @@ void QGraphicsView::paintEvent(QPaintEvent *event) const QTransform viewTransform = painter.worldTransform(); // Draw background - if ((d->cacheMode & CacheBackground) -#if 0 // Used to be included in Qt4 for Q_WS_X11 - && X11->use_xrender -#endif - ) { + if (d->cacheMode & CacheBackground) { // Recreate the background pixmap, and flag the whole background as // exposed. if (d->mustResizeBackgroundPixmap) { @@ -3677,11 +3673,7 @@ void QGraphicsView::scrollContentsBy(int dx, int dy) d->updateLastCenterPoint(); - if ((d->cacheMode & CacheBackground) -#if 0 // Used to be included in Qt4 for Q_WS_X11 - && X11->use_xrender -#endif - ) { + if (d->cacheMode & CacheBackground) { // Below, QPixmap::scroll() works in device pixels, while the delta values // and backgroundPixmapExposed are in device independent pixels. const qreal dpr = d->backgroundPixmap.devicePixelRatio(); diff --git a/src/widgets/graphicsview/qgraphicsview_p.h b/src/widgets/graphicsview/qgraphicsview_p.h index 0428b9ce70..01af61d6ba 100644 --- a/src/widgets/graphicsview/qgraphicsview_p.h +++ b/src/widgets/graphicsview/qgraphicsview_p.h @@ -184,24 +184,10 @@ public: inline void dispatchPendingUpdateRequests() { -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // QWidget::update() works slightly different on the Mac without the raster engine; - // it's not part of our backing store so it needs special threatment. - if (QApplicationPrivate::graphics_system_name != QLatin1String("raster")) { - // At this point either HIViewSetNeedsDisplay (Carbon) or setNeedsDisplay: YES (Cocoa) - // is called, which means there's a pending update request. We want to dispatch it - // now because otherwise graphics view updates would require two - // round-trips in the event loop before the item is painted. - extern void qt_mac_dispatchPendingUpdateRequests(QWidget *); - qt_mac_dispatchPendingUpdateRequests(viewport->window()); - } else -#endif - { - if (qt_widget_private(viewport)->paintOnScreen()) - QCoreApplication::sendPostedEvents(viewport, QEvent::UpdateRequest); - else - QCoreApplication::sendPostedEvents(viewport->window(), QEvent::UpdateRequest); - } + if (qt_widget_private(viewport)->shouldPaintOnScreen()) + QCoreApplication::sendPostedEvents(viewport, QEvent::UpdateRequest); + else + QCoreApplication::sendPostedEvents(viewport->window(), QEvent::UpdateRequest); } void setUpdateClip(QGraphicsItem *); diff --git a/src/widgets/graphicsview/qgraphicswidget.cpp b/src/widgets/graphicsview/qgraphicswidget.cpp index 643f073085..cf041b9817 100644 --- a/src/widgets/graphicsview/qgraphicswidget.cpp +++ b/src/widgets/graphicsview/qgraphicswidget.cpp @@ -716,22 +716,6 @@ void QGraphicsWidget::initStyleOption(QStyleOption *option) const option->state |= QStyle::State_Window; /* ### -#if 0 // Used to be included in Qt4 for Q_WS_MAC - extern bool qt_mac_can_clickThrough(const QGraphicsWidget *w); //qwidget_mac.cpp - if (!(option->state & QStyle::State_Active) && !qt_mac_can_clickThrough(widget)) - option->state &= ~QStyle::State_Enabled; - - switch (QMacStyle::widgetSizePolicy(widget)) { - case QMacStyle::SizeSmall: - option->state |= QStyle::State_Small; - break; - case QMacStyle::SizeMini: - option->state |= QStyle::State_Mini; - break; - default: - ; - } -#endif #ifdef QT_KEYPAD_NAVIGATION if (widget->hasEditFocus()) state |= QStyle::State_HasEditFocus; diff --git a/src/widgets/graphicsview/qgraphicswidget_p.cpp b/src/widgets/graphicsview/qgraphicswidget_p.cpp index fd47f444ea..0156faf8e4 100644 --- a/src/widgets/graphicsview/qgraphicswidget_p.cpp +++ b/src/widgets/graphicsview/qgraphicswidget_p.cpp @@ -691,13 +691,6 @@ void QGraphicsWidgetPrivate::windowFrameHoverMoveEvent(QGraphicsSceneHoverEvent case Qt::TitleBarArea: windowData->buttonRect = q->style()->subControlRect( QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarCloseButton, 0); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // On mac we should hover if we are in the 'area' of the buttons - windowData->buttonRect |= q->style()->subControlRect( - QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMinButton, 0); - windowData->buttonRect |= q->style()->subControlRect( - QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMaxButton, 0); -#endif if (windowData->buttonRect.contains(pos.toPoint())) windowData->buttonMouseOver = true; event->ignore(); diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index d4c83cb82c..089f398e71 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -1966,6 +1966,7 @@ void QAbstractItemView::mouseDoubleClickEvent(QMouseEvent *event) if ((event->button() == Qt::LeftButton) && !edit(persistent, DoubleClicked, event) && !style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, 0, this)) emit activated(persistent); + d->pressedIndex = QModelIndex(); } #if QT_CONFIG(draganddrop) @@ -3727,12 +3728,10 @@ QStyleOptionViewItem QAbstractItemView::viewOptions() const option.state &= ~QStyle::State_MouseOver; option.font = font(); -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC // On mac the focus appearance follows window activation // not widget activation if (!hasFocus()) option.state &= ~QStyle::State_Active; -#endif option.state &= ~QStyle::State_HasFocus; if (d->iconSize.isValid()) { diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp index c4766a74bd..d7bdf6aa4c 100644 --- a/src/widgets/itemviews/qheaderview.cpp +++ b/src/widgets/itemviews/qheaderview.cpp @@ -2570,7 +2570,6 @@ void QHeaderView::mouseMoveEvent(QMouseEvent *e) if (pos < 0 && d->state != QHeaderViewPrivate::SelectSections) return; if (e->buttons() == Qt::NoButton) { -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC // Under Cocoa, when the mouse button is released, may include an extra // simulated mouse moved event. The state of the buttons when this event // is generated is already "no button" and the code below gets executed @@ -2578,7 +2577,6 @@ void QHeaderView::mouseMoveEvent(QMouseEvent *e) // column dragging from working. So this code is disabled under Cocoa. d->state = QHeaderViewPrivate::NoState; d->pressed = -1; -#endif } switch (d->state) { case QHeaderViewPrivate::ResizeSection: { diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp index e706af1a42..c50156bbce 100644 --- a/src/widgets/itemviews/qtableview.cpp +++ b/src/widgets/itemviews/qtableview.cpp @@ -3186,14 +3186,18 @@ void QTableView::sortByColumn(int column) /*! \since 4.2 - Sorts the model by the values in the given \a column in the given \a order. + Sorts the model by the values in the given \a column and \a order. + + \a column may be -1, in which case no sort indicator will be shown + and the model will return to its natural, unsorted order. Note that not + all models support this and may even crash in this case. \sa sortingEnabled */ void QTableView::sortByColumn(int column, Qt::SortOrder order) { Q_D(QTableView); - if (column < 0) + if (column < -1) return; // If sorting is enabled it will emit a signal connected to // _q_sortIndicatorChanged, which then actually sorts diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index 23a530821f..413cc2a9cd 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -1943,6 +1943,7 @@ void QTreeView::mouseDoubleClickEvent(QMouseEvent *event) if (!style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, 0, this)) emit activated(persistent); + d->pressedIndex = QModelIndex(); d->executePostedLayout(); // we need to make sure viewItems is updated if (d->itemsExpandable && d->expandsOnDoubleClick @@ -2173,35 +2174,6 @@ QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie return QModelIndex(); } int vi = -1; -#if 0 /* Used to be included in Qt4 for Q_WS_MAC */ && QT_CONFIG(style_mac) - // Selection behavior is slightly different on the Mac. - if (d->selectionMode == QAbstractItemView::ExtendedSelection - && d->selectionModel - && d->selectionModel->hasSelection()) { - - const bool moveUpDown = (cursorAction == MoveUp || cursorAction == MoveDown); - const bool moveNextPrev = (cursorAction == MoveNext || cursorAction == MovePrevious); - const bool contiguousSelection = moveUpDown && (modifiers & Qt::ShiftModifier); - - // Use the outermost index in the selection as the current index - if (!contiguousSelection && (moveUpDown || moveNextPrev)) { - - // Find outermost index. - const bool useTopIndex = (cursorAction == MoveUp || cursorAction == MovePrevious); - int index = useTopIndex ? INT_MAX : INT_MIN; - const QItemSelection selection = d->selectionModel->selection(); - for (int i = 0; i < selection.count(); ++i) { - const QItemSelectionRange &range = selection.at(i); - int candidate = d->viewIndex(useTopIndex ? range.topLeft() : range.bottomRight()); - if (candidate >= 0) - index = useTopIndex ? qMin(index, candidate) : qMax(index, candidate); - } - - if (index >= 0 && index < INT_MAX) - vi = index; - } - } -#endif if (vi < 0) vi = qMax(0, d->viewIndex(current)); @@ -2619,7 +2591,7 @@ void QTreeView::sortByColumn(int column) /*! \since 4.2 - Sets the model up for sorting by the values in the given \a column and \a order. + Sorts the model by the values in the given \a column and \a order. \a column may be -1, in which case no sort indicator will be shown and the model will return to its natural, unsorted order. Note that not @@ -2630,7 +2602,7 @@ void QTreeView::sortByColumn(int column) void QTreeView::sortByColumn(int column, Qt::SortOrder order) { Q_D(QTreeView); - if (column < 0) + if (column < -1) return; // If sorting is enabled it will emit a signal connected to // _q_sortIndicatorChanged, which then actually sorts diff --git a/src/widgets/kernel/kernel.pri b/src/widgets/kernel/kernel.pri index a4b81335c5..693af7eb80 100644 --- a/src/widgets/kernel/kernel.pri +++ b/src/widgets/kernel/kernel.pri @@ -12,7 +12,7 @@ HEADERS += \ kernel/qactiongroup.h \ kernel/qapplication.h \ kernel/qapplication_p.h \ - kernel/qwidgetbackingstore_p.h \ + kernel/qwidgetrepaintmanager_p.h \ kernel/qboxlayout.h \ kernel/qdesktopwidget.h \ kernel/qgridlayout.h \ @@ -41,7 +41,7 @@ SOURCES += \ kernel/qaction.cpp \ kernel/qactiongroup.cpp \ kernel/qapplication.cpp \ - kernel/qwidgetbackingstore.cpp \ + kernel/qwidgetrepaintmanager.cpp \ kernel/qboxlayout.cpp \ kernel/qgridlayout.cpp \ kernel/qlayout.cpp \ diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 94b14ecb4f..629c696544 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -3388,7 +3388,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) #if QT_CONFIG(graphicsview) // QGraphicsProxyWidget handles its own propagation, // and we must not change QDragManagers currentTarget. - QWExtra *extra = w->window()->d_func()->extra; + const auto &extra = w->window()->d_func()->extra; if (extra && extra->proxyWidget) { res = d->notify_helper(w, dragEvent); break; @@ -3416,7 +3416,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) #if QT_CONFIG(graphicsview) // QGraphicsProxyWidget handles its own propagation, // and we must not change QDragManagers currentTarget. - QWExtra *extra = w->window()->d_func()->extra; + const auto &extra = w->window()->d_func()->extra; bool isProxyWidget = extra && extra->proxyWidget; if (!isProxyWidget) #endif diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index 36c0ba8739..3167bd423f 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -112,16 +112,9 @@ public: virtual bool shouldQuit() override; bool tryCloseAllWindows() override; -#if 0 // Used to be included in Qt4 for Q_WS_X11 -#if QT_CONFIG(settings) - static bool x11_apply_settings(); -#endif - static void reset_instance_pointer(); -#endif static bool autoSipEnabled; static QString desktopStyleKey(); - void createEventDispatcher() override; static void dispatchEnterLeave(QWidget *enter, QWidget *leave, const QPointF &globalPosF); @@ -132,10 +125,7 @@ public: static bool isBlockedByModal(QWidget *widget); static bool modalState(); static bool tryModalHelper(QWidget *widget, QWidget **rettop = nullptr); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - static QWidget *tryModalHelper_sys(QWidget *top); - bool canQuit(); -#endif + #ifdef QT_KEYPAD_NAVIGATION static bool keypadNavigationEnabled() { @@ -146,18 +136,10 @@ public: bool notify_helper(QObject *receiver, QEvent * e); - void init( -#if 0 // Used to be included in Qt4 for Q_WS_X11 - Display *dpy = 0, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0 -#endif - ); + void init(); void initialize(); void process_cmdline(); -#if 0 // Used to be included in Qt4 for Q_WS_X11 - static void x11_initialize_style(); -#endif - static bool inPopupMode(); bool popupActive() override { return inPopupMode(); } void closePopup(QWidget *popup); @@ -212,10 +194,6 @@ public: static void initializeWidgetFontHash(); static void setSystemFont(const QFont &font); -#if 0 // Used to be included in Qt4 for Q_WS_X11 - static void applyX11SpecificCommandLineArguments(QWidget *main_widget); -#endif - static QApplicationPrivate *instance() { return self; } #ifdef QT_KEYPAD_NAVIGATION @@ -223,10 +201,6 @@ public: static Qt::NavigationMode navigationMode; #endif -#if 0 /* Used to be included in Qt4 for Q_WS_MAC */ || 0 /* Used to be included in Qt4 for Q_WS_X11 */ - void _q_alertTimeOut(); - QHash<QWidget *, QTimer *> alertTimerHash; -#endif #ifndef QT_NO_STYLE_STYLESHEET static QString styleSheet; #endif @@ -263,14 +237,6 @@ public: QGestureManager *gestureManager; QWidget *gestureWidget; #endif -#if 0 /* Used to be included in Qt4 for Q_WS_X11 */ || 0 /* Used to be included in Qt4 for Q_WS_WIN */ - QPixmap *move_cursor; - QPixmap *copy_cursor; - QPixmap *link_cursor; -#endif -#if 0 // Used to be included in Qt4 for Q_WS_WIN - QPixmap *ignore_cursor; -#endif static bool updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent); void initializeMultitouch(); @@ -299,14 +265,7 @@ private: static bool isAlien(QWidget *); }; -#if 0 // Used to be included in Qt4 for Q_WS_WIN - extern void qt_win_set_cursor(QWidget *, bool); -#elif 0 // Used to be included in Qt4 for Q_WS_X11 - extern void qt_x11_enforce_cursor(QWidget *, bool); - extern void qt_x11_enforce_cursor(QWidget *); -#else - extern void qt_qpa_set_cursor(QWidget * w, bool force); -#endif +extern void qt_qpa_set_cursor(QWidget * w, bool force); QT_END_NAMESPACE diff --git a/src/widgets/kernel/qdesktopwidget.cpp b/src/widgets/kernel/qdesktopwidget.cpp index ac0cfcf2f5..4fbe6bba3f 100644 --- a/src/widgets/kernel/qdesktopwidget.cpp +++ b/src/widgets/kernel/qdesktopwidget.cpp @@ -111,7 +111,7 @@ const QRect QDesktopWidgetPrivate::availableGeometry(const QWidget *widget) QDesktopScreenWidget *QDesktopWidgetPrivate::widgetForScreen(QScreen *qScreen) const { foreach (QDesktopScreenWidget *widget, screens) { - if (widget->screen() == qScreen) + if (widget->assignedScreen() == qScreen) return widget; } return nullptr; diff --git a/src/widgets/kernel/qdesktopwidget_p.h b/src/widgets/kernel/qdesktopwidget_p.h index 69f87337b3..63949055aa 100644 --- a/src/widgets/kernel/qdesktopwidget_p.h +++ b/src/widgets/kernel/qdesktopwidget_p.h @@ -68,7 +68,7 @@ public: int screenNumber() const; void setScreenGeometry(const QRect &geometry); - QScreen *screen() const { return m_screen.data(); } + QScreen *assignedScreen() const { return m_screen.data(); } QRect screenGeometry() const { return m_geometry; } private: diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp index 1555c2a73a..d9d071a31a 100644 --- a/src/widgets/kernel/qgesturemanager.cpp +++ b/src/widgets/kernel/qgesturemanager.cpp @@ -54,9 +54,6 @@ #ifdef Q_OS_OSX #include "qmacgesturerecognizer_p.h" #endif -#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ && !defined(QT_NO_NATIVE_GESTURES) -#include "qwinnativepangesturerecognizer_win_p.h" -#endif #include "qdebug.h" #include <QtCore/QLoggingCategory> @@ -102,14 +99,7 @@ QGestureManager::QGestureManager(QObject *parent) registerGestureRecognizer(new QSwipeGestureRecognizer); registerGestureRecognizer(new QTapGestureRecognizer); #endif -#if 0 // Used to be included in Qt4 for Q_WS_WIN - #if !defined(QT_NO_NATIVE_GESTURES) - if (QApplicationPrivate::HasTouchSupport) - registerGestureRecognizer(new QWinNativePanGestureRecognizer); - #endif -#else registerGestureRecognizer(new QTapAndHoldGestureRecognizer); -#endif } QGestureManager::~QGestureManager() diff --git a/src/widgets/kernel/qshortcut.cpp b/src/widgets/kernel/qshortcut.cpp index a4ebcdfc84..39b08dbc1e 100644 --- a/src/widgets/kernel/qshortcut.cpp +++ b/src/widgets/kernel/qshortcut.cpp @@ -178,7 +178,7 @@ static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidge // Below is Qt::WindowShortcut context QWidget *tlw = w->window(); #if QT_CONFIG(graphicsview) - if (auto topData = static_cast<QWidgetPrivate *>(QObjectPrivate::get(tlw))->extra) { + if (auto topData = static_cast<QWidgetPrivate *>(QObjectPrivate::get(tlw))->extra.get()) { if (topData->proxyWidget) { bool res = correctGraphicsWidgetContext(context, topData->proxyWidget, active_window); return res; diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp index d030a28356..97a279d65d 100644 --- a/src/widgets/kernel/qtooltip.cpp +++ b/src/widgets/kernel/qtooltip.cpp @@ -36,9 +36,6 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#if 0 // Used to be included in Qt4 for Q_WS_MAC -# include <private/qcore_mac_p.h> -#endif #include <QtWidgets/private/qtwidgetsglobal_p.h> @@ -63,11 +60,6 @@ #include <QtWidgets/private/qlabel_p.h> #include <qtooltip.h> -#if 0 // Used to be included in Qt4 for Q_WS_MAC -# include <private/qcore_mac_p.h> -#include <private/qt_cocoa_helpers_mac_p.h> -#endif - QT_BEGIN_NAMESPACE /*! @@ -317,20 +309,7 @@ void QTipLabel::timerEvent(QTimerEvent *e) || e->timerId() == expireTimer.timerId()){ hideTimer.stop(); expireTimer.stop(); -#if 0 /* Used to be included in Qt4 for Q_WS_MAC */ && QT_CONFIG(effects) - if (QApplication::isEffectEnabled(Qt::UI_FadeTooltip)){ - // Fade out tip on mac (makes it invisible). - // The tip will not be deleted until a new tip is shown. - - // DRSWAT - Cocoa - macWindowFade(qt_mac_window_for(this)); - QTipLabel::instance->fadingOut = true; // will never be false again. - } - else - hideTipImmediately(); -#else hideTipImmediately(); -#endif } } @@ -420,29 +399,11 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w) #endif //QT_NO_STYLE_STYLESHEET -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // When in full screen mode, there is no Dock nor Menu so we can use - // the whole screen for displaying the tooltip. However when not in - // full screen mode we need to save space for the dock, so we use - // availableGeometry instead. - extern bool qt_mac_app_fullscreen; //qapplication_mac.mm - QRect screen; - if(qt_mac_app_fullscreen) - screen = QDesktopWidgetPrivate::screenGeometry(getTipScreen(pos, w)); - else - screen = QDesktopWidgetPrivate::availableGeometry(getTipScreen(pos, w)); -#else QRect screen = QDesktopWidgetPrivate::screenGeometry(getTipScreen(pos, w)); -#endif QPoint p = pos; - p += QPoint(2, -#if 0 // Used to be included in Qt4 for Q_WS_WIN - 21 -#else - 16 -#endif - ); + p += QPoint(2, 16); + if (p.x() + this->width() > screen.x() + screen.width()) p.rx() -= 4 + this->width(); if (p.y() + this->height() > screen.y() + screen.height()) @@ -541,7 +502,7 @@ QT_WARNING_POP QTipLabel::instance->setObjectName(QLatin1String("qtooltip_label")); -#if QT_CONFIG(effects) && !0 /* Used to be included in Qt4 for Q_WS_MAC */ +#if QT_CONFIG(effects) if (QApplication::isEffectEnabled(Qt::UI_FadeTooltip)) qFadeEffect(QTipLabel::instance); else if (QApplication::isEffectEnabled(Qt::UI_AnimateTooltip)) diff --git a/src/widgets/kernel/qwhatsthis.cpp b/src/widgets/kernel/qwhatsthis.cpp index a48eae6628..228ca4d38a 100644 --- a/src/widgets/kernel/qwhatsthis.cpp +++ b/src/widgets/kernel/qwhatsthis.cpp @@ -577,26 +577,12 @@ void QWhatsThisPrivate::say(QWidget * widget, const QString &text, int x, int y) if (text.size() == 0) return; // make a fresh widget, and set it up - QWhatsThat *whatsThat = new QWhatsThat( - text, -#if 0 /* Used to be included in Qt4 for Q_WS_X11 */ && !defined(QT_NO_CURSOR) - QApplication::desktop()->screen(widget ? widget->x11Info().screen() : QCursor::x11Screen()), -#else - 0, -#endif - widget - ); - + QWhatsThat *whatsThat = new QWhatsThat(text, 0, widget); // okay, now to find a suitable location - int scr = (widget ? QDesktopWidgetPrivate::screenNumber(widget) : -#if 0 /* Used to be included in Qt4 for Q_WS_X11 */ && !defined(QT_NO_CURSOR) - QCursor::x11Screen() -#else QDesktopWidgetPrivate::screenNumber(QPoint(x,y)) -#endif ); QRect screen = QDesktopWidgetPrivate::screenGeometry(scr); diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index cdea0a570c..cf5a81c204 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -61,13 +61,6 @@ #ifndef QT_NO_ACCESSIBILITY # include "qaccessible.h" #endif -#if 0 // Used to be included in Qt4 for Q_WS_MAC -# include "qt_mac_p.h" -# include "qt_cocoa_helpers_mac_p.h" -# include "qmainwindow.h" -# include "qtoolbar.h" -# include <private/qmainwindowlayout_p.h> -#endif #include <qpa/qplatformwindow.h> #include "private/qwidgetwindow_p.h" #include "qpainter.h" @@ -90,10 +83,7 @@ #include <private/qgraphicseffect_p.h> #endif #include <qbackingstore.h> -#include <private/qwidgetbackingstore_p.h> -#if 0 // Used to be included in Qt4 for Q_WS_MAC -# include <private/qpaintengine_mac_p.h> -#endif +#include <private/qwidgetrepaintmanager_p.h> #include <private/qpaintengine_raster_p.h> #include "qwidget_p.h" @@ -121,15 +111,15 @@ #include <QtPlatformHeaders/qxcbwindowfunctions.h> +#include <private/qmemory_p.h> + // widget/widget data creation count //#define QWIDGET_EXTRA_DEBUG //#define ALIEN_DEBUG QT_BEGIN_NAMESPACE -#if 0 // Used to be included in Qt4 for Q_WS_MAC -bool qt_mac_clearDirtyOnWidgetInsideDrawWidget = false; -#endif +Q_LOGGING_CATEGORY(lcWidgetPainting, "qt.widgets.painting", QtWarningMsg); static inline bool qRectIntersects(const QRect &r1, const QRect &r2) { @@ -137,101 +127,11 @@ static inline bool qRectIntersects(const QRect &r1, const QRect &r2) qMax(r1.top(), r2.top()) <= qMin(r1.bottom(), r2.bottom())); } -#if 0 // Used to be included in Qt4 for Q_WS_MAC -# define QT_NO_PAINT_DEBUG -#endif - extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp -/*! - \internal - \class QWidgetBackingStoreTracker - \brief Class which allows tracking of which widgets are using a given backing store - - QWidgetBackingStoreTracker is a thin wrapper around a QWidgetBackingStore pointer, - which maintains a list of the QWidgets which are currently using the backing - store. This list is modified via the registerWidget and unregisterWidget functions. - */ - -QWidgetBackingStoreTracker::QWidgetBackingStoreTracker() - : m_ptr(0) -{ - -} - -QWidgetBackingStoreTracker::~QWidgetBackingStoreTracker() -{ - delete m_ptr; -} - -/*! - \internal - Destroy the contained QWidgetBackingStore, if not null, and clear the list of - widgets using the backing store, then create a new QWidgetBackingStore, providing - the QWidget. - */ -void QWidgetBackingStoreTracker::create(QWidget *widget) -{ - destroy(); - m_ptr = new QWidgetBackingStore(widget); -} - -/*! - \internal - Destroy the contained QWidgetBackingStore, if not null, and clear the list of - widgets using the backing store. - */ -void QWidgetBackingStoreTracker::destroy() -{ - delete m_ptr; - m_ptr = 0; - m_widgets.clear(); -} - -/*! - \internal - Add the widget to the list of widgets currently using the backing store. - If the widget was already in the list, this function is a no-op. - */ -void QWidgetBackingStoreTracker::registerWidget(QWidget *w) -{ - Q_ASSERT(m_ptr); - Q_ASSERT(w->internalWinId()); - Q_ASSERT(qt_widget_private(w)->maybeBackingStore() == m_ptr); - m_widgets.insert(w); -} - -/*! - \internal - Remove the widget from the list of widgets currently using the backing store. - If the widget was in the list, and removing it causes the list to be empty, - the backing store is deleted. - If the widget was not in the list, this function is a no-op. - */ -void QWidgetBackingStoreTracker::unregisterWidget(QWidget *w) -{ - if (m_widgets.remove(w) && m_widgets.isEmpty()) { - delete m_ptr; - m_ptr = 0; - } -} - -/*! - \internal - Recursively remove widget and all of its descendents. - */ -void QWidgetBackingStoreTracker::unregisterWidgetSubtree(QWidget *widget) -{ - unregisterWidget(widget); - foreach (QObject *child, widget->children()) - if (QWidget *childWidget = qobject_cast<QWidget *>(child)) - unregisterWidgetSubtree(childWidget); -} - QWidgetPrivate::QWidgetPrivate(int version) : QObjectPrivate(version) - , extra(0) , focus_next(0) , focus_prev(0) , focus_child(0) @@ -285,17 +185,6 @@ QWidgetPrivate::QWidgetPrivate(int version) #if defined(Q_OS_WIN) , noPaintOnScreen(0) #endif -#if 0 // Used to be included in Qt4 for Q_WS_X11 - , picture(0) -#elif 0 // Used to be included in Qt4 for Q_WS_WIN - #ifndef QT_NO_GESTURES - , nativeGesturePanEnabled(0) - #endif -#elif 0 // Used to be included in Qt4 for Q_WS_MAC - , needWindowChange(0) - , window_event(0) - , qd_hd(0) -#endif { if (Q_UNLIKELY(!qApp)) { qFatal("QWidget: Must construct a QApplication before a QWidget"); @@ -314,16 +203,7 @@ QWidgetPrivate::QWidgetPrivate(int version) isWidget = true; memset(high_attributes, 0, sizeof(high_attributes)); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - drawRectOriginalAdded = false; - originalDrawMethod = true; - changeMethods = false; - isInUnifiedToolbar = false; - unifiedSurface = 0; - toolbar_ancestor = 0; - flushRequested = false; - touchEventsEnabled = false; -#endif + #ifdef QWIDGET_EXTRA_DEBUG static int count = 0; qDebug() << "widgets" << ++count; @@ -944,22 +824,6 @@ QWidgetSet *QWidgetPrivate::allWidgets = 0; // widgets with no wid /***************************************************************************** - QWidget utility functions - *****************************************************************************/ - -QRegion qt_dirtyRegion(QWidget *widget) -{ - if (!widget) - return QRegion(); - - QWidgetBackingStore *bs = qt_widget_private(widget)->maybeBackingStore(); - if (!bs) - return QRegion(); - - return bs->dirtyRegion(widget); -} - -/***************************************************************************** QWidget member functions *****************************************************************************/ @@ -1084,17 +948,12 @@ void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w) // Only enable this on non-Mac platforms. Since the old way of doing this would // interpret WindowSystemMenuHint as a close button and we can't change that behavior // we can't just add this in. -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC if ((flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint)) # ifdef Q_OS_WIN && type != Qt::Dialog // QTBUG-2027, allow for menu-less dialogs. # endif ) { flags |= Qt::WindowSystemMenuHint; -#else - if (flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint - | Qt::WindowSystemMenuHint)) { -#endif flags |= Qt::WindowTitleHint; flags &= ~Qt::FramelessWindowHint; } @@ -1149,13 +1008,6 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) } #endif -#if 0 // Used to be included in Qt4 for Q_WS_X11 - if (desktopWidget) { - // make sure the widget is created on the same screen as the - // programmer specified desktop widget - xinfo = desktopWidget->d_func()->xinfo; - } -#endif if (targetScreen >= 0) { topData()->initialScreenIndex = targetScreen; if (QWindow *window = q->windowHandle()) @@ -1183,9 +1035,6 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) mustHaveWindowHandle = 1; q->setAttribute(Qt::WA_NativeWindow); } -//#if 0 // Used to be included in Qt4 for Q_WS_MAC -// q->setAttribute(Qt::WA_NativeWindow); -//#endif q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute() adjustQuitOnCloseAttribute(); @@ -1209,9 +1058,6 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) setOpaque(q->isWindow() && background.style() != Qt::NoBrush && background.isOpaque()); } data.fnt = QFont(data.fnt, q); -#if 0 // Used to be included in Qt4 for Q_WS_X11 - data.fnt.x11SetScreen(xinfo.screen()); -#endif q->setAttribute(Qt::WA_PendingMoveEvent); q->setAttribute(Qt::WA_PendingResizeEvent); @@ -1227,20 +1073,8 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) QCoreApplication::postEvent(q, new QEvent(QEvent::PolishRequest)); extraPaintEngine = 0; - -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // If we add a child to the unified toolbar, we have to redirect the painting. - if (parentWidget && parentWidget->d_func() && parentWidget->d_func()->isInUnifiedToolbar) { - if (parentWidget->d_func()->unifiedSurface) { - QWidget *toolbar = parentWidget->d_func()->toolbar_ancestor; - parentWidget->d_func()->unifiedSurface->recursiveRedirect(toolbar, toolbar, toolbar->d_func()->toolbar_offset); - } - } -#endif } - - void QWidgetPrivate::createRecursively() { Q_Q(QWidget); @@ -1347,25 +1181,14 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow) << "Alien?" << !testAttribute(Qt::WA_NativeWindow); #endif -#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ && QT_CONFIG(draganddrop) - // Unregister the dropsite (if already registered) before we - // re-create the widget with a native window. - if (testAttribute(Qt::WA_WState_Created) && !internalWinId() && testAttribute(Qt::WA_NativeWindow) - && d->extra && d->extra->dropTarget) { - d->registerDropSite(false); - } -#endif - d->updateIsOpaque(); setAttribute(Qt::WA_WState_Created); // set created flag d->create(); - // a real toplevel window needs a backing store - if (isWindow() && windowType() != Qt::Desktop) { - d->topData()->backingStoreTracker.destroy(); - d->topData()->backingStoreTracker.create(this); - } + // A real toplevel window needs a paint manager + if (isWindow() && windowType() != Qt::Desktop) + d->topData()->repaintManager.reset(new QWidgetRepaintManager(this)); d->setModal_sys(); @@ -1638,7 +1461,7 @@ QWidget::~QWidget() while (w->d_func()->extra && w->d_func()->extra->focus_proxy) w = w->d_func()->extra->focus_proxy; QWidget *window = w->window(); - QWExtra *e = window ? window->d_func()->extra : 0; + QWExtra *e = window ? window->d_func()->extra.get() : nullptr ; if (!e || !e->proxyWidget || (w->parentWidget() && w->parentWidget()->d_func()->focus_child == this)) #endif clearFocus(); @@ -1659,21 +1482,14 @@ QWidget::~QWidget() // and if that also doesn't work, then give up } } - } - -#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ || 0 /* Used to be included in Qt4 for Q_WS_X11 */|| 0 /* Used to be included in Qt4 for Q_WS_MAC */ - else if (!internalWinId() && isVisible()) { - qApp->d_func()->sendSyntheticEnterLeave(this); - } -#endif - else if (isVisible()) { + } else if (isVisible()) { qApp->d_func()->sendSyntheticEnterLeave(this); } - if (QWidgetBackingStore *bs = d->maybeBackingStore()) { - bs->removeDirtyWidget(this); + if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) { + repaintManager->removeDirtyWidget(this); if (testAttribute(Qt::WA_StaticContents)) - bs->removeStaticWidget(this); + repaintManager->removeStaticWidget(this); } delete d->needsFlush; @@ -1710,15 +1526,6 @@ QWidget::~QWidget() d->blockSig = blocked; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // QCocoaView holds a pointer back to this widget. Clear it now - // to make sure it's not followed later on. The lifetime of the - // QCocoaView might exceed the lifetime of this widget in cases - // where Cocoa itself holds references to it. - extern void qt_mac_clearCocoaViewQWidgetPointers(QWidget *); - qt_mac_clearCocoaViewQWidgetPointers(this); -#endif - if (!d->children.isEmpty()) d->deleteChildren(); @@ -1765,9 +1572,6 @@ void QWidgetPrivate::setWinId(WId id) // set widget identifier const WId oldWinId = data.winid; data.winid = id; -#if 0 // Used to be included in Qt4 for Q_WS_X11 - hd = id; // X11: hd == ident -#endif if (mapper && id && !userDesktopWidget) { mapper->insert(data.winid, q); } @@ -1783,8 +1587,8 @@ void QWidgetPrivate::createTLExtra() if (!extra) createExtra(); if (!extra->topextra) { - QTLWExtra* x = extra->topextra = new QTLWExtra; - x->icon = 0; + extra->topextra = qt_make_unique<QTLWExtra>(); + QTLWExtra* x = extra->topextra.get(); x->backingStore = 0; x->sharedPainter = 0; x->incw = x->inch = 0; @@ -1798,11 +1602,8 @@ void QWidgetPrivate::createTLExtra() x->inTopLevelResize = false; x->embedded = 0; x->window = 0; - x->shareContext = 0; x->initialScreenIndex = -1; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - x->wasMaximized = false; -#endif + #ifdef QWIDGET_EXTRA_DEBUG static int count = 0; qDebug() << "tlextra" << ++count; @@ -1818,15 +1619,11 @@ void QWidgetPrivate::createTLExtra() void QWidgetPrivate::createExtra() { if (!extra) { // if not exists - extra = new QWExtra; + extra = qt_make_unique<QWExtra>(); extra->glContext = 0; - extra->topextra = 0; #if QT_CONFIG(graphicsview) extra->proxyWidget = 0; #endif -#ifndef QT_NO_CURSOR - extra->curs = 0; -#endif extra->minw = 0; extra->minh = 0; extra->maxw = QWIDGETSIZE_MAX; @@ -1860,9 +1657,6 @@ void QWidgetPrivate::createSysExtra() void QWidgetPrivate::deleteExtra() { if (extra) { // if exists -#ifndef QT_NO_CURSOR - delete extra->curs; -#endif deleteSysExtra(); #ifndef QT_NO_STYLE_STYLESHEET // dereference the stylesheet style @@ -1872,12 +1666,9 @@ void QWidgetPrivate::deleteExtra() if (extra->topextra) { deleteTLSysExtra(); // extra->topextra->backingStore destroyed in QWidgetPrivate::deleteTLSysExtra() - delete extra->topextra->icon; - delete extra->topextra; } - delete extra; // extra->xic destroyed in QWidget::destroy() - extra = 0; + extra.reset(); } } @@ -1899,13 +1690,11 @@ void QWidgetPrivate::deleteTLSysExtra() //the qplatformbackingstore may hold a reference to the window, so the backingstore //needs to be deleted first. - extra->topextra->backingStoreTracker.destroy(); + extra->topextra->repaintManager.reset(nullptr); deleteBackingStore(this); #ifndef QT_NO_OPENGL - qDeleteAll(extra->topextra->widgetTextures); extra->topextra->widgetTextures.clear(); - delete extra->topextra->shareContext; - extra->topextra->shareContext = 0; + extra->topextra->shareContext.reset(); #endif //the toplevel might have a context with a "qglcontext associated with it. We need to @@ -1950,7 +1739,7 @@ QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst const QRect siblingRect = sibling->d_func()->effectiveRectFor(sibling->data->crect); if (qRectIntersects(siblingRect, r)) { - const QWExtra *siblingExtra = sibling->d_func()->extra; + const auto &siblingExtra = sibling->d_func()->extra; if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect && !siblingExtra->mask.translated(sibling->data->crect.topLeft()).intersects(r)) { continue; @@ -1969,23 +1758,59 @@ QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst void QWidgetPrivate::syncBackingStore() { - if (paintOnScreen()) { - repaint_sys(dirty); + if (shouldPaintOnScreen()) { + paintOnScreen(dirty); dirty = QRegion(); - } else if (QWidgetBackingStore *bs = maybeBackingStore()) { - bs->sync(); + } else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) { + repaintManager->sync(); } } void QWidgetPrivate::syncBackingStore(const QRegion ®ion) { - if (paintOnScreen()) - repaint_sys(region); - else if (QWidgetBackingStore *bs = maybeBackingStore()) { - bs->sync(q_func(), region); + if (shouldPaintOnScreen()) + paintOnScreen(region); + else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) { + repaintManager->sync(q_func(), region); } } +void QWidgetPrivate::paintOnScreen(const QRegion &rgn) +{ + if (data.in_destructor) + return; + + if (shouldDiscardSyncRequest()) + return; + + Q_Q(QWidget); + if (q->testAttribute(Qt::WA_StaticContents)) { + if (!extra) + createExtra(); + extra->staticContentsSize = data.crect.size(); + } + + QPaintEngine *engine = q->paintEngine(); + + // QGLWidget does not support partial updates if: + // 1) The context is double buffered + // 2) The context is single buffered and auto-fill background is enabled. + const bool noPartialUpdateSupport = (engine && (engine->type() == QPaintEngine::OpenGL + || engine->type() == QPaintEngine::OpenGL2)) + && (usesDoubleBufferedGLContext || q->autoFillBackground()); + QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn); + + toBePainted &= clipRect(); + clipToEffectiveMask(toBePainted); + if (toBePainted.isEmpty()) + return; // Nothing to repaint. + + drawWidget(q, toBePainted, QPoint(), QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen, 0); + + if (Q_UNLIKELY(q->paintingActive())) + qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent"); +} + void QWidgetPrivate::setUpdatesEnabled_helper(bool enable) { Q_Q(QWidget); @@ -2210,11 +2035,6 @@ void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirt if (disableSubtractOpaqueSiblings || q->isWindow()) return; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (q->d_func()->isInUnifiedToolbar) - return; -#endif - QRect clipBoundingRect; bool dirtyClipBoundingRect = true; @@ -2318,7 +2138,7 @@ void QWidgetPrivate::clipToEffectiveMask(QRegion ®ion) const } } -bool QWidgetPrivate::paintOnScreen() const +bool QWidgetPrivate::shouldPaintOnScreen() const { #if defined(QT_NO_BACKINGSTORE) return true; @@ -2347,13 +2167,6 @@ void QWidgetPrivate::updateIsOpaque() #endif // QT_CONFIG(graphicseffect) Q_Q(QWidget); -#if 0 // Used to be included in Qt4 for Q_WS_X11 - if (q->testAttribute(Qt::WA_X11OpenGLOverlay)) { - setOpaque(false); - return; - } -#endif - if (q->testAttribute(Qt::WA_OpaquePaintEvent) || q->testAttribute(Qt::WA_PaintOnScreen)) { setOpaque(true); return; @@ -2406,20 +2219,9 @@ static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrus Q_ASSERT(painter); if (brush.style() == Qt::TexturePattern) { -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // Optimize pattern filling on mac by using HITheme directly - // when filling with the standard widget background. - // Defined in qmacstyle_mac.cpp - extern void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush); - qt_mac_fill_background(painter, rgn, brush); -#else - { - const QRect rect(rgn.boundingRect()); - painter->setClipRegion(rgn); - painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft()); - } -#endif - + const QRect rect(rgn.boundingRect()); + painter->setClipRegion(rgn); + painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft()); } else if (brush.gradient() && (brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode || brush.gradient()->coordinateMode() == QGradient::ObjectMode)) { @@ -2450,7 +2252,7 @@ bool QWidgetPrivate::updateBrushOrigin(QPainter *painter, const QBrush &brush) c return true; } -void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, int flags) const +void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, DrawWidgetFlags flags) const { Q_Q(const QWidget); @@ -2493,11 +2295,7 @@ void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, int visible widgets. */ -#if 0 // Used to be included in Qt4 for Q_WS_MAC - extern QPointer<QWidget> qt_button_down; -#else - extern QWidget *qt_button_down; -#endif +extern QWidget *qt_button_down; void QWidgetPrivate::deactivateWidgetCleanup() { @@ -2683,7 +2481,7 @@ WId QWidget::effectiveWinId() const \since 5.0 - \sa winId() + \sa winId(), screen() */ QWindow *QWidget::windowHandle() const { @@ -2691,6 +2489,29 @@ QWindow *QWidget::windowHandle() const return d->windowHandle(); } +/*! + Returns the screen the widget is on. + + \since 5.14 + + \sa windowHandle() +*/ +QScreen *QWidget::screen() const +{ + Q_D(const QWidget); + if (auto associatedScreen = d->associatedScreen()) + return associatedScreen; + if (auto topLevel = window()) { + if (auto topData = qt_widget_private(topLevel)->topData()) { + if (auto initialScreen = QGuiApplicationPrivate::screen_list.value(topData->initialScreenIndex)) + return initialScreen; + } + if (auto screenByPos = QGuiApplication::screenAt(topLevel->geometry().center())) + return screenByPos; + } + return QGuiApplication::primaryScreen(); +} + #ifndef QT_NO_STYLE_STYLESHEET /*! @@ -3166,15 +2987,6 @@ bool QWidget::isFullScreen() const */ void QWidget::showFullScreen() { -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // If the unified toolbar is enabled, we have to disable it before going fullscreen. - QMainWindow *mainWindow = qobject_cast<QMainWindow*>(this); - if (mainWindow && mainWindow->unifiedTitleAndToolBarOnMac()) { - mainWindow->setUnifiedTitleAndToolBarOnMac(false); - QMainWindowLayout *mainLayout = qobject_cast<QMainWindowLayout*>(mainWindow->layout()); - mainLayout->activateUnifiedToolbarAfterFullScreen = true; - } -#endif ensurePolished(); setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized)) @@ -3202,18 +3014,6 @@ void QWidget::showMaximized() setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen)) | Qt::WindowMaximized); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // If the unified toolbar was enabled before going fullscreen, we have to enable it back. - QMainWindow *mainWindow = qobject_cast<QMainWindow*>(this); - if (mainWindow) - { - QMainWindowLayout *mainLayout = qobject_cast<QMainWindowLayout*>(mainWindow->layout()); - if (mainLayout->activateUnifiedToolbarAfterFullScreen) { - mainWindow->setUnifiedTitleAndToolBarOnMac(true); - mainLayout->activateUnifiedToolbarAfterFullScreen = false; - } - } -#endif setVisible(true); } @@ -3231,18 +3031,6 @@ void QWidget::showNormal() setWindowState(windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // If the unified toolbar was enabled before going fullscreen, we have to enable it back. - QMainWindow *mainWindow = qobject_cast<QMainWindow*>(this); - if (mainWindow) - { - QMainWindowLayout *mainLayout = qobject_cast<QMainWindowLayout*>(mainWindow->layout()); - if (mainLayout->activateUnifiedToolbarAfterFullScreen) { - mainWindow->setUnifiedTitleAndToolBarOnMac(true); - mainLayout->activateUnifiedToolbarAfterFullScreen = false; - } - } -#endif setVisible(true); } @@ -3458,13 +3246,6 @@ void QWidgetPrivate::setEnabled_helper(bool enable) if (w && !w->testAttribute(attribute)) w->d_func()->setEnabled_helper(enable); } -#if 0 // Used to be included in Qt4 for Q_WS_X11 - if (q->testAttribute(Qt::WA_SetCursor) || q->isWindow()) { - // enforce the windows behavior of clearing the cursor on - // disabled widgets - qt_x11_enforce_cursor(q); - } -#endif #ifndef QT_NO_CURSOR if (q->testAttribute(Qt::WA_SetCursor) || q->isWindow()) { // enforce the windows behavior of clearing the cursor on @@ -3472,9 +3253,6 @@ void QWidgetPrivate::setEnabled_helper(bool enable) qt_qpa_set_cursor(q, false); } #endif -#if 0 // Used to be included in Qt4 for Q_WS_MAC - setEnabled_helper_sys(enable); -#endif #ifndef QT_NO_IM if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) { QWidget *focusWidget = effectiveFocusWidget(); @@ -3955,7 +3733,7 @@ QSize QWidget::sizeIncrement() const QSize QWidget::baseSize() const { Q_D(const QWidget); - return (d->extra != 0 && d->extra->topextra != 0) + return (d->extra && d->extra->topextra) ? QSize(d->extra->topextra->basew, d->extra->topextra->baseh) : QSize(0, 0); } @@ -4569,13 +4347,7 @@ const QPalette &QWidget::palette() const ) { data->pal.setCurrentColorGroup(QPalette::Active); } else { -#if 0 // Used to be included in Qt4 for Q_WS_MAC - extern bool qt_mac_can_clickThrough(const QWidget *); //qwidget_mac.cpp - if (qt_mac_can_clickThrough(this)) - data->pal.setCurrentColorGroup(QPalette::Active); - else -#endif - data->pal.setCurrentColorGroup(QPalette::Inactive); + data->pal.setCurrentColorGroup(QPalette::Inactive); } return data->pal; } @@ -4838,10 +4610,7 @@ void QWidgetPrivate::updateFont(const QFont &font) #endif data.fnt = QFont(font, q); -#if 0 // Used to be included in Qt4 for Q_WS_X11 - // make sure the font set on this widget is associated with the correct screen - data.fnt.x11SetScreen(xinfo.screen()); -#endif + // Combine new mask with natural mask and propagate to children. #if QT_CONFIG(graphicsview) if (!q->parentWidget() && extra && extra->proxyWidget) { @@ -5015,16 +4784,11 @@ QCursor QWidget::cursor() const void QWidget::setCursor(const QCursor &cursor) { Q_D(QWidget); -// On Mac we must set the cursor even if it is the ArrowCursor. -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC if (cursor.shape() != Qt::ArrowCursor || (d->extra && d->extra->curs)) -#endif { d->createExtra(); - QCursor *newCursor = new QCursor(cursor); - delete d->extra->curs; - d->extra->curs = newCursor; + d->extra->curs = qt_make_unique<QCursor>(cursor); } setAttribute(Qt::WA_SetCursor); d->setCursor_sys(cursor); @@ -5043,10 +4807,8 @@ void QWidgetPrivate::setCursor_sys(const QCursor &cursor) void QWidget::unsetCursor() { Q_D(QWidget); - if (d->extra) { - delete d->extra->curs; - d->extra->curs = 0; - } + if (d->extra) + d->extra->curs.reset(); if (!isWindow()) setAttribute(Qt::WA_SetCursor, false); d->unsetCursor_sys(); @@ -5450,11 +5212,9 @@ void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset Q_ASSERT(!toBePainted.isEmpty()); Q_Q(QWidget); -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC const QTransform originalTransform = painter->worldTransform(); const bool useDeviceCoordinates = originalTransform.isScaling(); if (!useDeviceCoordinates) { -#endif // Render via a pixmap. const QRect rect = toBePainted.boundingRect(); const QSize size = rect.size(); @@ -5477,7 +5237,6 @@ void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset if (restore) painter->setRenderHints(QPainter::SmoothPixmapTransform, false); -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC } else { // Render via a pixmap in device coordinates (to avoid pixmap scaling). QTransform transform = originalTransform; @@ -5508,26 +5267,29 @@ void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset painter->drawPixmap(deviceRect.topLeft(), pixmap); painter->setTransform(originalTransform); } -#endif } -void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, int flags, - QPainter *sharedPainter, QWidgetBackingStore *backingStore) +void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags, + QPainter *sharedPainter, QWidgetRepaintManager *repaintManager) { if (rgn.isEmpty()) return; + Q_Q(QWidget); + + qCInfo(lcWidgetPainting) << "Drawing" << rgn << "of" << q << "at" << offset + << "into paint device" << pdev << "with" << flags; + const bool asRoot = flags & DrawAsRoot; - bool onScreen = paintOnScreen(); + bool onScreen = shouldPaintOnScreen(); - Q_Q(QWidget); #if QT_CONFIG(graphicseffect) if (graphicsEffect && graphicsEffect->isEnabled()) { QGraphicsEffectSource *source = graphicsEffect->d_func()->source; QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *> (source->d_func()); if (!sourced->context) { - QWidgetPaintContext context(pdev, rgn, offset, flags, sharedPainter, backingStore); + QWidgetPaintContext context(pdev, rgn, offset, flags, sharedPainter, repaintManager); sourced->context = &context; if (!sharedPainter) { setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), rgn.translated(offset)); @@ -5551,10 +5313,8 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP } sourced->context = 0; - // Native widgets need to be marked dirty on screen so painting will be done in correct context - // Same check as in the no effects case below. - if (backingStore && !onScreen && !asRoot && (q->internalWinId() || !q->nativeParentWidget()->isWindow())) - backingStore->markDirtyOnScreen(rgn, q, offset); + if (repaintManager) + repaintManager->markNeedsFlush(q, rgn, offset); return; } @@ -5581,22 +5341,10 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP q->setAttribute(Qt::WA_WState_InPaintEvent); //clip away the new area -#ifndef QT_NO_PAINT_DEBUG - bool flushed = QWidgetBackingStore::flushPaint(q, toBePainted); -#endif QPaintEngine *paintEngine = pdev->paintEngine(); if (paintEngine) { setRedirected(pdev, -offset); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // (Alien support) Special case for Mac when redirecting: If the paint device - // is of the Widget type we need to set WA_WState_InPaintEvent since painting - // outside the paint event is not supported on QWidgets. The attributeis - // restored further down. - if (pdev->devType() == QInternal::Widget) - static_cast<QWidget *>(pdev)->setAttribute(Qt::WA_WState_InPaintEvent); - -#endif if (sharedPainter) setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), toBePainted); else @@ -5609,7 +5357,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP beginBackingStorePainting(); #endif QPainter p(q); - paintBackground(&p, toBePainted, (asRoot || onScreen) ? flags | DrawAsRoot : 0); + paintBackground(&p, toBePainted, (asRoot || onScreen) ? (flags | DrawAsRoot) : DrawWidgetFlags()); #ifndef QT_NO_OPENGL endBackingStorePainting(); #endif @@ -5644,11 +5392,11 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP // This widget renders into a texture which is composed later. We just need to // punch a hole in the backingstore, so the texture will be visible. beginBackingStorePainting(); - if (!q->testAttribute(Qt::WA_AlwaysStackOnTop) && backingStore) { + if (!q->testAttribute(Qt::WA_AlwaysStackOnTop) && repaintManager) { QPainter p(q); p.setCompositionMode(QPainter::CompositionMode_Source); p.fillRect(q->rect(), Qt::transparent); - } else if (!backingStore) { + } else if (!repaintManager) { // We are not drawing to a backingstore: fall back to QImage QImage img = grabFramebuffer(); // grabFramebuffer() always sets the format to RGB32 @@ -5672,16 +5420,11 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP sendPaintEvent(toBePainted); } - // Native widgets need to be marked dirty on screen so painting will be done in correct context - if (backingStore && !onScreen && !asRoot && (q->internalWinId() || (q->nativeParentWidget() && !q->nativeParentWidget()->isWindow()))) - backingStore->markDirtyOnScreen(toBePainted, q, offset); + if (repaintManager) + repaintManager->markNeedsFlush(q, toBePainted, offset); //restore if (paintEngine) { -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (pdev->devType() == QInternal::Widget) - static_cast<QWidget *>(pdev)->setAttribute(Qt::WA_WState_InPaintEvent, false); -#endif restoreRedirected(); if (!sharedPainter) paintEngine->d_func()->systemRect = QRect(); @@ -5697,11 +5440,6 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP if (paintEngine && paintEngine->autoDestruct()) { delete paintEngine; } - -#ifndef QT_NO_PAINT_DEBUG - if (flushed) - QWidgetBackingStore::unflushPaint(q, toBePainted); -#endif } else if (q->isWindow()) { QPaintEngine *engine = pdev->paintEngine(); if (engine) { @@ -5720,8 +5458,8 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP } if (recursive && !children.isEmpty()) { - paintSiblingsRecursive(pdev, children, children.size() - 1, rgn, offset, flags & ~DrawAsRoot - , sharedPainter, backingStore); + paintSiblingsRecursive(pdev, children, children.size() - 1, rgn, offset, flags & ~DrawAsRoot, + sharedPainter, repaintManager); } } @@ -5752,7 +5490,6 @@ void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset, if (paintRegion.isEmpty()) return; -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC QPainter *oldSharedPainter = inRenderWithPainter ? sharedPainter() : 0; // Use the target's shared painter if set (typically set when doing @@ -5765,7 +5502,6 @@ void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset, setSharedPainter(targetPainter); } } -#endif // Use the target's redirected device if set and adjust offset and paint // region accordingly. This is typically the case when people call render @@ -5792,7 +5528,7 @@ void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset, } // Set backingstore flags. - int flags = DrawPaintOnScreen | DrawInvisible; + DrawWidgetFlags flags = DrawPaintOnScreen | DrawInvisible; if (renderFlags & QWidget::DrawWindowBackground) flags |= DrawAsRoot; @@ -5812,8 +5548,8 @@ void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset, } void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn, - const QPoint &offset, int flags - , QPainter *sharedPainter, QWidgetBackingStore *backingStore) + const QPoint &offset, DrawWidgetFlags flags + , QPainter *sharedPainter, QWidgetRepaintManager *repaintManager) { QWidget *w = 0; QRect boundingRect; @@ -5848,8 +5584,8 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis QRegion wr(rgn); if (wd->isOpaque) wr -= hasMask ? wd->extra->mask.translated(widgetPos) : w->data->crect; - paintSiblingsRecursive(pdev, siblings, --index, wr, offset, flags - , sharedPainter, backingStore); + paintSiblingsRecursive(pdev, siblings, --index, wr, offset, flags, + sharedPainter, repaintManager); } if (w->updatesEnabled() @@ -5862,7 +5598,7 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis wRegion.translate(-widgetPos); if (hasMask) wRegion &= wd->extra->mask; - wd->drawWidget(pdev, wRegion, offset + widgetPos, flags, sharedPainter, backingStore); + wd->drawWidget(pdev, wRegion, offset + widgetPos, flags, sharedPainter, repaintManager); } } @@ -5897,7 +5633,7 @@ void QWidgetEffectSourcePrivate::draw(QPainter *painter) toBePainted &= wd->extra->mask; wd->drawWidget(context->pdev, toBePainted, context->offset, context->flags, - context->sharedPainter, context->backingStore); + context->sharedPainter, context->repaintManager); } QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset, @@ -5959,7 +5695,7 @@ QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint * QGraphicsProxyWidget *QWidgetPrivate::nearestGraphicsProxyWidget(const QWidget *origin) { if (origin) { - QWExtra *extra = origin->d_func()->extra; + const auto &extra = origin->d_func()->extra; if (extra && extra->proxyWidget) return extra->proxyWidget; return nearestGraphicsProxyWidget(origin->parentWidget()); @@ -6266,8 +6002,9 @@ void QWidget::setWindowIcon(const QIcon &icon) d->createTLExtra(); if (!d->extra->topextra->icon) - d->extra->topextra->icon = new QIcon(); - *d->extra->topextra->icon = icon; + d->extra->topextra->icon = qt_make_unique<QIcon>(icon); + else + *d->extra->topextra->icon = icon; d->setWindowIcon_sys(); d->setWindowIcon_helper(); @@ -6481,7 +6218,7 @@ void QWidget::setFocusProxy(QWidget * w) QWidget *QWidget::focusProxy() const { Q_D(const QWidget); - return d->extra ? (QWidget *)d->extra->focus_proxy : nullptr; + return d->extra ? d->extra->focus_proxy.data() : nullptr; } @@ -6504,7 +6241,7 @@ bool QWidget::hasFocus() const w = w->d_func()->extra->focus_proxy; #if QT_CONFIG(graphicsview) if (QWidget *window = w->window()) { - QWExtra *e = window->d_func()->extra; + const auto &e = window->d_func()->extra; if (e && e->proxyWidget && e->proxyWidget->hasFocus() && window->focusWidget() == w) return true; } @@ -6556,16 +6293,12 @@ void QWidget::setFocus(Qt::FocusReason reason) if (!f) f = this; - if (QApplication::focusWidget() == f -#if 0 // Used to be included in Qt4 for Q_WS_WIN - && GetFocus() == f->internalWinId() -#endif - ) + if (QApplication::focusWidget() == f) return; #if QT_CONFIG(graphicsview) QWidget *previousProxyFocus = 0; - if (QWExtra *topData = window()->d_func()->extra) { + if (const auto &topData = window()->d_func()->extra) { if (topData->proxyWidget && topData->proxyWidget->hasFocus()) { previousProxyFocus = topData->proxyWidget->widget()->focusWidget(); if (previousProxyFocus && previousProxyFocus->focusProxy()) @@ -6578,7 +6311,7 @@ void QWidget::setFocus(Qt::FocusReason reason) #if QT_CONFIG(graphicsview) // Update proxy state - if (QWExtra *topData = window()->d_func()->extra) { + if (const auto &topData = window()->d_func()->extra) { if (topData->proxyWidget && !topData->proxyWidget->hasFocus()) { f->d_func()->updateFocusChild(); topData->proxyWidget->d_func()->focusFromWidgetToProxy = 1; @@ -6619,7 +6352,7 @@ void QWidget::setFocus(Qt::FocusReason reason) } #endif #if QT_CONFIG(graphicsview) - if (QWExtra *topData = window()->d_func()->extra) { + if (const auto &topData = window()->d_func()->extra) { if (topData->proxyWidget) { if (previousProxyFocus && previousProxyFocus != f) { // Send event to self @@ -6632,7 +6365,7 @@ void QWidget::setFocus(Qt::FocusReason reason) if (!isHidden()) { #if QT_CONFIG(graphicsview) // Update proxy state - if (QWExtra *topData = window()->d_func()->extra) + if (const auto &topData = window()->d_func()->extra) if (topData->proxyWidget && topData->proxyWidget->hasFocus()) topData->proxyWidget->d_func()->updateProxyInputMethodAcceptanceFromWidget(); #endif @@ -6769,7 +6502,7 @@ void QWidget::clearFocus() } #if QT_CONFIG(graphicsview) - QWExtra *topData = d_func()->extra; + const auto &topData = d_func()->extra; if (topData && topData->proxyWidget) topData->proxyWidget->clearFocus(); #endif @@ -6777,17 +6510,10 @@ void QWidget::clearFocus() if (hasFocus()) { // Update proxy state QApplicationPrivate::setFocusWidget(0, Qt::OtherFocusReason); -#if 0 // Used to be included in Qt4 for Q_WS_WIN - if (!(windowType() == Qt::Popup) && GetFocus() == internalWinId()) - SetFocus(0); - else -#endif - { #ifndef QT_NO_ACCESSIBILITY - QAccessibleEvent event(this, QAccessible::Focus); - QAccessible::updateAccessibility(&event); + QAccessibleEvent event(this, QAccessible::Focus); + QAccessible::updateAccessibility(&event); #endif - } } } @@ -6935,7 +6661,7 @@ bool QWidget::isActiveWindow() const return true; #if QT_CONFIG(graphicsview) - if (QWExtra *tlwExtra = tlw->d_func()->extra) { + if (const auto &tlwExtra = tlw->d_func()->extra) { if (isVisible() && tlwExtra->proxyWidget) return tlwExtra->proxyWidget->isActiveWindow(); } @@ -7431,18 +7157,6 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) */ QByteArray QWidget::saveGeometry() const { -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // We check if the window was maximized during this invocation. If so, we need to record the - // starting position as 0,0. - Q_D(const QWidget); - QRect newFramePosition = frameGeometry(); - QRect newNormalPosition = normalGeometry(); - if(d->topData()->wasMaximized && !(windowState() & Qt::WindowMaximized)) { - // Change the starting position - newFramePosition.moveTo(0, 0); - newNormalPosition.moveTo(0, 0); - } -#endif QByteArray array; QDataStream stream(&array, QIODevice::WriteOnly); stream.setVersion(QDataStream::Qt_4_0); @@ -7457,13 +7171,8 @@ QByteArray QWidget::saveGeometry() const stream << magicNumber << majorVersion << minorVersion -#if 0 // Used to be included in Qt4 for Q_WS_MAC - << newFramePosition - << newNormalPosition -#else << frameGeometry() << normalGeometry() -#endif << qint32(screenNumber) << quint8(windowState() & Qt::WindowMaximized) << quint8(windowState() & Qt::WindowFullScreen) @@ -7583,11 +7292,6 @@ bool QWidget::restoreGeometry(const QByteArray &geometry) // that would make the window "lost". This happens if: // - The restored geometry is completely oustside the available geometry // - The title bar is outside the available geometry. - // - (Mac only) The window is higher than the available geometry. It must - // be possible to bring the size grip on screen by moving the window. -#if 0 // Used to be included in Qt4 for Q_WS_MAC - restoredNormalGeometry.setHeight(qMin(restoredNormalGeometry.height(), availableGeometry.height() - frameHeight)); -#endif checkRestoredGeometry(availableGeometry, &restoredGeometry, frameHeight); checkRestoredGeometry(availableGeometry, &restoredNormalGeometry, frameHeight); @@ -8107,14 +7811,6 @@ void QWidgetPrivate::show_helper() Q_UNUSED(isEmbedded); #endif - // On Windows, show the popup now so that our own focus handling - // stores the correct old focus widget even if it's stolen in the - // showevent -#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ || 0 /* Used to be included in Qt4 for Q_WS_MAC */ - if (!isEmbedded && q->windowType() == Qt::Popup) - qApp->d_func()->openPopup(q); -#endif - // send the show event before showing the window QShowEvent showEvent; QCoreApplication::sendEvent(q, &showEvent); @@ -8239,12 +7935,6 @@ void QWidgetPrivate::hide_helper() if (!isEmbedded && (q->windowType() == Qt::Popup)) qApp->d_func()->closePopup(q); -#if 0 // Used to be included in Qt4 for Q_WS_WIN - if (q->isWindow() && !(q->windowType() == Qt::Popup) && q->parentWidget() - && !q->parentWidget()->isHidden() && q->isActiveWindow()) - q->parentWidget()->activateWindow(); // Activate parent -#endif - q->setAttribute(Qt::WA_Mapped, false); hide_sys(); @@ -8273,8 +7963,8 @@ void QWidgetPrivate::hide_helper() } } - if (QWidgetBackingStore *bs = maybeBackingStore()) - bs->removeDirtyWidget(q); + if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) + repaintManager->removeDirtyWidget(q); #ifndef QT_NO_ACCESSIBILITY if (wasVisible) { @@ -8429,16 +8119,6 @@ void QWidgetPrivate::setVisible(bool visible) QEvent showToParentEvent(QEvent::ShowToParent); QCoreApplication::sendEvent(q, &showToParentEvent); } else { // hide -#if 0 // Used to be included in Qt4 for Q_WS_WIN - // reset WS_DISABLED style in a Blocked window - if(isWindow() && testAttribute(Qt::WA_WState_Created) - && QApplicationPrivate::isBlockedByModal(this)) - { - LONG dwStyle = GetWindowLong(winId(), GWL_STYLE); - dwStyle &= ~WS_DISABLED; - SetWindowLong(winId(), GWL_STYLE, dwStyle); - } -#endif if (QApplicationPrivate::hidden_focus_widget == q) QApplicationPrivate::hidden_focus_widget = 0; @@ -8511,23 +8191,7 @@ void QWidgetPrivate::hideChildren(bool spontaneous) QWidget *widget = qobject_cast<QWidget*>(childList.at(i)); if (!widget || widget->isWindow() || widget->testAttribute(Qt::WA_WState_Hidden)) continue; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // Before doing anything we need to make sure that we don't leave anything in a non-consistent state. - // When hiding a widget we need to make sure that no mouse_down events are active, because - // the mouse_up event will never be received by a hidden widget or one of its descendants. - // The solution is simple, before going through with this we check if there are any mouse_down events in - // progress, if so we check if it is related to this widget or not. If so, we just reset the mouse_down and - // then we continue. - // In X11 and Windows we send a mouse_release event, however we don't do that here because we were already - // ignoring that from before. I.e. Carbon did not send the mouse release event, so we will not send the - // mouse release event. There are two ways to interpret this: - // 1. If we don't send the mouse release event, the widget might get into an inconsistent state, i.e. it - // might be waiting for a release event that will never arrive. - // 2. If we send the mouse release event, then the widget might decide to trigger an action that is not - // supposed to trigger because it is not visible. - if(widget == qt_button_down) - qt_button_down = 0; -#endif + if (spontaneous) widget->setAttribute(Qt::WA_Mapped, false); else @@ -8762,11 +8426,9 @@ QSize QWidgetPrivate::adjustedSize() const s.setWidth(qMax(s.width(), 200)); if (exp & Qt::Vertical) s.setHeight(qMax(s.height(), 100)); -#if 0 // Used to be included in Qt4 for Q_WS_X11 - QRect screen = QDesktopWidgetPrivate::screenGeometry(q->x11Info().screen()); -#else // all others + QRect screen = QDesktopWidgetPrivate::screenGeometry(q->pos()); -#endif + s.setWidth(qMin(s.width(), screen.width()*2/3)); s.setHeight(qMin(s.height(), screen.height()*2/3)); @@ -8891,26 +8553,6 @@ bool QWidget::isAncestorOf(const QWidget *child) const return false; } -#if 0 // Used to be included in Qt4 for Q_WS_WIN -inline void setDisabledStyle(QWidget *w, bool setStyle) -{ - // set/reset WS_DISABLED style. - if(w && w->isWindow() && w->isVisible() && w->isEnabled()) { - LONG dwStyle = GetWindowLong(w->winId(), GWL_STYLE); - LONG newStyle = dwStyle; - if (setStyle) - newStyle |= WS_DISABLED; - else - newStyle &= ~WS_DISABLED; - if (newStyle != dwStyle) { - SetWindowLong(w->winId(), GWL_STYLE, newStyle); - // we might need to repaint in some situations (eg. menu) - w->repaint(); - } - } -} -#endif - /***************************************************************************** QWidget event handling *****************************************************************************/ @@ -9327,9 +8969,6 @@ bool QWidget::event(QEvent *event) } } } -#if 0 // Used to be included in Qt4 for Q_WS_WIN - setDisabledStyle(this, (event->type() == QEvent::WindowBlocked)); -#endif break; #ifndef QT_NO_TOOLTIP case QEvent::ToolTip: @@ -9354,9 +8993,6 @@ bool QWidget::event(QEvent *event) case QEvent::EmbeddingControl: d->topData()->frameStrut.setCoords(0 ,0, 0, 0); data->fstrut_dirty = false; -#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ || 0 /* Used to be included in Qt4 for Q_WS_X11 */ - d->topData()->embedded = 1; -#endif break; #ifndef QT_NO_ACTION case QEvent::ActionAdded: @@ -9379,11 +9015,6 @@ bool QWidget::event(QEvent *event) } break; } -#if 0 // Used to be included in Qt4 for Q_WS_MAC - case QEvent::MacGLWindowChange: - d->needWindowChange = false; - break; -#endif case QEvent::TouchBegin: case QEvent::TouchUpdate: case QEvent::TouchEnd: @@ -9495,11 +9126,6 @@ void QWidget::changeEvent(QEvent * event) case QEvent::MacSizeChange: updateGeometry(); break; -#elif 0 // Used to be included in Qt4 for Q_WS_MAC - case QEvent::ToolTipChange: - case QEvent::MouseTrackingChange: - qt_mac_update_mouseTracking(this); - break; #endif default: @@ -10425,7 +10051,7 @@ void QWidget::setSizePolicy(QSizePolicy policy) d->size_policy = policy; #if QT_CONFIG(graphicsview) - if (QWExtra *extra = d->extra) { + if (const auto &extra = d->extra) { if (extra->proxyWidget) extra->proxyWidget->setSizePolicy(policy); } @@ -10768,16 +10394,8 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) if (newParent && isAncestorOf(focusWidget())) focusWidget()->clearFocus(); - QTLWExtra *oldTopExtra = window()->d_func()->maybeTopData(); - QWidgetBackingStoreTracker *oldBsTracker = oldTopExtra ? &oldTopExtra->backingStoreTracker : 0; - d->setParent_sys(parent, f); - QTLWExtra *topExtra = window()->d_func()->maybeTopData(); - QWidgetBackingStoreTracker *bsTracker = topExtra ? &topExtra->backingStoreTracker : 0; - if (oldBsTracker && oldBsTracker != bsTracker) - oldBsTracker->unregisterWidgetSubtree(this); - if (desktopWidget) parent = 0; @@ -10788,12 +10406,12 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) } #endif - if (QWidgetBackingStore *oldBs = oldtlw->d_func()->maybeBackingStore()) { + if (QWidgetRepaintManager *oldPaintManager = oldtlw->d_func()->maybeRepaintManager()) { if (newParent) - oldBs->removeDirtyWidget(this); + oldPaintManager->removeDirtyWidget(this); // Move the widget and all its static children from // the old backing store to the new one. - oldBs->moveStaticWidgets(this); + oldPaintManager->moveStaticWidgets(this); } // ### fixme: Qt 6: Remove AA_ImmediateWidgetCreation. @@ -10819,7 +10437,7 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) // (f & Qt::MSWindowsOwnDC) clause (which is set on QGLWidgets on all // platforms). if (newParent -#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ || defined(QT_OPENGL_ES) +#if defined(QT_OPENGL_ES) || (f & Qt::MSWindowsOwnDC) #endif ) { @@ -10838,15 +10456,6 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) QCoreApplication::sendEvent(parent, &e); } -//### already hidden above ---> must probably do something smart on the mac -// #if 0 // Used to be included in Qt4 for Q_WS_MAC -// extern bool qt_mac_is_macdrawer(const QWidget *); //qwidget_mac.cpp -// if(!qt_mac_is_macdrawer(q)) //special case -// q->setAttribute(Qt::WA_WState_Hidden); -// #else -// q->setAttribute(Qt::WA_WState_Hidden); -//#endif - if (parent && d->sendChildEvents && d->polished) { QChildEvent e(QEvent::ChildPolished, this); QCoreApplication::sendEvent(parent, &e); @@ -11147,7 +10756,7 @@ void QWidgetPrivate::repaint(T r) QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) - tlwExtra->backingStoreTracker->markDirty(r, q, QWidgetBackingStore::UpdateNow); + tlwExtra->repaintManager->markDirty(r, q, QWidgetRepaintManager::UpdateNow); } /*! @@ -11222,7 +10831,7 @@ void QWidgetPrivate::update(T r) QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) - tlwExtra->backingStoreTracker->markDirty(clipped, q); + tlwExtra->repaintManager->markDirty(clipped, q); } /*! @@ -11328,23 +10937,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) case Qt::WA_NoChildEventsFromChildren: d->receiveChildEvents = !on; break; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - case Qt::WA_MacOpaqueSizeGrip: - d->macUpdateOpaqueSizeGrip(); - break; - case Qt::WA_MacShowFocusRect: - if (hasFocus()) { - clearFocus(); - setFocus(); - } - break; - case Qt::WA_Hover: - qt_mac_update_mouseTracking(this); - break; - case Qt::WA_MacAlwaysShowToolWindow: - d->macUpdateHideOnSuspend(); - break; -#endif case Qt::WA_MacNormalSize: case Qt::WA_MacSmallSize: case Qt::WA_MacMiniSize: @@ -11422,15 +11014,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) } case Qt::WA_PaintOnScreen: d->updateIsOpaque(); -#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ || 0 /* Used to be included in Qt4 for Q_WS_X11 */ || 0 /* Used to be included in Qt4 for Q_WS_MAC */ - // Recreate the widget if it's already created as an alien widget and - // WA_PaintOnScreen is enabled. Paint on screen widgets must have win id. - // So must their children. - if (on) { - setAttribute(Qt::WA_NativeWindow); - d->enforceNativeChildren(); - } -#endif Q_FALLTHROUGH(); case Qt::WA_OpaquePaintEvent: d->updateIsOpaque(); @@ -11442,9 +11025,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) d->updateSystemBackground(); break; case Qt::WA_TransparentForMouseEvents: -#if 0 // Used to be included in Qt4 for Q_WS_MAC - d->macUpdateIgnoreMouseEvents(); -#endif break; case Qt::WA_InputMethodEnabled: { #ifndef QT_NO_IM @@ -11461,20 +11041,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) d->resolveFont(); d->resolveLocale(); break; -#if 0 // Used to be included in Qt4 for Q_WS_X11 - case Qt::WA_NoX11EventCompression: - if (!d->extra) - d->createExtra(); - d->extra->compress_events = on; - break; - case Qt::WA_X11OpenGLOverlay: - d->updateIsOpaque(); - break; - case Qt::WA_X11DoNotAcceptFocus: - if (testAttribute(Qt::WA_WState_Created)) - d->updateX11AcceptFocus(); - break; -#endif case Qt::WA_DontShowOnScreen: { if (on && isVisible()) { // Make sure we keep the current state and only hide the widget @@ -11503,11 +11069,11 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) break; case Qt::WA_StaticContents: - if (QWidgetBackingStore *bs = d->maybeBackingStore()) { + if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) { if (on) - bs->addStaticWidget(this); + repaintManager->addStaticWidget(this); else - bs->removeStaticWidget(this); + repaintManager->removeStaticWidget(this); } break; case Qt::WA_TranslucentBackground: @@ -11517,10 +11083,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) break; case Qt::WA_AcceptTouchEvents: -#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ || 0 /* Used to be included in Qt4 for Q_WS_MAC */ - if (on) - d->registerTouchWindow(); -#endif break; default: break; @@ -12136,10 +11698,8 @@ QRect QWidgetPrivate::frameStrut() const } if (data.fstrut_dirty -#if 1 // Used to be excluded in Qt4 for Q_WS_WIN // ### Fix properly for 4.3 && q->isVisible() -#endif && q->testAttribute(Qt::WA_WState_Created)) const_cast<QWidgetPrivate *>(this)->updateFrameStrut(); @@ -12312,14 +11872,14 @@ void QWidget::setBackingStore(QBackingStore *store) deleteBackingStore(d); topData->backingStore = store; - QWidgetBackingStore *bs = d->maybeBackingStore(); - if (!bs) + QWidgetRepaintManager *repaintManager = d->maybeRepaintManager(); + if (!repaintManager) return; if (isTopLevel()) { - if (bs->store != oldStore && bs->store != store) - delete bs->store; - bs->store = store; + if (repaintManager->backingStore() != oldStore && repaintManager->backingStore() != store) + delete repaintManager->backingStore(); + repaintManager->setBackingStore(store); } } @@ -12335,9 +11895,8 @@ QBackingStore *QWidget::backingStore() const if (extra && extra->backingStore) return extra->backingStore; - QWidgetBackingStore *bs = d->maybeBackingStore(); - - return bs ? bs->store : 0; + QWidgetRepaintManager *repaintManager = d->maybeRepaintManager(); + return repaintManager ? repaintManager->backingStore() : nullptr; } void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const @@ -12410,19 +11969,18 @@ QOpenGLContext *QWidgetPrivate::shareContext() const #ifdef QT_NO_OPENGL return 0; #else - if (Q_UNLIKELY(!extra || !extra->topextra || !extra->topextra->window)) + if (!extra || !extra->topextra || !extra->topextra->window) return 0; - QWidgetPrivate *that = const_cast<QWidgetPrivate *>(this); if (!extra->topextra->shareContext) { - QOpenGLContext *ctx = new QOpenGLContext; + auto ctx = qt_make_unique<QOpenGLContext>(); ctx->setShareContext(qt_gl_global_share_context()); ctx->setFormat(extra->topextra->window->format()); ctx->setScreen(extra->topextra->window->screen()); ctx->create(); - that->extra->topextra->shareContext = ctx; + extra->topextra->shareContext = std::move(ctx); } - return that->extra->topextra->shareContext; + return extra->topextra->shareContext.get(); #endif // QT_NO_OPENGL } @@ -13068,10 +12626,8 @@ void QWidget::setMask(const QRegion &newMask) d->extra->mask = newMask; d->extra->hasMask = !newMask.isEmpty(); -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC if (!testAttribute(Qt::WA_WState_Created)) return; -#endif d->setMask_sys(newMask); diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h index 0777bed65c..83a6e6d4b3 100644 --- a/src/widgets/kernel/qwidget.h +++ b/src/widgets/kernel/qwidget.h @@ -85,6 +85,7 @@ class QDragEnterEvent; class QDragMoveEvent; class QDragLeaveEvent; class QDropEvent; +class QScreen; class QShowEvent; class QHideEvent; class QIcon; @@ -601,6 +602,7 @@ public: QBackingStore *backingStore() const; QWindow *windowHandle() const; + QScreen *screen() const; static QWidget *createWindowContainer(QWindow *window, QWidget *parent=nullptr, Qt::WindowFlags flags=Qt::WindowFlags()); @@ -697,7 +699,7 @@ private: QLayout *takeLayout(); friend class QBackingStoreDevice; - friend class QWidgetBackingStore; + friend class QWidgetRepaintManager; friend class QApplication; friend class QApplicationPrivate; friend class QGuiApplication; diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 7cb9a3895a..698928b0b0 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -75,15 +75,20 @@ #include <private/qgesture_p.h> #include <qpa/qplatformbackingstore.h> +#include <vector> +#include <memory> + QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcWidgetPainting); + // Extra QWidget data // - to minimize memory usage for members that are seldom used. // - top-level widgets have extra extra data to reduce cost further class QWidgetWindow; class QPaintEngine; class QPixmap; -class QWidgetBackingStore; +class QWidgetRepaintManager; class QGraphicsProxyWidget; class QWidgetItemV2; class QOpenGLContext; @@ -113,60 +118,18 @@ protected: QRegion m_region; }; - - -class Q_AUTOTEST_EXPORT QWidgetBackingStoreTracker -{ - -public: - QWidgetBackingStoreTracker(); - ~QWidgetBackingStoreTracker(); - - void create(QWidget *tlw); - void destroy(); - - void registerWidget(QWidget *w); - void unregisterWidget(QWidget *w); - void unregisterWidgetSubtree(QWidget *w); - - inline QWidgetBackingStore* data() - { - return m_ptr; - } - - inline QWidgetBackingStore* operator->() - { - return m_ptr; - } - - inline QWidgetBackingStore& operator*() - { - return *m_ptr; - } - - inline operator bool() const - { - return (nullptr != m_ptr); - } - -private: - Q_DISABLE_COPY_MOVE(QWidgetBackingStoreTracker) - -private: - QWidgetBackingStore* m_ptr; - QSet<QWidget *> m_widgets; -}; - struct QTLWExtra { // *************************** Cross-platform variables ***************************** // Regular pointers (keep them together to avoid gaps on 64 bits architectures). - QIcon *icon; // widget icon - QWidgetBackingStoreTracker backingStoreTracker; + std::unique_ptr<QIcon> icon; // widget icon + std::unique_ptr<QWidgetRepaintManager> repaintManager; QBackingStore *backingStore; QPainter *sharedPainter; QWidgetWindow *window; - QOpenGLContext *shareContext; +#ifndef QT_NO_OPENGL + mutable std::unique_ptr<QOpenGLContext> shareContext; +#endif // Implicit pointers (shared_null). QString caption; // widget caption @@ -184,7 +147,9 @@ struct QTLWExtra { // ### TODO replace initialScreenIndex with QScreen *, in case the screens change at runtime int initialScreenIndex; // Screen number when passing a QDesktop[Screen]Widget as parent. - QVector<QPlatformTextureList *> widgetTextures; +#ifndef QT_NO_OPENGL + std::vector<std::unique_ptr<QPlatformTextureList>> widgetTextures; +#endif // *************************** Cross-platform bit fields **************************** uint opacity : 8; @@ -192,41 +157,6 @@ struct QTLWExtra { uint sizeAdjusted : 1; uint inTopLevelResize : 1; uint embedded : 1; - - // *************************** Platform specific values (bit fields first) ********** -#if 0 /* Used to be included in Qt4 for Q_WS_X11 */ // <----------------------------------------------------------- X11 - uint spont_unmapped: 1; // window was spontaneously unmapped - uint dnd : 1; // DND properties installed - uint validWMState : 1; // is WM_STATE valid? - uint waitingForMapNotify : 1; // show() has been called, haven't got the MapNotify yet - WId parentWinId; // parent window Id (valid after reparenting) - WId userTimeWindow; // window id that contains user-time timestamp when WM supports a _NET_WM_USER_TIME_WINDOW atom - QPoint fullScreenOffset; -#ifndef QT_NO_XSYNC - WId syncUpdateCounter; - ulong syncRequestTimestamp; - qint32 newCounterValueHi; - quint32 newCounterValueLo; -#endif -#elif 0 /* Used to be included in Qt4 for Q_WS_WIN */ // <--------------------------------------------------------- WIN - uint hotkeyRegistered: 1; // Hot key from the STARTUPINFO has been registered. - HICON winIconBig; // internal big Windows icon - HICON winIconSmall; // internal small Windows icon -#elif 0 /* Used to be included in Qt4 for Q_WS_MAC */ // <--------------------------------------------------------- MAC - uint resizer : 4; - uint isSetGeometry : 1; - uint isMove : 1; - quint32 wattr; - quint32 wclass; - WindowGroupRef group; - IconRef windowIcon; // the current window icon, if set with setWindowIcon_sys. - quint32 savedWindowAttributesFromMaximized; // Saved attributes from when the calling updateMaximizeButton_sys() - // This value is just to make sure we maximize and restore to the right location, yet we allow apps to be maximized and - // manually resized. - // The name is misleading, since this is set when maximizing the window. It is a hint to saveGeometry(..) to record the - // starting position as 0,0 instead of the normal starting position. - bool wasMaximized; -#endif }; struct QWExtra { @@ -234,12 +164,12 @@ struct QWExtra { // Regular pointers (keep them together to avoid gaps on 64 bits architectures). void *glContext; // if the widget is hijacked by QGLWindowSurface - QTLWExtra *topextra; // only useful for TLWs + std::unique_ptr<QTLWExtra> topextra; // only useful for TLWs #if QT_CONFIG(graphicsview) QGraphicsProxyWidget *proxyWidget; // if the widget is embedded #endif #ifndef QT_NO_CURSOR - QCursor *curs; + std::unique_ptr<QCursor> curs; #endif QPointer<QStyle> style; QPointer<QWidget> focus_proxy; @@ -265,21 +195,6 @@ struct QWExtra { uint inRenderWithPainter : 1; uint hasMask : 1; uint hasWindowContainer : 1; - - // *************************** Platform specific values (bit fields first) ********** -#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ // <----------------------------------------------------------- WIN -#if QT_CONFIG(draganddrop) - QOleDropTarget *dropTarget; // drop target - QList<QPointer<QWidget> > oleDropWidgets; -#endif -#elif 0 /* Used to be included in Qt4 for Q_WS_X11 */ // <--------------------------------------------------------- X11 - uint compress_events : 1; - WId xDndProxy; // XDND forwarding to embedded windows -#elif 0 /* Used to be included in Qt4 for Q_WS_MAC */ // <------------------------------------------------------ MAC - // Cocoa Mask stuff - QImage maskBits; - CGImageRef imageMask; -#endif }; /*! @@ -303,10 +218,11 @@ static inline bool bypassGraphicsProxyWidget(const QWidget *p) class Q_WIDGETS_EXPORT QWidgetPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QWidget) + Q_GADGET public: // *************************** Cross-platform *************************************** - enum DrawWidgetFlags { + enum DrawWidgetFlag { DrawAsRoot = 0x01, DrawPaintOnScreen = 0x02, DrawRecursive = 0x04, @@ -316,12 +232,15 @@ public: DontDrawNativeChildren = 0x40, DontSetCompositionMode = 0x80 }; + Q_DECLARE_FLAGS(DrawWidgetFlags, DrawWidgetFlag) + Q_FLAG(DrawWidgetFlags) enum CloseMode { CloseNoEvent, CloseWithEvent, CloseWithSpontaneousEvent }; + Q_ENUM(CloseMode) enum Direction { DirectionNorth = 0x01, @@ -329,6 +248,7 @@ public: DirectionSouth = 0x02, DirectionWest = 0x20 }; + Q_ENUM(Direction) // Functions. explicit QWidgetPrivate(int version = QObjectPrivateVersion); @@ -342,7 +262,7 @@ public: QTLWExtra *maybeTopData() const; QPainter *sharedPainter() const; void setSharedPainter(QPainter *painter); - QWidgetBackingStore *maybeBackingStore() const; + QWidgetRepaintManager *maybeRepaintManager() const; enum class WindowHandleMode { Direct, @@ -413,26 +333,27 @@ public: void setUpdatesEnabled_helper(bool ); bool updateBrushOrigin(QPainter *, const QBrush &brush) const; - void paintBackground(QPainter *, const QRegion &, int flags = DrawAsRoot) const; + void paintBackground(QPainter *, const QRegion &, DrawWidgetFlags flags = DrawAsRoot) const; bool isAboutToShow() const; QRegion prepareToRender(const QRegion ®ion, QWidget::RenderFlags renderFlags); void render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &sourceRegion, QWidget::RenderFlags renderFlags); void render(QPaintDevice *target, const QPoint &targetOffset, const QRegion &sourceRegion, QWidget::RenderFlags renderFlags); - void drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, int flags, - QPainter *sharedPainter = nullptr, QWidgetBackingStore *backingStore = nullptr); + void drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags, + QPainter *sharedPainter = nullptr, QWidgetRepaintManager *repaintManager = nullptr); void sendPaintEvent(const QRegion &toBePainted); void paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& children, int index, - const QRegion &rgn, const QPoint &offset, int flags, - QPainter *sharedPainter, QWidgetBackingStore *backingStore); + const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags, + QPainter *sharedPainter, QWidgetRepaintManager *repaintManager); #if QT_CONFIG(graphicsview) static QGraphicsProxyWidget * nearestGraphicsProxyWidget(const QWidget *origin); #endif - void repaint_sys(const QRegion &rgn); + bool shouldPaintOnScreen() const; + void paintOnScreen(const QRegion &rgn); QRect clipRect() const; QRegion clipRegion() const; @@ -444,7 +365,6 @@ public: void updateIsOpaque(); void setOpaque(bool opaque); void updateIsTranslucent(); - bool paintOnScreen() const; #if QT_CONFIG(graphicseffect) void invalidateGraphicsEffectsRecursively(); #endif // QT_CONFIG(graphicseffect) @@ -471,6 +391,8 @@ public: void syncBackingStore(); void syncBackingStore(const QRegion ®ion); + bool shouldDiscardSyncRequest() const; + // tells the input method about the widgets transform void updateWidgetTransform(QEvent *event); @@ -706,7 +628,7 @@ public: // Variables. // Regular pointers (keep them together to avoid gaps on 64 bit architectures). - QWExtra *extra; + std::unique_ptr<QWExtra> extra; QWidget *focus_next; QWidget *focus_prev; QWidget *focus_child; @@ -800,109 +722,8 @@ public: // *************************** Platform specific ************************************ #if defined(Q_OS_WIN) uint noPaintOnScreen : 1; // see qwidget.cpp ::paintEngine() -#endif -#if 0 /* Used to be included in Qt4 for Q_WS_X11 */ // <----------------------------------------------------------- X11 - Qt::HANDLE picture; - static QWidget *mouseGrabber; - static QWidget *keyboardGrabber; - - void setWindowRole(); - void sendStartupMessage(const char *message) const; - void x11UpdateIsOpaque(); - bool isBackgroundInherited() const; - void updateX11AcceptFocus(); - QPoint mapToGlobal(const QPoint &pos) const; - QPoint mapFromGlobal(const QPoint &pos) const; -#elif 0 /* Used to be included in Qt4 for Q_WS_WIN */ // <--------------------------------------------------------- WIN -#ifndef QT_NO_GESTURES - uint nativeGesturePanEnabled : 1; -#endif - bool shouldShowMaximizeButton(); - void winUpdateIsOpaque(); - void reparentChildren(); -#if QT_CONFIG(draganddrop) - QOleDropTarget *registerOleDnd(QWidget *widget); - void unregisterOleDnd(QWidget *widget, QOleDropTarget *target); -#endif - void grabMouseWhileInWindow(); - void registerTouchWindow(); - void winSetupGestures(); -#elif defined(Q_OS_MAC) // <--------------------------------------------------------- MAC +#elif defined(Q_OS_MAC) void macUpdateSizeAttribute(); -#elif 0 /* Used to be included in Qt4 for Q_WS_MAC */ // <--------------------------------------------------------- MAC (old stuff) - // This is new stuff - uint needWindowChange : 1; - - // Each wiget keeps a list of all its child and grandchild OpenGL widgets. - // This list is used to update the gl context whenever a parent and a granparent - // moves, and also to check for intersections with gl widgets within the window - // when a widget moves. - struct GlWidgetInfo - { - GlWidgetInfo(QWidget *widget) : widget(widget), lastUpdateWidget(0) { } - bool operator==(const GlWidgetInfo &other) const { return (widget == other.widget); } - QWidget * widget; - QWidget * lastUpdateWidget; - }; - - // dirtyOnWidget contains the areas in the widget that needs to be repained, - // in the same way as dirtyOnScreen does for the window. Areas are added in - // dirtyWidget_sys and cleared in the paint event. In scroll_sys we then use - // this information repaint invalid areas when widgets are scrolled. - QRegion dirtyOnWidget; - EventHandlerRef window_event; - QList<GlWidgetInfo> glWidgets; - - //these are here just for code compat (HIViews) - Qt::HANDLE qd_hd; - - void macUpdateHideOnSuspend(); - void macUpdateOpaqueSizeGrip(); - void macUpdateIgnoreMouseEvents(); - void macUpdateMetalAttribute(); - void macUpdateIsOpaque(); - void macSetNeedsDisplay(QRegion region); - void setEnabled_helper_sys(bool enable); - bool isRealWindow() const; - void adjustWithinMaxAndMinSize(int &w, int &h); - void applyMaxAndMinSizeOnWindow(); - void update_sys(const QRect &rect); - void update_sys(const QRegion &rgn); - void setGeometry_sys_helper(int, int, int, int, bool); - void updateMaximizeButton_sys(); - void createWindow_sys(); - void recreateMacWindow(); - void setSubWindowStacking(bool set); - void setWindowLevel(); - void finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ windowRef); - void syncCocoaMask(); - void finishCocoaMaskSetup(); - // Did we add the drawRectOriginal method? - bool drawRectOriginalAdded; - // Is the original drawRect method available? - bool originalDrawMethod; - // Do we need to change the methods? - bool changeMethods; - - // Unified toolbar variables - bool isInUnifiedToolbar; - QUnifiedToolbarSurface *unifiedSurface; - QPoint toolbar_offset; - QWidget *toolbar_ancestor; - bool flushRequested; - bool touchEventsEnabled; - void determineWindowClass(); - void transferChildren(); - bool qt_mac_dnd_event(uint, DragRef); - void toggleDrawers(bool); - //mac event functions - static bool qt_create_root_win(); - static void qt_clean_root_win(); - static bool qt_mac_update_sizer(QWidget *, int up = 0); - static OSStatus qt_window_event(EventHandlerCallRef er, EventRef event, void *); - static OSStatus qt_widget_event(EventHandlerCallRef er, EventRef event, void *); - static bool qt_widget_rgn(QWidget *, short, RgnHandle, bool); - void registerTouchWindow(bool enable = true); #endif void setNetWmWindowTypes(bool skipIfMissing = false); @@ -910,18 +731,20 @@ public: bool stealMouseGrab(bool grab); }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QWidgetPrivate::DrawWidgetFlags) + struct QWidgetPaintContext { - inline QWidgetPaintContext(QPaintDevice *d, const QRegion &r, const QPoint &o, int f, - QPainter *p, QWidgetBackingStore *b) - : pdev(d), rgn(r), offset(o), flags(f), sharedPainter(p), backingStore(b), painter(nullptr) {} + inline QWidgetPaintContext(QPaintDevice *d, const QRegion &r, const QPoint &o, QWidgetPrivate::DrawWidgetFlags f, + QPainter *p, QWidgetRepaintManager *rpm) + : pdev(d), rgn(r), offset(o), flags(f), sharedPainter(p), repaintManager(rpm), painter(nullptr) {} QPaintDevice *pdev; QRegion rgn; QPoint offset; - int flags; + QWidgetPrivate::DrawWidgetFlags flags; QPainter *sharedPainter; - QWidgetBackingStore *backingStore; + QWidgetRepaintManager *repaintManager; QPainter *painter; }; @@ -982,18 +805,18 @@ public: inline QWExtra *QWidgetPrivate::extraData() const { - return extra; + return extra.get(); } inline QTLWExtra *QWidgetPrivate::topData() const { const_cast<QWidgetPrivate *>(this)->createTLExtra(); - return extra->topextra; + return extra->topextra.get(); } inline QTLWExtra *QWidgetPrivate::maybeTopData() const { - return extra ? extra->topextra : nullptr; + return extra ? extra->topextra.get() : nullptr; } inline QPainter *QWidgetPrivate::sharedPainter() const @@ -1017,11 +840,11 @@ inline bool QWidgetPrivate::pointInsideRectAndMask(const QPoint &p) const || extra->mask.contains(p)); } -inline QWidgetBackingStore *QWidgetPrivate::maybeBackingStore() const +inline QWidgetRepaintManager *QWidgetPrivate::maybeRepaintManager() const { Q_Q(const QWidget); QTLWExtra *x = q->window()->d_func()->maybeTopData(); - return x ? x->backingStoreTracker.data() : nullptr; + return x ? x->repaintManager.get() : nullptr; } QT_END_NAMESPACE diff --git a/src/widgets/kernel/qwidgetbackingstore_p.h b/src/widgets/kernel/qwidgetbackingstore_p.h deleted file mode 100644 index 9409ba7832..0000000000 --- a/src/widgets/kernel/qwidgetbackingstore_p.h +++ /dev/null @@ -1,310 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWIDGETBACKINGSTORE_P_H -#define QWIDGETBACKINGSTORE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtWidgets/private/qtwidgetsglobal_p.h> -#include <QDebug> -#include <QtWidgets/qwidget.h> -#include <private/qwidget_p.h> -#include <QtGui/qbackingstore.h> - -QT_BEGIN_NAMESPACE - -class QPlatformTextureList; -class QPlatformTextureListWatcher; -class QWidgetBackingStore; - -struct BeginPaintInfo { - inline BeginPaintInfo() : wasFlushed(0), nothingToPaint(0), backingStoreRecreated(0) {} - uint wasFlushed : 1; - uint nothingToPaint : 1; - uint backingStoreRecreated : 1; -}; - -#ifndef QT_NO_OPENGL -class QPlatformTextureListWatcher : public QObject -{ - Q_OBJECT - -public: - QPlatformTextureListWatcher(QWidgetBackingStore *backingStore); - void watch(QPlatformTextureList *textureList); - bool isLocked() const; - -private slots: - void onLockStatusChanged(bool locked); - -private: - QHash<QPlatformTextureList *, bool> m_locked; - QWidgetBackingStore *m_backingStore; -}; -#endif - -class Q_AUTOTEST_EXPORT QWidgetBackingStore -{ -public: - enum UpdateTime { - UpdateNow, - UpdateLater - }; - - enum BufferState{ - BufferValid, - BufferInvalid - }; - - QWidgetBackingStore(QWidget *t); - ~QWidgetBackingStore(); - - static void showYellowThing(QWidget *widget, const QRegion &rgn, int msec, bool); - - void sync(QWidget *exposedWidget, const QRegion &exposedRegion); - void sync(); - void flush(QWidget *widget = nullptr); - - QBackingStore *backingStore() const { return store; } - - inline bool isDirty() const - { - return !(dirtyWidgets.isEmpty() && dirty.isEmpty() && dirtyRenderToTextureWidgets.isEmpty()); - } - - template <class T> - void markDirty(const T &r, QWidget *widget, UpdateTime updateTime = UpdateLater, - BufferState bufferState = BufferValid); - -private: - QWidget *tlw; - QRegion dirtyOnScreen; // needsFlush - QRegion dirty; // needsRepaint - QRegion dirtyFromPreviousSync; - QVector<QWidget *> dirtyWidgets; - QVector<QWidget *> dirtyRenderToTextureWidgets; - QVector<QWidget *> *dirtyOnScreenWidgets; - QList<QWidget *> staticWidgets; - QBackingStore *store; - uint updateRequestSent : 1; - - QPlatformTextureListWatcher *textureListWatcher; - QElapsedTimer perfTime; - int perfFrames; - - void sendUpdateRequest(QWidget *widget, UpdateTime updateTime); - - static bool flushPaint(QWidget *widget, const QRegion &rgn); - static void unflushPaint(QWidget *widget, const QRegion &rgn); - static void qt_flush(QWidget *widget, const QRegion ®ion, QBackingStore *backingStore, - QWidget *tlw, - QPlatformTextureList *widgetTextures, - QWidgetBackingStore *widgetBackingStore); - - void doSync(); - bool bltRect(const QRect &rect, int dx, int dy, QWidget *widget); - - void beginPaint(QRegion &toClean, QWidget *widget, QBackingStore *backingStore, - BeginPaintInfo *returnInfo, bool toCleanIsInTopLevelCoordinates = true); - void endPaint(const QRegion &cleaned, QBackingStore *backingStore, BeginPaintInfo *beginPaintInfo); - - QRegion dirtyRegion(QWidget *widget = nullptr) const; - QRegion staticContents(QWidget *widget = nullptr, const QRect &withinClipRect = QRect()) const; - - void markDirtyOnScreen(const QRegion &dirtyOnScreen, QWidget *widget, const QPoint &topLevelOffset); - - void removeDirtyWidget(QWidget *w); - - void updateLists(QWidget *widget); - - bool syncAllowed(); - - inline void addDirtyWidget(QWidget *widget, const QRegion &rgn) - { - if (widget && !widget->d_func()->inDirtyList && !widget->data->in_destructor) { - QWidgetPrivate *widgetPrivate = widget->d_func(); -#if QT_CONFIG(graphicseffect) - if (widgetPrivate->graphicsEffect) - widgetPrivate->dirty = widgetPrivate->effectiveRectFor(rgn.boundingRect()); - else -#endif // QT_CONFIG(graphicseffect) - widgetPrivate->dirty = rgn; - dirtyWidgets.append(widget); - widgetPrivate->inDirtyList = true; - } - } - - inline void addDirtyRenderToTextureWidget(QWidget *widget) - { - if (widget && !widget->d_func()->inDirtyList && !widget->data->in_destructor) { - QWidgetPrivate *widgetPrivate = widget->d_func(); - Q_ASSERT(widgetPrivate->renderToTexture); - dirtyRenderToTextureWidgets.append(widget); - widgetPrivate->inDirtyList = true; - } - } - - inline void dirtyWidgetsRemoveAll(QWidget *widget) - { - int i = 0; - while (i < dirtyWidgets.size()) { - if (dirtyWidgets.at(i) == widget) - dirtyWidgets.remove(i); - else - ++i; - } - } - - inline void addStaticWidget(QWidget *widget) - { - if (!widget) - return; - - Q_ASSERT(widget->testAttribute(Qt::WA_StaticContents)); - if (!staticWidgets.contains(widget)) - staticWidgets.append(widget); - } - - inline void removeStaticWidget(QWidget *widget) - { staticWidgets.removeAll(widget); } - - // Move the reparented widget and all its static children from this backing store - // to the new backing store if reparented into another top-level / backing store. - inline void moveStaticWidgets(QWidget *reparented) - { - Q_ASSERT(reparented); - QWidgetBackingStore *newBs = reparented->d_func()->maybeBackingStore(); - if (newBs == this) - return; - - int i = 0; - while (i < staticWidgets.size()) { - QWidget *w = staticWidgets.at(i); - if (reparented == w || reparented->isAncestorOf(w)) { - staticWidgets.removeAt(i); - if (newBs) - newBs->addStaticWidget(w); - } else { - ++i; - } - } - } - - inline QRect topLevelRect() const - { - return tlw->data->crect; - } - - inline void appendDirtyOnScreenWidget(QWidget *widget) - { - if (!widget) - return; - - if (!dirtyOnScreenWidgets) { - dirtyOnScreenWidgets = new QVector<QWidget *>; - dirtyOnScreenWidgets->append(widget); - } else if (!dirtyOnScreenWidgets->contains(widget)) { - dirtyOnScreenWidgets->append(widget); - } - } - - inline void dirtyOnScreenWidgetsRemoveAll(QWidget *widget) - { - if (!widget || !dirtyOnScreenWidgets) - return; - - int i = 0; - while (i < dirtyOnScreenWidgets->size()) { - if (dirtyOnScreenWidgets->at(i) == widget) - dirtyOnScreenWidgets->remove(i); - else - ++i; - } - } - - inline void resetWidget(QWidget *widget) - { - if (widget) { - widget->d_func()->inDirtyList = false; - widget->d_func()->isScrolled = false; - widget->d_func()->isMoved = false; - widget->d_func()->dirty = QRegion(); - } - } - - inline void updateStaticContentsSize() - { - for (int i = 0; i < staticWidgets.size(); ++i) { - QWidgetPrivate *wd = staticWidgets.at(i)->d_func(); - if (!wd->extra) - wd->createExtra(); - wd->extra->staticContentsSize = wd->data.crect.size(); - } - } - - inline bool hasStaticContents() const - { -#if defined(Q_OS_WIN) - return !staticWidgets.isEmpty(); -#else - return !staticWidgets.isEmpty() && false; -#endif - } - - friend QRegion qt_dirtyRegion(QWidget *); - friend class QWidgetPrivate; - friend class QWidget; - friend class QBackingStore; - - Q_DISABLE_COPY_MOVE(QWidgetBackingStore) -}; - -QT_END_NAMESPACE - -#endif // QBACKINGSTORE_P_H diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetrepaintmanager.cpp index ab33649b3e..4eb298e108 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetrepaintmanager.cpp @@ -40,7 +40,7 @@ #include "qplatformdefs.h" -#include "qwidgetbackingstore_p.h" +#include "qwidgetrepaintmanager_p.h" #include <QtCore/qglobal.h> #include <QtCore/qdebug.h> @@ -63,443 +63,131 @@ #include <qpa/qplatformbackingstore.h> -#if defined(Q_OS_WIN) && !defined(QT_NO_PAINT_DEBUG) -# include <QtCore/qt_windows.h> -# include <qpa/qplatformnativeinterface.h> -#endif +#include <private/qmemory_p.h> QT_BEGIN_NAMESPACE -extern QRegion qt_dirtyRegion(QWidget *); - #ifndef QT_NO_OPENGL Q_GLOBAL_STATIC(QPlatformTextureList, qt_dummy_platformTextureList) -#endif -/** - * Flushes the contents of the \a backingStore into the screen area of \a widget. - * \a region is the region to be updated in \a widget coordinates. - */ -void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion ®ion, QBackingStore *backingStore, - QWidget *tlw, QPlatformTextureList *widgetTextures, - QWidgetBackingStore *widgetBackingStore) +// Watches one or more QPlatformTextureLists for changes in the lock state and +// triggers a backingstore sync when all the registered lists turn into +// unlocked state. This is essential when a custom composeAndFlush() +// implementation in a platform plugin is not synchronous and keeps +// holding on to the textures for some time even after returning from there. +class QPlatformTextureListWatcher : public QObject { -#ifdef QT_NO_OPENGL - Q_UNUSED(widgetTextures); - Q_ASSERT(!region.isEmpty()); -#else - Q_ASSERT(!region.isEmpty() || widgetTextures); -#endif - Q_ASSERT(widget); - Q_ASSERT(backingStore); - Q_ASSERT(tlw); -#if !defined(QT_NO_PAINT_DEBUG) - static int flushUpdate = qEnvironmentVariableIntValue("QT_FLUSH_UPDATE"); - if (flushUpdate > 0) - QWidgetBackingStore::showYellowThing(widget, region, flushUpdate * 10, false); -#endif - - if (tlw->testAttribute(Qt::WA_DontShowOnScreen) || widget->testAttribute(Qt::WA_DontShowOnScreen)) - return; - - // Foreign Windows do not have backing store content and must not be flushed - if (QWindow *widgetWindow = widget->windowHandle()) { - if (widgetWindow->type() == Qt::ForeignWindow) - return; + Q_OBJECT +public: + QPlatformTextureListWatcher(QWidgetRepaintManager *repaintManager) + : m_repaintManager(repaintManager) {} + + void watch(QPlatformTextureList *textureList) { + connect(textureList, SIGNAL(locked(bool)), SLOT(onLockStatusChanged(bool))); + m_locked[textureList] = textureList->isLocked(); } - static bool fpsDebug = qEnvironmentVariableIntValue("QT_DEBUG_FPS"); - if (fpsDebug) { - if (!widgetBackingStore->perfFrames++) - widgetBackingStore->perfTime.start(); - if (widgetBackingStore->perfTime.elapsed() > 5000) { - double fps = double(widgetBackingStore->perfFrames * 1000) / widgetBackingStore->perfTime.restart(); - qDebug("FPS: %.1f\n", fps); - widgetBackingStore->perfFrames = 0; + bool isLocked() const { + foreach (bool v, m_locked) { + if (v) + return true; } + return false; } - QPoint offset; - if (widget != tlw) - offset += widget->mapTo(tlw, QPoint()); - - QRegion effectiveRegion = region; -#ifndef QT_NO_OPENGL - const bool compositionWasActive = widget->d_func()->renderToTextureComposeActive; - if (!widgetTextures) { - widget->d_func()->renderToTextureComposeActive = false; - // Detect the case of falling back to the normal flush path when no - // render-to-texture widgets are visible anymore. We will force one - // last flush to go through the OpenGL-based composition to prevent - // artifacts. The next flush after this one will use the normal path. - if (compositionWasActive) - widgetTextures = qt_dummy_platformTextureList; - } else { - widget->d_func()->renderToTextureComposeActive = true; - } - // When changing the composition status, make sure the dirty region covers - // the entire widget. Just having e.g. the shown/hidden render-to-texture - // widget's area marked as dirty is incorrect when changing flush paths. - if (compositionWasActive != widget->d_func()->renderToTextureComposeActive) - effectiveRegion = widget->rect(); - - // re-test since we may have been forced to this path via the dummy texture list above - if (widgetTextures) { - qt_window_private(tlw->windowHandle())->compositing = true; - widget->window()->d_func()->sendComposeStatus(widget->window(), false); - // A window may have alpha even when the app did not request - // WA_TranslucentBackground. Therefore the compositor needs to know whether the app intends - // to rely on translucency, in order to decide if it should clear to transparent or opaque. - const bool translucentBackground = widget->testAttribute(Qt::WA_TranslucentBackground); - backingStore->handle()->composeAndFlush(widget->windowHandle(), effectiveRegion, offset, - widgetTextures, translucentBackground); - widget->window()->d_func()->sendComposeStatus(widget->window(), true); - } else +private slots: + void onLockStatusChanged(bool locked) { + QPlatformTextureList *tl = static_cast<QPlatformTextureList *>(sender()); + m_locked[tl] = locked; + if (!isLocked()) + m_repaintManager->sync(); + } + +private: + QHash<QPlatformTextureList *, bool> m_locked; + QWidgetRepaintManager *m_repaintManager; +}; #endif - backingStore->flush(effectiveRegion, widget->windowHandle(), offset); -} -#ifndef QT_NO_PAINT_DEBUG -#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) +// --------------------------------------------------------------------------- -static void showYellowThing_win(QWidget *widget, const QRegion ®ion, int msec) +QWidgetRepaintManager::QWidgetRepaintManager(QWidget *topLevel) + : tlw(topLevel), store(tlw->backingStore()) { - // We expect to be passed a native parent. - QWindow *nativeWindow = widget->windowHandle(); - if (!nativeWindow) - return; - void *hdcV = QGuiApplication::platformNativeInterface()->nativeResourceForWindow(QByteArrayLiteral("getDC"), nativeWindow); - if (!hdcV) - return; - const HDC hdc = reinterpret_cast<HDC>(hdcV); - - static const COLORREF colors[] = {RGB(255, 255, 0), RGB(255, 200, 55), RGB(200, 255, 55), RGB(200, 200, 0)}; - - static size_t i = 0; - const HBRUSH brush = CreateSolidBrush(colors[i]); - i = (i + 1) % (sizeof(colors) / sizeof(colors[0])); - - for (const QRect &rect : region) { - RECT winRect; - SetRect(&winRect, rect.left(), rect.top(), rect.right(), rect.bottom()); - FillRect(hdc, &winRect, brush); - } - DeleteObject(brush); - QGuiApplication::platformNativeInterface()->nativeResourceForWindow(QByteArrayLiteral("releaseDC"), nativeWindow); - ::Sleep(msec); -} -#endif // defined(Q_OS_WIN) && !defined(Q_OS_WINRT) - -void QWidgetBackingStore::showYellowThing(QWidget *widget, const QRegion &toBePainted, int msec, bool unclipped) -{ -#ifdef Q_OS_WINRT - Q_UNUSED(msec) -#endif - QRegion paintRegion = toBePainted; - QRect widgetRect = widget->rect(); - - if (!widget->internalWinId()) { - QWidget *nativeParent = widget->nativeParentWidget(); - const QPoint offset = widget->mapTo(nativeParent, QPoint(0, 0)); - paintRegion.translate(offset); - widgetRect.translate(offset); - widget = nativeParent; - } - -#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) - Q_UNUSED(unclipped); - showYellowThing_win(widget, paintRegion, msec); -#else - //flags to fool painter - bool paintUnclipped = widget->testAttribute(Qt::WA_PaintUnclipped); - if (unclipped && !widget->d_func()->paintOnScreen()) - widget->setAttribute(Qt::WA_PaintUnclipped); - - const bool setFlag = !widget->testAttribute(Qt::WA_WState_InPaintEvent); - if (setFlag) - widget->setAttribute(Qt::WA_WState_InPaintEvent); - - //setup the engine - QPaintEngine *pe = widget->paintEngine(); - if (pe) { - pe->setSystemClip(paintRegion); - { - QPainter p(widget); - p.setClipRegion(paintRegion); - static int i = 0; - switch (i) { - case 0: - p.fillRect(widgetRect, QColor(255,255,0)); - break; - case 1: - p.fillRect(widgetRect, QColor(255,200,55)); - break; - case 2: - p.fillRect(widgetRect, QColor(200,255,55)); - break; - case 3: - p.fillRect(widgetRect, QColor(200,200,0)); - break; - } - i = (i+1) & 3; - p.end(); - } - } - - if (setFlag) - widget->setAttribute(Qt::WA_WState_InPaintEvent, false); - - //restore - widget->setAttribute(Qt::WA_PaintUnclipped, paintUnclipped); - - if (pe) - pe->setSystemClip(QRegion()); - -#if defined(Q_OS_UNIX) - ::usleep(1000 * msec); -#endif -#endif // !Q_OS_WIN -} - -bool QWidgetBackingStore::flushPaint(QWidget *widget, const QRegion &rgn) -{ - if (!widget) - return false; - - int delay = 0; - if (widget->testAttribute(Qt::WA_WState_InPaintEvent)) { - static int flushPaintEvent = qEnvironmentVariableIntValue("QT_FLUSH_PAINT_EVENT"); - if (!flushPaintEvent) - return false; - delay = flushPaintEvent; - } else { - static int flushPaint = qEnvironmentVariableIntValue("QT_FLUSH_PAINT"); - if (!flushPaint) - return false; - delay = flushPaint; - } + Q_ASSERT(store); - QWidgetBackingStore::showYellowThing(widget, rgn, delay * 10, true); - return true; + // Ensure all existing subsurfaces and static widgets are added to their respective lists. + updateLists(topLevel); } -void QWidgetBackingStore::unflushPaint(QWidget *widget, const QRegion &rgn) +void QWidgetRepaintManager::updateLists(QWidget *cur) { - if (widget->d_func()->paintOnScreen() || rgn.isEmpty()) - return; - - QWidget *tlw = widget->window(); - QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData(); - if (!tlwExtra) + if (!cur) return; - qt_flush(widget, rgn, tlwExtra->backingStoreTracker->store, tlw, 0, tlw->d_func()->maybeBackingStore()); -} -#endif // QT_NO_PAINT_DEBUG - -/* - Moves the whole rect by (dx, dy) in widget's coordinate system. - Doesn't generate any updates. -*/ -bool QWidgetBackingStore::bltRect(const QRect &rect, int dx, int dy, QWidget *widget) -{ - const QPoint pos(widget->mapTo(tlw, rect.topLeft())); - const QRect tlwRect(QRect(pos, rect.size())); - if (dirty.intersects(tlwRect)) - return false; // We don't want to scroll junk. - return store->scroll(tlwRect, dx, dy); -} - -/*! - Prepares the window surface to paint a\ toClean region of the \a widget and - updates the BeginPaintInfo struct accordingly. - - The \a toClean region might be clipped by the window surface. -*/ -void QWidgetBackingStore::beginPaint(QRegion &toClean, QWidget *widget, QBackingStore *backingStore, - BeginPaintInfo *returnInfo, bool toCleanIsInTopLevelCoordinates) -{ - Q_UNUSED(widget); - Q_UNUSED(toCleanIsInTopLevelCoordinates); - - // Always flush repainted areas. - dirtyOnScreen += toClean; - -#ifdef QT_NO_PAINT_DEBUG - backingStore->beginPaint(toClean); -#else - returnInfo->wasFlushed = QWidgetBackingStore::flushPaint(tlw, toClean); - // Avoid deadlock with QT_FLUSH_PAINT: the server will wait for - // the BackingStore lock, so if we hold that, the server will - // never release the Communication lock that we are waiting for in - // sendSynchronousCommand - if (!returnInfo->wasFlushed) - backingStore->beginPaint(toClean); -#endif - - Q_UNUSED(returnInfo); -} + QList<QObject*> children = cur->children(); + for (int i = 0; i < children.size(); ++i) { + QWidget *child = qobject_cast<QWidget*>(children.at(i)); + if (!child || child->isWindow()) + continue; -void QWidgetBackingStore::endPaint(const QRegion &cleaned, QBackingStore *backingStore, - BeginPaintInfo *beginPaintInfo) -{ -#ifndef QT_NO_PAINT_DEBUG - if (!beginPaintInfo->wasFlushed) - backingStore->endPaint(); - else - QWidgetBackingStore::unflushPaint(tlw, cleaned); -#else - Q_UNUSED(beginPaintInfo); - Q_UNUSED(cleaned); - backingStore->endPaint(); -#endif + updateLists(child); + } - flush(); + if (cur->testAttribute(Qt::WA_StaticContents)) + addStaticWidget(cur); } -/*! - Returns the region (in top-level coordinates) that needs repaint and/or flush. - - If the widget is non-zero, only the dirty region for the widget is returned - and the region will be in widget coordinates. -*/ -QRegion QWidgetBackingStore::dirtyRegion(QWidget *widget) const +QWidgetRepaintManager::~QWidgetRepaintManager() { - const bool widgetDirty = widget && widget != tlw; - const QRect tlwRect(topLevelRect()); - const QRect surfaceGeometry(tlwRect.topLeft(), store->size()); - if (surfaceGeometry != tlwRect && surfaceGeometry.size() != tlwRect.size()) { - if (widgetDirty) { - const QRect dirtyTlwRect = QRect(QPoint(), tlwRect.size()); - const QPoint offset(widget->mapTo(tlw, QPoint())); - const QRect dirtyWidgetRect(dirtyTlwRect & widget->rect().translated(offset)); - return dirtyWidgetRect.translated(-offset); - } - return QRect(QPoint(), tlwRect.size()); - } - - // Calculate the region that needs repaint. - QRegion r(dirty); - for (int i = 0; i < dirtyWidgets.size(); ++i) { - QWidget *w = dirtyWidgets.at(i); - if (widgetDirty && w != widget && !widget->isAncestorOf(w)) - continue; - r += w->d_func()->dirty.translated(w->mapTo(tlw, QPoint())); - } - - // Append the region that needs flush. - r += dirtyOnScreen; - - if (dirtyOnScreenWidgets) { // Only in use with native child widgets. - for (int i = 0; i < dirtyOnScreenWidgets->size(); ++i) { - QWidget *w = dirtyOnScreenWidgets->at(i); - if (widgetDirty && w != widget && !widget->isAncestorOf(w)) - continue; - QWidgetPrivate *wd = w->d_func(); - Q_ASSERT(wd->needsFlush); - r += wd->needsFlush->translated(w->mapTo(tlw, QPoint())); - } - } - - if (widgetDirty) { - // Intersect with the widget geometry and translate to its coordinates. - const QPoint offset(widget->mapTo(tlw, QPoint())); - r &= widget->rect().translated(offset); - r.translate(-offset); - } - return r; + for (int c = 0; c < dirtyWidgets.size(); ++c) + resetWidget(dirtyWidgets.at(c)); + for (int c = 0; c < dirtyRenderToTextureWidgets.size(); ++c) + resetWidget(dirtyRenderToTextureWidgets.at(c)); } /*! - Returns the static content inside the \a parent if non-zero; otherwise the static content - for the entire backing store is returned. The content will be clipped to \a withinClipRect - if non-empty. + Invalidates the \a r (in widget's coordinates) of the backing store, i.e. + all widgets intersecting with the region will be repainted when the backing + store is synced. */ -QRegion QWidgetBackingStore::staticContents(QWidget *parent, const QRect &withinClipRect) const +template <class T> +void QWidgetPrivate::invalidateBackingStore(const T &r) { - if (!parent && tlw->testAttribute(Qt::WA_StaticContents)) { - const QSize surfaceGeometry(store->size()); - QRect surfaceRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height()); - if (!withinClipRect.isEmpty()) - surfaceRect &= withinClipRect; - return QRegion(surfaceRect); - } - - QRegion region; - if (parent && parent->d_func()->children.isEmpty()) - return region; - - const bool clipToRect = !withinClipRect.isEmpty(); - const int count = staticWidgets.count(); - for (int i = 0; i < count; ++i) { - QWidget *w = staticWidgets.at(i); - QWidgetPrivate *wd = w->d_func(); - if (!wd->isOpaque || !wd->extra || wd->extra->staticContentsSize.isEmpty() - || !w->isVisible() || (parent && !parent->isAncestorOf(w))) { - continue; - } - - QRect rect(0, 0, wd->extra->staticContentsSize.width(), wd->extra->staticContentsSize.height()); - const QPoint offset = w->mapTo(parent ? parent : tlw, QPoint()); - if (clipToRect) - rect &= withinClipRect.translated(-offset); - if (rect.isEmpty()) - continue; - - rect &= wd->clipRect(); - if (rect.isEmpty()) - continue; + if (r.isEmpty()) + return; - QRegion visible(rect); - wd->clipToEffectiveMask(visible); - if (visible.isEmpty()) - continue; - wd->subtractOpaqueSiblings(visible, 0, /*alsoNonOpaque=*/true); + if (QCoreApplication::closingDown()) + return; - visible.translate(offset); - region += visible; - } + Q_Q(QWidget); + if (!q->isVisible() || !q->updatesEnabled()) + return; - return region; -} + QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); + if (!tlwExtra || tlwExtra->inTopLevelResize || !tlwExtra->backingStore) + return; -void QWidgetBackingStore::sendUpdateRequest(QWidget *widget, UpdateTime updateTime) -{ - if (!widget) + T clipped(r); + clipped &= clipRect(); + if (clipped.isEmpty()) return; -#ifndef QT_NO_OPENGL - // Having every repaint() leading to a sync/flush is bad as it causes - // compositing and waiting for vsync each and every time. Change to - // UpdateLater, except for approx. once per frame to prevent starvation in - // case the control does not get back to the event loop. - QWidget *w = widget->window(); - if (updateTime == UpdateNow && w && w->windowHandle() && QWindowPrivate::get(w->windowHandle())->compositing) { - int refresh = 60; - QScreen *ws = w->windowHandle()->screen(); - if (ws) - refresh = ws->refreshRate(); - QWindowPrivate *wd = QWindowPrivate::get(w->windowHandle()); - if (wd->lastComposeTime.isValid()) { - const qint64 elapsed = wd->lastComposeTime.elapsed(); - if (elapsed <= qint64(1000.0f / refresh)) - updateTime = UpdateLater; - } - } -#endif + if (!graphicsEffect && extra && extra->hasMask) { + QRegion masked(extra->mask); + masked &= clipped; + if (masked.isEmpty()) + return; - switch (updateTime) { - case UpdateLater: - updateRequestSent = true; - QCoreApplication::postEvent(widget, new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority); - break; - case UpdateNow: { - QEvent event(QEvent::UpdateRequest); - QCoreApplication::sendEvent(widget, &event); - break; - } + tlwExtra->repaintManager->markDirty(masked, q, + QWidgetRepaintManager::UpdateLater, QWidgetRepaintManager::BufferInvalid); + } else { + tlwExtra->repaintManager->markDirty(clipped, q, + QWidgetRepaintManager::UpdateLater, QWidgetRepaintManager::BufferInvalid); } } +// Needed by tst_QWidget +template Q_AUTOTEST_EXPORT void QWidgetPrivate::invalidateBackingStore<QRect>(const QRect &r); static inline QRect widgetRectFor(QWidget *, const QRect &r) { return r; } static inline QRect widgetRectFor(QWidget *widget, const QRegion &) { return widget->rect(); } @@ -516,8 +204,11 @@ static inline QRect widgetRectFor(QWidget *widget, const QRegion &) { return wid instead of the top-level widget, and bufferState is completely ignored. */ template <class T> -void QWidgetBackingStore::markDirty(const T &r, QWidget *widget, UpdateTime updateTime, BufferState bufferState) +void QWidgetRepaintManager::markDirty(const T &r, QWidget *widget, UpdateTime updateTime, BufferState bufferState) { + qCInfo(lcWidgetPainting) << "Marking" << r << "of" << widget << "dirty" + << "with" << updateTime; + Q_ASSERT(tlw->d_func()->extra); Q_ASSERT(tlw->d_func()->extra->topextra); Q_ASSERT(!tlw->d_func()->extra->topextra->inTopLevelResize); @@ -533,7 +224,7 @@ void QWidgetBackingStore::markDirty(const T &r, QWidget *widget, UpdateTime upda // --------------------------------------------------------------------------- - if (widget->d_func()->paintOnScreen()) { + if (widget->d_func()->shouldPaintOnScreen()) { if (widget->d_func()->dirty.isEmpty()) { widget->d_func()->dirty = r; sendUpdateRequest(widget, updateTime); @@ -620,70 +311,35 @@ void QWidgetBackingStore::markDirty(const T &r, QWidget *widget, UpdateTime upda if (updateTime == UpdateNow) sendUpdateRequest(tlw, updateTime); } -template void QWidgetBackingStore::markDirty<QRect>(const QRect &, QWidget *, UpdateTime, BufferState); -template void QWidgetBackingStore::markDirty<QRegion>(const QRegion &, QWidget *, UpdateTime, BufferState); - -/*! - Marks the \a region of the \a widget as dirty on screen. The \a region will be copied from - the backing store to the \a widget's native parent next time flush() is called. +template void QWidgetRepaintManager::markDirty<QRect>(const QRect &, QWidget *, UpdateTime, BufferState); +template void QWidgetRepaintManager::markDirty<QRegion>(const QRegion &, QWidget *, UpdateTime, BufferState); - Paint on screen widgets are ignored. -*/ -void QWidgetBackingStore::markDirtyOnScreen(const QRegion ®ion, QWidget *widget, const QPoint &topLevelOffset) +void QWidgetRepaintManager::addDirtyWidget(QWidget *widget, const QRegion &rgn) { - if (!widget || widget->d_func()->paintOnScreen() || region.isEmpty()) - return; - -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (!widget->testAttribute(Qt::WA_WState_InPaintEvent)) - dirtyOnScreen += region.translated(topLevelOffset); - return; -#endif - - // Top-level. - if (widget == tlw) { - if (!widget->testAttribute(Qt::WA_WState_InPaintEvent)) - dirtyOnScreen += region; - return; - } - - // Alien widgets. - if (!widget->internalWinId() && !widget->isWindow()) { - QWidget *nativeParent = widget->nativeParentWidget(); // Alien widgets with the top-level as the native parent (common case). - if (nativeParent == tlw) { - if (!widget->testAttribute(Qt::WA_WState_InPaintEvent)) - dirtyOnScreen += region.translated(topLevelOffset); - return; - } - - // Alien widgets with native parent != tlw. - QWidgetPrivate *nativeParentPrivate = nativeParent->d_func(); - if (!nativeParentPrivate->needsFlush) - nativeParentPrivate->needsFlush = new QRegion; - const QPoint nativeParentOffset = widget->mapTo(nativeParent, QPoint()); - *nativeParentPrivate->needsFlush += region.translated(nativeParentOffset); - appendDirtyOnScreenWidget(nativeParent); - return; + if (widget && !widget->d_func()->inDirtyList && !widget->data->in_destructor) { + QWidgetPrivate *widgetPrivate = widget->d_func(); +#if QT_CONFIG(graphicseffect) + if (widgetPrivate->graphicsEffect) + widgetPrivate->dirty = widgetPrivate->effectiveRectFor(rgn.boundingRect()); + else +#endif // QT_CONFIG(graphicseffect) + widgetPrivate->dirty = rgn; + dirtyWidgets.append(widget); + widgetPrivate->inDirtyList = true; } - - // Native child widgets. - QWidgetPrivate *widgetPrivate = widget->d_func(); - if (!widgetPrivate->needsFlush) - widgetPrivate->needsFlush = new QRegion; - *widgetPrivate->needsFlush += region; - appendDirtyOnScreenWidget(widget); } -void QWidgetBackingStore::removeDirtyWidget(QWidget *w) +void QWidgetRepaintManager::removeDirtyWidget(QWidget *w) { if (!w) return; - dirtyWidgetsRemoveAll(w); - dirtyOnScreenWidgetsRemoveAll(w); + dirtyWidgets.removeAll(w); dirtyRenderToTextureWidgets.removeAll(w); resetWidget(w); + needsFlushWidgets.removeAll(w); + QWidgetPrivate *wd = w->d_func(); const int n = wd->children.count(); for (int i = 0; i < n; ++i) { @@ -692,46 +348,71 @@ void QWidgetBackingStore::removeDirtyWidget(QWidget *w) } } -void QWidgetBackingStore::updateLists(QWidget *cur) +void QWidgetRepaintManager::resetWidget(QWidget *widget) { - if (!cur) - return; - - QList<QObject*> children = cur->children(); - for (int i = 0; i < children.size(); ++i) { - QWidget *child = qobject_cast<QWidget*>(children.at(i)); - if (!child || child->isWindow()) - continue; - - updateLists(child); + if (widget) { + widget->d_func()->inDirtyList = false; + widget->d_func()->isScrolled = false; + widget->d_func()->isMoved = false; + widget->d_func()->dirty = QRegion(); } +} - if (cur->testAttribute(Qt::WA_StaticContents)) - addStaticWidget(cur); +void QWidgetRepaintManager::addDirtyRenderToTextureWidget(QWidget *widget) +{ + if (widget && !widget->d_func()->inDirtyList && !widget->data->in_destructor) { + QWidgetPrivate *widgetPrivate = widget->d_func(); + Q_ASSERT(widgetPrivate->renderToTexture); + dirtyRenderToTextureWidgets.append(widget); + widgetPrivate->inDirtyList = true; + } } -QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel) - : tlw(topLevel), - dirtyOnScreenWidgets(0), - updateRequestSent(0), - textureListWatcher(0), - perfFrames(0) +void QWidgetRepaintManager::sendUpdateRequest(QWidget *widget, UpdateTime updateTime) { - store = tlw->backingStore(); - Q_ASSERT(store); + if (!widget) + return; - // Ensure all existing subsurfaces and static widgets are added to their respective lists. - updateLists(topLevel); + qCInfo(lcWidgetPainting) << "Sending update request to" << widget << "with" << updateTime; + +#ifndef QT_NO_OPENGL + // Having every repaint() leading to a sync/flush is bad as it causes + // compositing and waiting for vsync each and every time. Change to + // UpdateLater, except for approx. once per frame to prevent starvation in + // case the control does not get back to the event loop. + QWidget *w = widget->window(); + if (updateTime == UpdateNow && w && w->windowHandle() && QWindowPrivate::get(w->windowHandle())->compositing) { + int refresh = 60; + QScreen *ws = w->windowHandle()->screen(); + if (ws) + refresh = ws->refreshRate(); + QWindowPrivate *wd = QWindowPrivate::get(w->windowHandle()); + if (wd->lastComposeTime.isValid()) { + const qint64 elapsed = wd->lastComposeTime.elapsed(); + if (elapsed <= qint64(1000.0f / refresh)) + updateTime = UpdateLater; + } + } +#endif + + switch (updateTime) { + case UpdateLater: + updateRequestSent = true; + QCoreApplication::postEvent(widget, new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority); + break; + case UpdateNow: { + QEvent event(QEvent::UpdateRequest); + QCoreApplication::sendEvent(widget, &event); + break; + } + } } -QWidgetBackingStore::~QWidgetBackingStore() -{ - for (int c = 0; c < dirtyWidgets.size(); ++c) - resetWidget(dirtyWidgets.at(c)); - for (int c = 0; c < dirtyRenderToTextureWidgets.size(); ++c) - resetWidget(dirtyRenderToTextureWidgets.at(c)); +// --------------------------------------------------------------------------- - delete dirtyOnScreenWidgets; +static bool hasPlatformWindow(QWidget *widget) +{ + return widget && widget->windowHandle() && widget->windowHandle()->handle(); } static QVector<QRect> getSortedRectsToScroll(const QRegion ®ion, int dx, int dy) @@ -778,7 +459,7 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) destRect = destRect.translated(dx, dy).intersected(clipR); const QRect sourceRect(destRect.translated(-dx, -dy)); const QRect parentRect(rect & clipR); - const bool nativeWithTextureChild = textureChildSeen && q->internalWinId(); + const bool nativeWithTextureChild = textureChildSeen && hasPlatformWindow(q); const bool accelerateMove = accelEnv && isOpaque && !nativeWithTextureChild #if QT_CONFIG(graphicsview) @@ -799,7 +480,7 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) invalidateBackingStore((newRect & clipR).translated(-data.crect.topLeft())); } else { - QWidgetBackingStore *wbs = x->backingStoreTracker.data(); + QWidgetRepaintManager *repaintManager = x->repaintManager.get(); QRegion childExpose(newRect & clipR); QRegion overlappedExpose; @@ -811,7 +492,7 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) const QVector<QRect> rectsToScroll = getSortedRectsToScroll(QRegion(sourceRect) - overlappedExpose, dx, dy); for (QRect rect : rectsToScroll) { - if (wbs->bltRect(rect, dx, dy, pw)) { + if (repaintManager->bltRect(rect, dx, dy, pw)) { childExpose -= rect.translated(dx, dy); } } @@ -831,7 +512,7 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) } if (!childExpose.isEmpty()) { childExpose.translate(-data.crect.topLeft()); - wbs->markDirty(childExpose, q); + repaintManager->markDirty(childExpose, q); isMoved = true; } } @@ -842,14 +523,14 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) parentExpose += QRegion(newRect) - extra->mask.translated(data.crect.topLeft()); if (!parentExpose.isEmpty()) { - wbs->markDirty(parentExpose, pw); + repaintManager->markDirty(parentExpose, pw); pd->isMoved = true; } if (childUpdatesEnabled) { QRegion needsFlush(sourceRect); needsFlush += destRect; - wbs->markDirtyOnScreen(needsFlush, pw, toplevelOffset); + repaintManager->markNeedsFlush(pw, needsFlush, toplevelOffset); } } } @@ -863,8 +544,8 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy) if (x->inTopLevelResize) return; - QWidgetBackingStore *wbs = x->backingStoreTracker.data(); - if (!wbs) + QWidgetRepaintManager *repaintManager = x->repaintManager.get(); + if (!repaintManager) return; static const bool accelEnv = qEnvironmentVariableIntValue("QT_NO_FAST_SCROLL") == 0; @@ -895,7 +576,7 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy) const QVector<QRect> rectsToScroll = getSortedRectsToScroll(QRegion(sourceRect) - overlappedExpose, dx, dy); for (const QRect &rect : rectsToScroll) { - if (wbs->bltRect(rect, dx, dy, q)) { + if (repaintManager->bltRect(rect, dx, dy, q)) { childExpose -= rect.translated(dx, dy); } } @@ -922,17 +603,32 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy) if (!overlappedExpose.isEmpty()) invalidateBackingStore(overlappedExpose); if (!childExpose.isEmpty()) { - wbs->markDirty(childExpose, q); + repaintManager->markDirty(childExpose, q); isScrolled = true; } // Instead of using native scroll-on-screen, we copy from // backingstore, giving only one screen update for each // scroll, and a solid appearance - wbs->markDirtyOnScreen(destRect, q, toplevelOffset); + repaintManager->markNeedsFlush(q, destRect, toplevelOffset); } } +/* + Moves the whole rect by (dx, dy) in widget's coordinate system. + Doesn't generate any updates. +*/ +bool QWidgetRepaintManager::bltRect(const QRect &rect, int dx, int dy, QWidget *widget) +{ + const QPoint pos(widget->mapTo(tlw, rect.topLeft())); + const QRect tlwRect(QRect(pos, rect.size())); + if (dirty.intersects(tlwRect)) + return false; // We don't want to scroll junk. + return store->scroll(tlwRect, dx, dy); +} + +// --------------------------------------------------------------------------- + #ifndef QT_NO_OPENGL static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatformTextureList *widgetTextures, QVector<QWidget *> *nativeChildren) { @@ -946,9 +642,9 @@ static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatfo for (int i = 0; i < wd->children.size(); ++i) { QWidget *w = qobject_cast<QWidget *>(wd->children.at(i)); // Stop at native widgets but store them. Stop at hidden widgets too. - if (w && !w->isWindow() && w->internalWinId()) + if (w && !w->isWindow() && hasPlatformWindow(w)) nativeChildren->append(w); - if (w && !w->isWindow() && !w->internalWinId() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen) + if (w && !w->isWindow() && !hasPlatformWindow(w) && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen) findTextureWidgetsRecursively(tlw, w, widgetTextures, nativeChildren); } } @@ -958,15 +654,15 @@ static void findAllTextureWidgetsRecursively(QWidget *tlw, QWidget *widget) // textureChildSeen does not take native child widgets into account and that's good. if (QWidgetPrivate::get(widget)->textureChildSeen) { QVector<QWidget *> nativeChildren; - QScopedPointer<QPlatformTextureList> tl(new QPlatformTextureList); + auto tl = qt_make_unique<QPlatformTextureList>(); // Look for texture widgets (incl. widget itself) from 'widget' down, // but skip subtrees with a parent of a native child widget. - findTextureWidgetsRecursively(tlw, widget, tl.data(), &nativeChildren); + findTextureWidgetsRecursively(tlw, widget, tl.get(), &nativeChildren); // tl may be empty regardless of textureChildSeen if we have native or hidden children. if (!tl->isEmpty()) - QWidgetPrivate::get(tlw)->topData()->widgetTextures.append(tl.take()); + QWidgetPrivate::get(tlw)->topData()->widgetTextures.push_back(std::move(tl)); // Native child widgets, if there was any, get their own separate QPlatformTextureList. - foreach (QWidget *ncw, nativeChildren) { + for (QWidget *ncw : qAsConst(nativeChildren)) { if (QWidgetPrivate::get(ncw)->textureChildSeen) findAllTextureWidgetsRecursively(tlw, ncw); } @@ -975,12 +671,12 @@ static void findAllTextureWidgetsRecursively(QWidget *tlw, QWidget *widget) static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget) { - foreach (QPlatformTextureList *tl, QWidgetPrivate::get(tlw)->topData()->widgetTextures) { + for (const auto &tl : QWidgetPrivate::get(tlw)->topData()->widgetTextures) { Q_ASSERT(!tl->isEmpty()); for (int i = 0; i < tl->count(); ++i) { QWidget *w = static_cast<QWidget *>(tl->source(i)); - if ((w->internalWinId() && w == widget) || (!w->internalWinId() && w->nativeParentWidget() == widget)) - return tl; + if ((hasPlatformWindow(w) && w == widget) || (!hasPlatformWindow(w) && w->nativeParentWidget() == widget)) + return tl.get(); } } @@ -1000,39 +696,6 @@ static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget) return 0; } -// Watches one or more QPlatformTextureLists for changes in the lock state and -// triggers a backingstore sync when all the registered lists turn into -// unlocked state. This is essential when a custom composeAndFlush() -// implementation in a platform plugin is not synchronous and keeps -// holding on to the textures for some time even after returning from there. -QPlatformTextureListWatcher::QPlatformTextureListWatcher(QWidgetBackingStore *backingStore) - : m_backingStore(backingStore) -{ -} - -void QPlatformTextureListWatcher::watch(QPlatformTextureList *textureList) -{ - connect(textureList, SIGNAL(locked(bool)), SLOT(onLockStatusChanged(bool))); - m_locked[textureList] = textureList->isLocked(); -} - -bool QPlatformTextureListWatcher::isLocked() const -{ - foreach (bool v, m_locked) { - if (v) - return true; - } - return false; -} - -void QPlatformTextureListWatcher::onLockStatusChanged(bool locked) -{ - QPlatformTextureList *tl = static_cast<QPlatformTextureList *>(sender()); - m_locked[tl] = locked; - if (!isLocked()) - m_backingStore->sync(); -} - #else static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget) @@ -1044,81 +707,55 @@ static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget) #endif // QT_NO_OPENGL -static inline bool discardSyncRequest(QWidget *tlw, QTLWExtra *tlwExtra) -{ - if (!tlw || !tlwExtra || !tlw->testAttribute(Qt::WA_Mapped) || !tlw->isVisible()) - return true; - - return false; -} - -bool QWidgetBackingStore::syncAllowed() -{ -#ifndef QT_NO_OPENGL - QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData(); - if (textureListWatcher && !textureListWatcher->isLocked()) { - textureListWatcher->deleteLater(); - textureListWatcher = 0; - } else if (!tlwExtra->widgetTextures.isEmpty()) { - bool skipSync = false; - foreach (QPlatformTextureList *tl, tlwExtra->widgetTextures) { - if (tl->isLocked()) { - if (!textureListWatcher) - textureListWatcher = new QPlatformTextureListWatcher(this); - if (!textureListWatcher->isLocked()) - textureListWatcher->watch(tl); - skipSync = true; - } - } - if (skipSync) // cannot compose due to widget textures being in use - return false; - } -#endif - return true; -} +// --------------------------------------------------------------------------- /*! Synchronizes the \a exposedRegion of the \a exposedWidget with the backing store. - If there's nothing to repaint, the area is flushed and painting does not occur; - otherwise the area is marked as dirty on screen and will be flushed right after - we are done with all painting. + If there are dirty widgets, including but not limited to the \a exposedWidget, + these will be repainted first. The backingstore is then flushed to the screen, + regardless of whether or not there were any repaints. */ -void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedRegion) +void QWidgetRepaintManager::sync(QWidget *exposedWidget, const QRegion &exposedRegion) { + qCInfo(lcWidgetPainting) << "Syncing" << exposedRegion << "of" << exposedWidget; + QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData(); if (!tlw->isVisible() || !tlwExtra || tlwExtra->inTopLevelResize) return; - if (!exposedWidget || !exposedWidget->internalWinId() || !exposedWidget->isVisible() || !exposedWidget->testAttribute(Qt::WA_Mapped) + if (!exposedWidget || !hasPlatformWindow(exposedWidget) + || !exposedWidget->isVisible() || !exposedWidget->testAttribute(Qt::WA_Mapped) || !exposedWidget->updatesEnabled() || exposedRegion.isEmpty()) { return; } // Nothing to repaint. if (!isDirty() && store->size().isValid()) { - QPlatformTextureList *tl = widgetTexturesFor(tlw, exposedWidget); - qt_flush(exposedWidget, tl ? QRegion() : exposedRegion, store, tlw, tl, this); + QPlatformTextureList *widgetTextures = widgetTexturesFor(tlw, exposedWidget); + flush(exposedWidget, widgetTextures ? QRegion() : exposedRegion, widgetTextures); return; } - if (exposedWidget != tlw) - markDirtyOnScreen(exposedRegion, exposedWidget, exposedWidget->mapTo(tlw, QPoint())); - else - markDirtyOnScreen(exposedRegion, exposedWidget, QPoint()); + // As requests to sync a specific widget typically comes from an expose event + // we can't rely solely on our own dirty tracking to decide what to flush, and + // need to respect the platform's request to at least flush the entire widget, + QPoint offset = exposedWidget != tlw ? exposedWidget->mapTo(tlw, QPoint()) : QPoint(); + markNeedsFlush(exposedWidget, exposedRegion, offset); if (syncAllowed()) - doSync(); + paintAndFlush(); } /*! Synchronizes the backing store, i.e. dirty areas are repainted and flushed. */ -void QWidgetBackingStore::sync() +void QWidgetRepaintManager::sync() { + qCInfo(lcWidgetPainting) << "Syncing dirty widgets"; + updateRequestSent = false; - QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData(); - if (discardSyncRequest(tlw, tlwExtra)) { + if (qt_widget_private(tlw)->shouldDiscardSyncRequest()) { // If the top-level is minimized, it's not visible on the screen so we can delay the // update until it's shown again. In order to do that we must keep the dirty states. // These will be cleared when we receive the first expose after showNormal(). @@ -1134,16 +771,50 @@ void QWidgetBackingStore::sync() } if (syncAllowed()) - doSync(); + paintAndFlush(); +} + +bool QWidgetPrivate::shouldDiscardSyncRequest() const +{ + Q_Q(const QWidget); + return !maybeTopData() || !q->testAttribute(Qt::WA_Mapped) || !q->isVisible(); +} + +bool QWidgetRepaintManager::syncAllowed() +{ +#ifndef QT_NO_OPENGL + QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData(); + if (textureListWatcher && !textureListWatcher->isLocked()) { + textureListWatcher->deleteLater(); + textureListWatcher = 0; + } else if (!tlwExtra->widgetTextures.empty()) { + bool skipSync = false; + for (const auto &tl : tlwExtra->widgetTextures) { + if (tl->isLocked()) { + if (!textureListWatcher) + textureListWatcher = new QPlatformTextureListWatcher(this); + if (!textureListWatcher->isLocked()) + textureListWatcher->watch(tl.get()); + skipSync = true; + } + } + if (skipSync) // cannot compose due to widget textures being in use + return false; + } +#endif + return true; } -void QWidgetBackingStore::doSync() +void QWidgetRepaintManager::paintAndFlush() { + qCInfo(lcWidgetPainting) << "Painting and flushing dirty" + << "top level" << dirty << "and dirty widgets" << dirtyWidgets; + const bool updatesDisabled = !tlw->updatesEnabled(); bool repaintAllWidgets = false; const bool inTopLevelResize = tlw->d_func()->maybeTopData()->inTopLevelResize; - const QRect tlwRect(topLevelRect()); + const QRect tlwRect = tlw->data->crect; const QRect surfaceGeometry(tlwRect.topLeft(), store->size()); if ((inTopLevelResize || surfaceGeometry.size() != tlwRect.size()) && !updatesDisabled) { if (hasStaticContents() && !store->size().isEmpty() ) { @@ -1237,10 +908,9 @@ void QWidgetBackingStore::doSync() // The search is cut at native widget boundaries, meaning that each native child widget // has its own list for the subtree below it. QTLWExtra *tlwExtra = tlw->d_func()->topData(); - qDeleteAll(tlwExtra->widgetTextures); tlwExtra->widgetTextures.clear(); findAllTextureWidgetsRecursively(tlw, tlw); - qt_window_private(tlw->windowHandle())->compositing = false; // will get updated in qt_flush() + qt_window_private(tlw->windowHandle())->compositing = false; // will get updated in flush() #endif if (toClean.isEmpty()) { @@ -1263,13 +933,10 @@ void QWidgetBackingStore::doSync() w->d_func()->sendPaintEvent(w->rect()); if (w != tlw) { QWidget *npw = w->nativeParentWidget(); - if (w->internalWinId() || (npw && npw != tlw)) { - if (!w->internalWinId()) + if (hasPlatformWindow(w) || (npw && npw != tlw)) { + if (!hasPlatformWindow(w)) w = npw; - QWidgetPrivate *wPrivate = w->d_func(); - if (!wPrivate->needsFlush) - wPrivate->needsFlush = new QRegion; - appendDirtyOnScreenWidget(w); + markNeedsFlush(w); } } } @@ -1283,7 +950,7 @@ void QWidgetBackingStore::doSync() } #ifndef QT_NO_OPENGL - foreach (QPlatformTextureList *tl, tlwExtra->widgetTextures) { + for (const auto &tl : tlwExtra->widgetTextures) { for (int i = 0; i < tl->count(); ++i) { QWidget *w = static_cast<QWidget *>(tl->source(i)); if (dirtyRenderToTextureWidgets.contains(w)) { @@ -1312,15 +979,7 @@ void QWidgetBackingStore::doSync() } #endif - BeginPaintInfo beginPaintInfo; - beginPaint(toClean, tlw, store, &beginPaintInfo); - if (beginPaintInfo.nothingToPaint) { - for (int i = 0; i < opaqueNonOverlappedWidgets.size(); ++i) - resetWidget(opaqueNonOverlappedWidgets[i]); - dirty = QRegion(); - updateRequestSent = false; - return; - } + store->beginPaint(toClean); // Must do this before sending any paint events because // the size may change in the paint event. @@ -1334,7 +993,7 @@ void QWidgetBackingStore::doSync() QWidget *w = opaqueNonOverlappedWidgets[i]; QWidgetPrivate *wd = w->d_func(); - int flags = QWidgetPrivate::DrawRecursive; + QWidgetPrivate::DrawWidgetFlags flags = QWidgetPrivate::DrawRecursive; // Scrolled and moved widgets must draw all children. if (!wd->isScrolled && !wd->isMoved) flags |= QWidgetPrivate::DontDrawOpaqueChildren; @@ -1352,56 +1011,301 @@ void QWidgetBackingStore::doSync() // Paint the rest with composition. if (repaintAllWidgets || !dirtyCopy.isEmpty()) { - const int flags = QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawRecursive; + QWidgetPrivate::DrawWidgetFlags flags = QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawRecursive; tlw->d_func()->drawWidget(store->paintDevice(), dirtyCopy, QPoint(), flags, 0, this); } - endPaint(toClean, store, &beginPaintInfo); + store->endPaint(); + + flush(); +} + +/*! + Marks the \a region of the \a widget as needing a flush. The \a region will be copied from + the backing store to the \a widget's native parent next time flush() is called. + + Paint on screen widgets are ignored. +*/ +void QWidgetRepaintManager::markNeedsFlush(QWidget *widget, const QRegion ®ion, const QPoint &topLevelOffset) +{ + if (!widget || widget->d_func()->shouldPaintOnScreen() || region.isEmpty()) + return; + + if (widget == tlw) { + // Top-level (native) + qCInfo(lcWidgetPainting) << "Marking" << region << "of top level" + << widget << "as needing flush"; + topLevelNeedsFlush += region; + } else if (!hasPlatformWindow(widget) && !widget->isWindow()) { + QWidget *nativeParent = widget->nativeParentWidget(); + qCInfo(lcWidgetPainting) << "Marking" << region << "of" + << widget << "as needing flush in" << nativeParent + << "at offset" << topLevelOffset; + if (nativeParent == tlw) { + // Alien widgets with the top-level as the native parent (common case) + topLevelNeedsFlush += region.translated(topLevelOffset); + } else { + // Alien widgets with native parent != tlw + const QPoint nativeParentOffset = widget->mapTo(nativeParent, QPoint()); + markNeedsFlush(nativeParent, region.translated(nativeParentOffset)); + } + } else { + // Native child widgets + qCInfo(lcWidgetPainting) << "Marking" << region + << "of native child" << widget << "as needing flush"; + markNeedsFlush(widget, region); + } +} + +void QWidgetRepaintManager::markNeedsFlush(QWidget *widget, const QRegion ®ion) +{ + if (!widget) + return; + + auto *widgetPrivate = qt_widget_private(widget); + if (!widgetPrivate->needsFlush) + widgetPrivate->needsFlush = new QRegion; + + *widgetPrivate->needsFlush += region; + + if (!needsFlushWidgets.contains(widget)) + needsFlushWidgets.append(widget); } /*! Flushes the contents of the backing store into the top-level widget. - If the \a widget is non-zero, the content is flushed to the \a widget. - If the \a surface is non-zero, the content of the \a surface is flushed. */ -void QWidgetBackingStore::flush(QWidget *widget) +void QWidgetRepaintManager::flush() { - const bool hasDirtyOnScreenWidgets = dirtyOnScreenWidgets && !dirtyOnScreenWidgets->isEmpty(); + qCInfo(lcWidgetPainting) << "Flushing top level" + << topLevelNeedsFlush << "and children" << needsFlushWidgets; + + const bool hasNeedsFlushWidgets = !needsFlushWidgets.isEmpty(); bool flushed = false; - // Flush the region in dirtyOnScreen. - if (!dirtyOnScreen.isEmpty()) { - QWidget *target = widget ? widget : tlw; - qt_flush(target, dirtyOnScreen, store, tlw, widgetTexturesFor(tlw, tlw), this); - dirtyOnScreen = QRegion(); + // Flush the top level widget + if (!topLevelNeedsFlush.isEmpty()) { + flush(tlw, topLevelNeedsFlush, widgetTexturesFor(tlw, tlw)); + topLevelNeedsFlush = QRegion(); flushed = true; } - // Render-to-texture widgets are not in dirtyOnScreen so flush if we have not done it above. - if (!flushed && !hasDirtyOnScreenWidgets) { + // Render-to-texture widgets are not in topLevelNeedsFlush so flush if we have not done it above. + if (!flushed && !hasNeedsFlushWidgets) { #ifndef QT_NO_OPENGL - if (!tlw->d_func()->topData()->widgetTextures.isEmpty()) { - QPlatformTextureList *tl = widgetTexturesFor(tlw, tlw); - if (tl) { - QWidget *target = widget ? widget : tlw; - qt_flush(target, QRegion(), store, tlw, tl, this); - } + if (!tlw->d_func()->topData()->widgetTextures.empty()) { + if (QPlatformTextureList *widgetTextures = widgetTexturesFor(tlw, tlw)) + flush(tlw, QRegion(), widgetTextures); } #endif } - if (!hasDirtyOnScreenWidgets) + if (!hasNeedsFlushWidgets) return; - for (int i = 0; i < dirtyOnScreenWidgets->size(); ++i) { - QWidget *w = dirtyOnScreenWidgets->at(i); + for (QWidget *w : qExchange(needsFlushWidgets, {})) { QWidgetPrivate *wd = w->d_func(); Q_ASSERT(wd->needsFlush); QPlatformTextureList *widgetTexturesForNative = wd->textureChildSeen ? widgetTexturesFor(tlw, w) : 0; - qt_flush(w, *wd->needsFlush, store, tlw, widgetTexturesForNative, this); + flush(w, *wd->needsFlush, widgetTexturesForNative); *wd->needsFlush = QRegion(); } - dirtyOnScreenWidgets->clear(); +} + +/* + Flushes the contents of the backingstore into the screen area of \a widget. + + \a region is the region to be updated in \a widget coordinates. + */ +void QWidgetRepaintManager::flush(QWidget *widget, const QRegion ®ion, QPlatformTextureList *widgetTextures) +{ +#ifdef QT_NO_OPENGL + Q_UNUSED(widgetTextures); + Q_ASSERT(!region.isEmpty()); +#else + Q_ASSERT(!region.isEmpty() || widgetTextures); +#endif + Q_ASSERT(widget); + Q_ASSERT(tlw); + + if (tlw->testAttribute(Qt::WA_DontShowOnScreen) || widget->testAttribute(Qt::WA_DontShowOnScreen)) + return; + + // Foreign Windows do not have backing store content and must not be flushed + if (QWindow *widgetWindow = widget->windowHandle()) { + if (widgetWindow->type() == Qt::ForeignWindow) + return; + } + + qCInfo(lcWidgetPainting) << "Flushing" << region << "of" << widget; + + static bool fpsDebug = qEnvironmentVariableIntValue("QT_DEBUG_FPS"); + if (fpsDebug) { + if (!perfFrames++) + perfTime.start(); + if (perfTime.elapsed() > 5000) { + double fps = double(perfFrames * 1000) / perfTime.restart(); + qDebug("FPS: %.1f\n", fps); + perfFrames = 0; + } + } + + QPoint offset; + if (widget != tlw) + offset += widget->mapTo(tlw, QPoint()); + + QRegion effectiveRegion = region; +#ifndef QT_NO_OPENGL + const bool compositionWasActive = widget->d_func()->renderToTextureComposeActive; + if (!widgetTextures) { + widget->d_func()->renderToTextureComposeActive = false; + // Detect the case of falling back to the normal flush path when no + // render-to-texture widgets are visible anymore. We will force one + // last flush to go through the OpenGL-based composition to prevent + // artifacts. The next flush after this one will use the normal path. + if (compositionWasActive) + widgetTextures = qt_dummy_platformTextureList; + } else { + widget->d_func()->renderToTextureComposeActive = true; + } + // When changing the composition status, make sure the dirty region covers + // the entire widget. Just having e.g. the shown/hidden render-to-texture + // widget's area marked as dirty is incorrect when changing flush paths. + if (compositionWasActive != widget->d_func()->renderToTextureComposeActive) + effectiveRegion = widget->rect(); + + // re-test since we may have been forced to this path via the dummy texture list above + if (widgetTextures) { + qt_window_private(tlw->windowHandle())->compositing = true; + widget->window()->d_func()->sendComposeStatus(widget->window(), false); + // A window may have alpha even when the app did not request + // WA_TranslucentBackground. Therefore the compositor needs to know whether the app intends + // to rely on translucency, in order to decide if it should clear to transparent or opaque. + const bool translucentBackground = widget->testAttribute(Qt::WA_TranslucentBackground); + store->handle()->composeAndFlush(widget->windowHandle(), effectiveRegion, offset, + widgetTextures, translucentBackground); + widget->window()->d_func()->sendComposeStatus(widget->window(), true); + } else +#endif + store->flush(effectiveRegion, widget->windowHandle(), offset); +} + +// --------------------------------------------------------------------------- + +void QWidgetRepaintManager::addStaticWidget(QWidget *widget) +{ + if (!widget) + return; + + Q_ASSERT(widget->testAttribute(Qt::WA_StaticContents)); + if (!staticWidgets.contains(widget)) + staticWidgets.append(widget); +} + +// Move the reparented widget and all its static children from this backing store +// to the new backing store if reparented into another top-level / backing store. +void QWidgetRepaintManager::moveStaticWidgets(QWidget *reparented) +{ + Q_ASSERT(reparented); + QWidgetRepaintManager *newPaintManager = reparented->d_func()->maybeRepaintManager(); + if (newPaintManager == this) + return; + + int i = 0; + while (i < staticWidgets.size()) { + QWidget *w = staticWidgets.at(i); + if (reparented == w || reparented->isAncestorOf(w)) { + staticWidgets.removeAt(i); + if (newPaintManager) + newPaintManager->addStaticWidget(w); + } else { + ++i; + } + } +} + +void QWidgetRepaintManager::removeStaticWidget(QWidget *widget) +{ + staticWidgets.removeAll(widget); +} + +bool QWidgetRepaintManager::hasStaticContents() const +{ +#if defined(Q_OS_WIN) + return !staticWidgets.isEmpty(); +#else + return !staticWidgets.isEmpty() && false; +#endif +} + +/*! + Returns the static content inside the \a parent if non-zero; otherwise the static content + for the entire backing store is returned. The content will be clipped to \a withinClipRect + if non-empty. +*/ +QRegion QWidgetRepaintManager::staticContents(QWidget *parent, const QRect &withinClipRect) const +{ + if (!parent && tlw->testAttribute(Qt::WA_StaticContents)) { + const QSize surfaceGeometry(store->size()); + QRect surfaceRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height()); + if (!withinClipRect.isEmpty()) + surfaceRect &= withinClipRect; + return QRegion(surfaceRect); + } + + QRegion region; + if (parent && parent->d_func()->children.isEmpty()) + return region; + + const bool clipToRect = !withinClipRect.isEmpty(); + const int count = staticWidgets.count(); + for (int i = 0; i < count; ++i) { + QWidget *w = staticWidgets.at(i); + QWidgetPrivate *wd = w->d_func(); + if (!wd->isOpaque || !wd->extra || wd->extra->staticContentsSize.isEmpty() + || !w->isVisible() || (parent && !parent->isAncestorOf(w))) { + continue; + } + + QRect rect(0, 0, wd->extra->staticContentsSize.width(), wd->extra->staticContentsSize.height()); + const QPoint offset = w->mapTo(parent ? parent : tlw, QPoint()); + if (clipToRect) + rect &= withinClipRect.translated(-offset); + if (rect.isEmpty()) + continue; + + rect &= wd->clipRect(); + if (rect.isEmpty()) + continue; + + QRegion visible(rect); + wd->clipToEffectiveMask(visible); + if (visible.isEmpty()) + continue; + wd->subtractOpaqueSiblings(visible, 0, /*alsoNonOpaque=*/true); + + visible.translate(offset); + region += visible; + } + + return region; +} + +void QWidgetRepaintManager::updateStaticContentsSize() +{ + for (int i = 0; i < staticWidgets.size(); ++i) { + QWidgetPrivate *wd = staticWidgets.at(i)->d_func(); + if (!wd->extra) + wd->createExtra(); + wd->extra->staticContentsSize = wd->data.crect.size(); + } +} + +// --------------------------------------------------------------------------- + +bool QWidgetRepaintManager::isDirty() const +{ + return !(dirtyWidgets.isEmpty() && dirty.isEmpty() && dirtyRenderToTextureWidgets.isEmpty()); } /*! @@ -1425,8 +1329,8 @@ void QWidgetPrivate::invalidateBackingStore_resizeHelper(const QPoint &oldPos, c if (!staticContents || graphicsEffect) { QRegion staticChildren; - QWidgetBackingStore *bs = 0; - if (offset.isNull() && (bs = maybeBackingStore())) + QWidgetRepaintManager *bs = 0; + if (offset.isNull() && (bs = maybeRepaintManager())) staticChildren = bs->staticContents(q, oldWidgetRect); const bool hasStaticChildren = !staticChildren.isEmpty(); @@ -1496,101 +1400,6 @@ void QWidgetPrivate::invalidateBackingStore_resizeHelper(const QPoint &oldPos, c } } -/*! - Invalidates the \a r (in widget's coordinates) of the backing store, i.e. - all widgets intersecting with the region will be repainted when the backing - store is synced. -*/ -template <class T> -void QWidgetPrivate::invalidateBackingStore(const T &r) -{ - if (r.isEmpty()) - return; - - if (QCoreApplication::closingDown()) - return; - - Q_Q(QWidget); - if (!q->isVisible() || !q->updatesEnabled()) - return; - - QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); - if (!tlwExtra || tlwExtra->inTopLevelResize || !tlwExtra->backingStore) - return; - - T clipped(r); - clipped &= clipRect(); - if (clipped.isEmpty()) - return; - - if (!graphicsEffect && extra && extra->hasMask) { - QRegion masked(extra->mask); - masked &= clipped; - if (masked.isEmpty()) - return; - - tlwExtra->backingStoreTracker->markDirty(masked, q, - QWidgetBackingStore::UpdateLater, QWidgetBackingStore::BufferInvalid); - } else { - tlwExtra->backingStoreTracker->markDirty(clipped, q, - QWidgetBackingStore::UpdateLater, QWidgetBackingStore::BufferInvalid); - } -} -// Needed by tst_QWidget -template Q_AUTOTEST_EXPORT void QWidgetPrivate::invalidateBackingStore<QRect>(const QRect &r); - -void QWidgetPrivate::repaint_sys(const QRegion &rgn) -{ - if (data.in_destructor) - return; - - Q_Q(QWidget); - if (discardSyncRequest(q, maybeTopData())) - return; - - if (q->testAttribute(Qt::WA_StaticContents)) { - if (!extra) - createExtra(); - extra->staticContentsSize = data.crect.size(); - } - - QPaintEngine *engine = q->paintEngine(); - - // QGLWidget does not support partial updates if: - // 1) The context is double buffered - // 2) The context is single buffered and auto-fill background is enabled. - const bool noPartialUpdateSupport = (engine && (engine->type() == QPaintEngine::OpenGL - || engine->type() == QPaintEngine::OpenGL2)) - && (usesDoubleBufferedGLContext || q->autoFillBackground()); - QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn); - -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // No difference between update() and repaint() on the Mac. - update_sys(toBePainted); - return; -#endif - - toBePainted &= clipRect(); - clipToEffectiveMask(toBePainted); - if (toBePainted.isEmpty()) - return; // Nothing to repaint. - -#ifndef QT_NO_PAINT_DEBUG - bool flushed = QWidgetBackingStore::flushPaint(q, toBePainted); -#endif - - drawWidget(q, toBePainted, QPoint(), QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen, 0); - -#ifndef QT_NO_PAINT_DEBUG - if (flushed) - QWidgetBackingStore::unflushPaint(q, toBePainted); -#endif - - if (Q_UNLIKELY(q->paintingActive())) - qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent"); -} - - QT_END_NAMESPACE -#include "moc_qwidgetbackingstore_p.cpp" +#include "qwidgetrepaintmanager.moc" diff --git a/src/widgets/kernel/qwidgetrepaintmanager_p.h b/src/widgets/kernel/qwidgetrepaintmanager_p.h new file mode 100644 index 0000000000..58687383f4 --- /dev/null +++ b/src/widgets/kernel/qwidgetrepaintmanager_p.h @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWidgets module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWIDGETREPAINTMANAGER_P_H +#define QWIDGETREPAINTMANAGER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtWidgets/private/qtwidgetsglobal_p.h> +#include <QDebug> +#include <QtWidgets/qwidget.h> +#include <private/qwidget_p.h> +#include <QtGui/qbackingstore.h> + +QT_BEGIN_NAMESPACE + +class QPlatformTextureList; +class QPlatformTextureListWatcher; +class QWidgetRepaintManager; + +class Q_AUTOTEST_EXPORT QWidgetRepaintManager +{ + Q_GADGET +public: + enum UpdateTime { + UpdateNow, + UpdateLater + }; + Q_ENUM(UpdateTime) + + enum BufferState{ + BufferValid, + BufferInvalid + }; + Q_ENUM(BufferState) + + QWidgetRepaintManager(QWidget *t); + ~QWidgetRepaintManager(); + + QBackingStore *backingStore() const { return store; } + void setBackingStore(QBackingStore *backingStore) { store = backingStore; } + + template <class T> + void markDirty(const T &r, QWidget *widget, UpdateTime updateTime = UpdateLater, + BufferState bufferState = BufferValid); + + void removeDirtyWidget(QWidget *w); + + void sync(QWidget *exposedWidget, const QRegion &exposedRegion); + void sync(); + + void markNeedsFlush(QWidget *widget, const QRegion ®ion, const QPoint &topLevelOffset); + + void addStaticWidget(QWidget *widget); + void moveStaticWidgets(QWidget *reparented); + void removeStaticWidget(QWidget *widget); + QRegion staticContents(QWidget *widget = nullptr, const QRect &withinClipRect = QRect()) const; + + bool bltRect(const QRect &rect, int dx, int dy, QWidget *widget); + +private: + void updateLists(QWidget *widget); + + void addDirtyWidget(QWidget *widget, const QRegion &rgn); + void resetWidget(QWidget *widget); + + void addDirtyRenderToTextureWidget(QWidget *widget); + + void sendUpdateRequest(QWidget *widget, UpdateTime updateTime); + + bool syncAllowed(); + void paintAndFlush(); + + void markNeedsFlush(QWidget *widget, const QRegion ®ion = QRegion()); + + void flush(); + void flush(QWidget *widget, const QRegion ®ion, QPlatformTextureList *widgetTextures); + + bool isDirty() const; + + bool hasStaticContents() const; + void updateStaticContentsSize(); + + QWidget *tlw = nullptr; + QBackingStore *store = nullptr; + + QRegion dirty; // needsRepaint + QVector<QWidget *> dirtyWidgets; + QVector<QWidget *> dirtyRenderToTextureWidgets; + + QRegion topLevelNeedsFlush; + QVector<QWidget *> needsFlushWidgets; + + QList<QWidget *> staticWidgets; + + QPlatformTextureListWatcher *textureListWatcher = nullptr; + + bool updateRequestSent = false; + + QElapsedTimer perfTime; + int perfFrames = 0; + + Q_DISABLE_COPY_MOVE(QWidgetRepaintManager) +}; + +QT_END_NAMESPACE + +#endif // QWIDGETREPAINTMANAGER_P_H diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 5537ff497a..b9a67edc6a 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -46,7 +46,7 @@ #ifndef QT_NO_ACCESSIBILITY #include <QtGui/qaccessible.h> #endif -#include <private/qwidgetbackingstore_p.h> +#include <private/qwidgetrepaintmanager_p.h> #include <qpa/qwindowsysteminterface_p.h> #include <qpa/qplatformtheme.h> #include <qpa/qplatformwindow.h> @@ -770,8 +770,8 @@ void QWidgetWindow::repaintWindow() QTLWExtra *tlwExtra = m_widget->window()->d_func()->maybeTopData(); if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) - tlwExtra->backingStoreTracker->markDirty(m_widget->rect(), m_widget, - QWidgetBackingStore::UpdateNow, QWidgetBackingStore::BufferInvalid); + tlwExtra->repaintManager->markDirty(m_widget->rect(), m_widget, + QWidgetRepaintManager::UpdateNow, QWidgetRepaintManager::BufferInvalid); } // Store normal geometry used for saving application settings. @@ -803,7 +803,7 @@ void QWidgetWindow::handleResizeEvent(QResizeEvent *event) if (updateSize()) { QGuiApplication::forwardEvent(m_widget, event); - if (m_widget->d_func()->paintOnScreen()) { + if (m_widget->d_func()->shouldPaintOnScreen()) { QRegion updateRegion(geometry()); if (m_widget->testAttribute(Qt::WA_StaticContents)) updateRegion -= QRect(0, 0, oldSize.width(), oldSize.height()); diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index 7b53f5272c..3db85ca07a 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -4247,10 +4247,11 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex #if QT_CONFIG(combobox) case CC_ComboBox: if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) { + const qreal dpi = QStyleHelper::dpi(opt); const int x = cb->rect.x(), y = cb->rect.y(), wi = cb->rect.width(), he = cb->rect.height(); - const int margin = cb->frame ? qRound(QStyleHelper::dpiScaled(3)) : 0; - const int bmarg = cb->frame ? qRound(QStyleHelper::dpiScaled(2)) : 0; - const int xpos = x + wi - bmarg - qRound(QStyleHelper::dpiScaled(16)); + const int margin = cb->frame ? qRound(QStyleHelper::dpiScaled(3, dpi)) : 0; + const int bmarg = cb->frame ? qRound(QStyleHelper::dpiScaled(2, dpi)) : 0; + const int xpos = x + wi - bmarg - qRound(QStyleHelper::dpiScaled(16, dpi)); switch (sc) { @@ -4258,10 +4259,10 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex ret = cb->rect; break; case SC_ComboBoxArrow: - ret.setRect(xpos, y + bmarg, qRound(QStyleHelper::dpiScaled(16)), he - 2*bmarg); + ret.setRect(xpos, y + bmarg, qRound(QStyleHelper::dpiScaled(16, opt)), he - 2*bmarg); break; case SC_ComboBoxEditField: - ret.setRect(x + margin, y + margin, wi - 2 * margin - qRound(QStyleHelper::dpiScaled(16)), he - 2 * margin); + ret.setRect(x + margin, y + margin, wi - 2 * margin - qRound(QStyleHelper::dpiScaled(16, dpi)), he - 2 * margin); break; case SC_ComboBoxListBoxPopup: ret = cb->rect; @@ -4505,13 +4506,13 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid ret = 0; break; case PM_DialogButtonsSeparator: - ret = int(QStyleHelper::dpiScaled(5.)); + ret = int(QStyleHelper::dpiScaled(5, opt)); break; case PM_DialogButtonsButtonWidth: - ret = int(QStyleHelper::dpiScaled(70.)); + ret = int(QStyleHelper::dpiScaled(70, opt)); break; case PM_DialogButtonsButtonHeight: - ret = int(QStyleHelper::dpiScaled(30.)); + ret = int(QStyleHelper::dpiScaled(30, opt)); break; case PM_TitleBarHeight: { if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) { @@ -4519,33 +4520,33 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid ret = qMax(widget ? widget->fontMetrics().height() : opt->fontMetrics.height(), 16); #if QT_CONFIG(dockwidget) } else if (qobject_cast<const QDockWidget*>(widget)) { - ret = qMax(widget->fontMetrics().height(), int(QStyleHelper::dpiScaled(13))); + ret = qMax(widget->fontMetrics().height(), int(QStyleHelper::dpiScaled(13, opt))); #endif } else { ret = qMax(widget ? widget->fontMetrics().height() : opt->fontMetrics.height(), 18); } } else { - ret = int(QStyleHelper::dpiScaled(18.)); + ret = int(QStyleHelper::dpiScaled(18., opt)); } break; } case PM_TitleBarButtonSize: - ret = int(QStyleHelper::dpiScaled(16.)); + ret = int(QStyleHelper::dpiScaled(16., opt)); break; case PM_TitleBarButtonIconSize: - ret = int(QStyleHelper::dpiScaled(16.)); + ret = int(QStyleHelper::dpiScaled(16., opt)); break; case PM_ScrollBarSliderMin: - ret = int(QStyleHelper::dpiScaled(9.)); + ret = int(QStyleHelper::dpiScaled(9., opt)); break; case PM_ButtonMargin: - ret = int(QStyleHelper::dpiScaled(6.)); + ret = int(QStyleHelper::dpiScaled(6., opt)); break; case PM_DockWidgetTitleBarButtonMargin: - ret = int(QStyleHelper::dpiScaled(2.)); + ret = int(QStyleHelper::dpiScaled(2., opt)); break; case PM_ButtonDefaultIndicator: @@ -4553,7 +4554,7 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid break; case PM_MenuButtonIndicator: - ret = int(QStyleHelper::dpiScaled(12.)); + ret = int(QStyleHelper::dpiScaled(12, opt)); break; case PM_ButtonShiftHorizontal: @@ -4568,15 +4569,15 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid case PM_MenuPanelWidth: case PM_TabBarBaseOverlap: case PM_TabBarBaseHeight: - ret = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); + ret = proxy()->pixelMetric(PM_DefaultFrameWidth, opt); break; case PM_MdiSubWindowFrameWidth: - ret = int(QStyleHelper::dpiScaled(4.)); + ret = int(QStyleHelper::dpiScaled(4, opt)); break; case PM_MdiSubWindowMinimizedWidth: - ret = int(QStyleHelper::dpiScaled(196.)); + ret = int(QStyleHelper::dpiScaled(196, opt)); break; #if QT_CONFIG(scrollbar) @@ -4587,7 +4588,7 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid : QApplication::globalStrut().width(); ret = qMax(16, s); } else { - ret = int(QStyleHelper::dpiScaled(16.)); + ret = int(QStyleHelper::dpiScaled(16, opt)); } break; #endif @@ -4597,7 +4598,7 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid #if QT_CONFIG(slider) case PM_SliderThickness: - ret = int(QStyleHelper::dpiScaled(16.)); + ret = int(QStyleHelper::dpiScaled(16, opt)); break; case PM_SliderTickmarkOffset: @@ -4631,11 +4632,11 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid #endif // QT_CONFIG(slider) #if QT_CONFIG(dockwidget) case PM_DockWidgetSeparatorExtent: - ret = int(QStyleHelper::dpiScaled(6.)); + ret = int(QStyleHelper::dpiScaled(6, opt)); break; case PM_DockWidgetHandleExtent: - ret = int(QStyleHelper::dpiScaled(8.)); + ret = int(QStyleHelper::dpiScaled(8, opt)); break; case PM_DockWidgetTitleMargin: ret = 0; @@ -4664,19 +4665,19 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid break; case PM_ToolBarItemSpacing: - ret = int(QStyleHelper::dpiScaled(4.)); + ret = int(QStyleHelper::dpiScaled(4, opt)); break; case PM_ToolBarHandleExtent: - ret = int(QStyleHelper::dpiScaled(8.)); + ret = int(QStyleHelper::dpiScaled(8, opt)); break; case PM_ToolBarSeparatorExtent: - ret = int(QStyleHelper::dpiScaled(6.)); + ret = int(QStyleHelper::dpiScaled(6, opt)); break; case PM_ToolBarExtensionExtent: - ret = int(QStyleHelper::dpiScaled(12.)); + ret = int(QStyleHelper::dpiScaled(12, opt)); break; #endif // QT_CONFIG(toolbar) @@ -4686,7 +4687,7 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid break; case PM_TabBarTabHSpace: - ret = int(QStyleHelper::dpiScaled(24.)); + ret = int(QStyleHelper::dpiScaled(24, opt)); break; case PM_TabBarTabShiftHorizontal: @@ -4715,27 +4716,27 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid break; case PM_IndicatorWidth: - ret = int(QStyleHelper::dpiScaled(13.)); + ret = int(QStyleHelper::dpiScaled(13, opt)); break; case PM_IndicatorHeight: - ret = int(QStyleHelper::dpiScaled(13.)); + ret = int(QStyleHelper::dpiScaled(13, opt)); break; case PM_ExclusiveIndicatorWidth: - ret = int(QStyleHelper::dpiScaled(12.)); + ret = int(QStyleHelper::dpiScaled(12, opt)); break; case PM_ExclusiveIndicatorHeight: - ret = int(QStyleHelper::dpiScaled(12.)); + ret = int(QStyleHelper::dpiScaled(12, opt)); break; case PM_MenuTearoffHeight: - ret = int(QStyleHelper::dpiScaled(10.)); + ret = int(QStyleHelper::dpiScaled(10, opt)); break; case PM_MenuScrollerHeight: - ret = int(QStyleHelper::dpiScaled(10.)); + ret = int(QStyleHelper::dpiScaled(10, opt)); break; case PM_MenuDesktopFrameWidth: @@ -4745,22 +4746,22 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid break; case PM_HeaderMargin: - ret = int(QStyleHelper::dpiScaled(4.)); + ret = int(QStyleHelper::dpiScaled(4, opt)); break; case PM_HeaderMarkSize: - ret = int(QStyleHelper::dpiScaled(16.)); + ret = int(QStyleHelper::dpiScaled(16, opt)); break; case PM_HeaderGripMargin: - ret = int(QStyleHelper::dpiScaled(4.)); + ret = int(QStyleHelper::dpiScaled(4, opt)); break; case PM_HeaderDefaultSectionSizeHorizontal: - ret = int(QStyleHelper::dpiScaled(100.)); + ret = int(QStyleHelper::dpiScaled(100, opt)); break; case PM_HeaderDefaultSectionSizeVertical: - ret = int(QStyleHelper::dpiScaled(30.)); + ret = int(QStyleHelper::dpiScaled(30, opt)); break; case PM_TabBarScrollButtonWidth: - ret = int(QStyleHelper::dpiScaled(16.)); + ret = int(QStyleHelper::dpiScaled(16, opt)); break; case PM_LayoutLeftMargin: case PM_LayoutTopMargin: @@ -4782,13 +4783,13 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid break; case PM_DefaultTopLevelMargin: - ret = int(QStyleHelper::dpiScaled(11.)); + ret = int(QStyleHelper::dpiScaled(11, opt)); break; case PM_DefaultChildMargin: - ret = int(QStyleHelper::dpiScaled(9.)); + ret = int(QStyleHelper::dpiScaled(9, opt)); break; case PM_DefaultLayoutSpacing: - ret = int(QStyleHelper::dpiScaled(6.)); + ret = int(QStyleHelper::dpiScaled(6, opt)); break; case PM_ToolBarIconSize: @@ -4796,31 +4797,31 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) ret = theme->themeHint(QPlatformTheme::ToolBarIconSize).toInt(); if (ret <= 0) - ret = int(QStyleHelper::dpiScaled(24.)); + ret = int(QStyleHelper::dpiScaled(24, opt)); break; case PM_TabBarIconSize: - ret = proxy()->pixelMetric(PM_SmallIconSize, opt, widget); + ret = proxy()->pixelMetric(PM_SmallIconSize, opt); break; case PM_ListViewIconSize: #if QT_CONFIG(filedialog) if (qobject_cast<const QSidebar *>(widget)) - ret = int(QStyleHelper::dpiScaled(24.)); + ret = int(QStyleHelper::dpiScaled(24., opt)); else #endif - ret = proxy()->pixelMetric(PM_SmallIconSize, opt, widget); + ret = proxy()->pixelMetric(PM_SmallIconSize, opt); break; case PM_ButtonIconSize: case PM_SmallIconSize: - ret = int(QStyleHelper::dpiScaled(16.)); + ret = int(QStyleHelper::dpiScaled(16, opt)); break; case PM_IconViewIconSize: - ret = proxy()->pixelMetric(PM_LargeIconSize, opt, widget); + ret = proxy()->pixelMetric(PM_LargeIconSize, opt); break; case PM_LargeIconSize: - ret = int(QStyleHelper::dpiScaled(32.)); + ret = int(QStyleHelper::dpiScaled(32, opt)); break; case PM_ToolTipLabelFrameWidth: @@ -4828,10 +4829,10 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid break; case PM_CheckBoxLabelSpacing: case PM_RadioButtonLabelSpacing: - ret = int(QStyleHelper::dpiScaled(6.)); + ret = int(QStyleHelper::dpiScaled(6, opt)); break; case PM_SizeGripSize: - ret = int(QStyleHelper::dpiScaled(13.)); + ret = int(QStyleHelper::dpiScaled(13, opt)); break; case PM_MessageBoxIconSize: #ifdef Q_OS_MAC @@ -4840,7 +4841,7 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid } else #endif { - ret = int(QStyleHelper::dpiScaled(32.)); + ret = int(QStyleHelper::dpiScaled(32, opt)); } break; case PM_TextCursorWidth: @@ -4851,19 +4852,19 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid break; case PM_TabCloseIndicatorWidth: case PM_TabCloseIndicatorHeight: - ret = int(QStyleHelper::dpiScaled(16.)); + ret = int(QStyleHelper::dpiScaled(16, opt)); break; case PM_ScrollView_ScrollBarSpacing: - ret = 2 * proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); + ret = 2 * proxy()->pixelMetric(PM_DefaultFrameWidth, opt); break; case PM_ScrollView_ScrollBarOverlap: ret = 0; break; case PM_SubMenuOverlap: - ret = -proxy()->pixelMetric(QStyle::PM_MenuPanelWidth, opt, widget); + ret = -proxy()->pixelMetric(QStyle::PM_MenuPanelWidth, opt); break; case PM_TreeViewIndentation: - ret = int(QStyleHelper::dpiScaled(20.)); + ret = int(QStyleHelper::dpiScaled(20, opt)); break; default: ret = 0; diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index e21ff4bec8..ba2b6b0ed9 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -250,8 +250,9 @@ static void qt_fusion_draw_arrow(Qt::ArrowType type, QPainter *painter, const QS if (rect.isEmpty()) return; - const int arrowWidth = QStyleHelper::dpiScaled(14); - const int arrowHeight = QStyleHelper::dpiScaled(8); + const qreal dpi = QStyleHelper::dpi(option); + const int arrowWidth = int(QStyleHelper::dpiScaled(14, dpi)); + const int arrowHeight = int(QStyleHelper::dpiScaled(8, dpi)); const int arrowMax = qMin(arrowHeight, arrowWidth); const int rectMax = qMin(rect.height(), rect.width()); @@ -465,6 +466,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, switch (elem) { +#if QT_CONFIG(groupbox) // No frame drawn case PE_FrameGroupBox: { @@ -481,6 +483,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, qDrawBorderPixmap(painter, frame, QMargins(6, 6, 6, 6), pixmap); break; } +#endif // QT_CONFIG(groupbox) case PE_IndicatorBranch: { if (!(option->state & State_Children)) break; @@ -786,12 +789,13 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, painter->drawRect(rect.adjusted(checkMarkPadding, checkMarkPadding, -checkMarkPadding, -checkMarkPadding)); } else if (checkbox->state & State_On) { - qreal penWidth = QStyleHelper::dpiScaled(1.5); + const qreal dpi = QStyleHelper::dpi(option); + qreal penWidth = QStyleHelper::dpiScaled(1.5, dpi); penWidth = qMax<qreal>(penWidth, 0.13 * rect.height()); penWidth = qMin<qreal>(penWidth, 0.20 * rect.height()); QPen checkPen = QPen(checkMarkColor, penWidth); checkMarkColor.setAlpha(210); - painter->translate(dpiScaled(-0.8), dpiScaled(0.5)); + painter->translate(dpiScaled(-0.8, dpi), dpiScaled(0.5, dpi)); painter->setPen(checkPen); painter->setBrush(Qt::NoBrush); @@ -1542,7 +1546,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio QColor highlight = option->palette.highlight().color(); if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { int w = 0; - const int margin = QStyleHelper::dpiScaled(5); + const int margin = int(QStyleHelper::dpiScaled(5, option)); if (!menuItem->text.isEmpty()) { painter->setFont(menuItem->font); proxy()->drawItemText(painter, menuItem->rect.adjusted(margin, 0, -margin, 0), Qt::AlignLeft | Qt::AlignVCenter, @@ -1572,7 +1576,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio bool ignoreCheckMark = false; const int checkColHOffset = windowsItemHMargin + windowsItemFrame - 1; int checkcol = qMax<int>(menuItem->rect.height() * 0.79, - qMax<int>(menuItem->maxIconWidth, dpiScaled(21))); // icon checkbox's highlight column width + qMax<int>(menuItem->maxIconWidth, dpiScaled(21, option))); // icon checkbox's highlight column width if ( #if QT_CONFIG(combobox) qobject_cast<const QComboBox*>(widget) || @@ -1582,7 +1586,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio if (!ignoreCheckMark) { // Check, using qreal and QRectF to avoid error accumulation - const qreal boxMargin = dpiScaled(3.5); + const qreal boxMargin = dpiScaled(3.5, option); const qreal boxWidth = checkcol - 2 * boxMargin; QRectF checkRectF(option->rect.left() + boxMargin + checkColHOffset, option->rect.center().y() - boxWidth/2 + 1, boxWidth, boxWidth); QRect checkRect = checkRectF.toRect(); @@ -3182,7 +3186,7 @@ int QFusionStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, co default: return QCommonStyle::pixelMetric(metric, option, widget); } - return QStyleHelper::dpiScaled(val); + return QStyleHelper::dpiScaled(val, option); } /*! @@ -3234,7 +3238,7 @@ QSize QFusionStyle::sizeFromContents(ContentsType type, const QStyleOption *opti if (menuItem->text.contains(QLatin1Char('\t'))) w += tabSpacing; else if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) - w += 2 * QStyleHelper::dpiScaled(QFusionStylePrivate::menuArrowHMargin); + w += 2 * QStyleHelper::dpiScaled(QFusionStylePrivate::menuArrowHMargin, option); else if (menuItem->menuItemType == QStyleOptionMenuItem::DefaultItem) { QFontMetrics fm(menuItem->font); QFont fontBold = menuItem->font; @@ -3242,9 +3246,10 @@ QSize QFusionStyle::sizeFromContents(ContentsType type, const QStyleOption *opti QFontMetrics fmBold(fontBold); w += fmBold.horizontalAdvance(menuItem->text) - fm.horizontalAdvance(menuItem->text); } - const int checkcol = qMax<int>(maxpmw, QStyleHelper::dpiScaled(QFusionStylePrivate::menuCheckMarkWidth)); // Windows always shows a check column + const qreal dpi = QStyleHelper::dpi(option); + const int checkcol = qMax<int>(maxpmw, QStyleHelper::dpiScaled(QFusionStylePrivate::menuCheckMarkWidth, dpi)); // Windows always shows a check column w += checkcol; - w += QStyleHelper::dpiScaled(int(QFusionStylePrivate::menuRightBorder) + 10); + w += QStyleHelper::dpiScaled(int(QFusionStylePrivate::menuRightBorder) + 10, dpi); newSize.setWidth(w); if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { if (!menuItem->text.isEmpty()) { @@ -3258,8 +3263,8 @@ QSize QFusionStyle::sizeFromContents(ContentsType type, const QStyleOption *opti } #endif } - newSize.setWidth(newSize.width() + QStyleHelper::dpiScaled(12)); - newSize.setWidth(qMax<int>(newSize.width(), QStyleHelper::dpiScaled(120))); + newSize.setWidth(newSize.width() + int(QStyleHelper::dpiScaled(12, dpi))); + newSize.setWidth(qMax<int>(newSize.width(), int(QStyleHelper::dpiScaled(120, dpi)))); } break; case CT_SizeGrip: @@ -3407,7 +3412,7 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom break; case SC_SliderGroove: { QPoint grooveCenter = slider->rect.center(); - const int grooveThickness = QStyleHelper::dpiScaled(7); + const int grooveThickness = QStyleHelper::dpiScaled(7, option); if (slider->orientation == Qt::Horizontal) { rect.setHeight(grooveThickness); if (slider->tickPosition & QSlider::TicksAbove) @@ -3436,7 +3441,7 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom int center = spinbox->rect.height() / 2; int fw = spinbox->frame ? 3 : 0; // Is drawn with 3 pixels width in drawComplexControl, independently from PM_SpinBoxFrameWidth int y = fw; - const int buttonWidth = QStyleHelper::dpiScaled(14); + const int buttonWidth = QStyleHelper::dpiScaled(14, option); int x, lx, rx; x = spinbox->rect.width() - y - buttonWidth + 2; lx = fw; @@ -3520,17 +3525,19 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom case CC_ComboBox: switch (subControl) { - case SC_ComboBoxArrow: + case SC_ComboBoxArrow: { + const qreal dpi = QStyleHelper::dpi(option); rect = visualRect(option->direction, option->rect, rect); - rect.setRect(rect.right() - QStyleHelper::dpiScaled(18), rect.top() - 2, - QStyleHelper::dpiScaled(19), rect.height() + 4); + rect.setRect(rect.right() - int(QStyleHelper::dpiScaled(18, dpi)), rect.top() - 2, + int(QStyleHelper::dpiScaled(19, dpi)), rect.height() + 4); rect = visualRect(option->direction, option->rect, rect); + } break; case SC_ComboBoxEditField: { int frameWidth = 2; rect = visualRect(option->direction, option->rect, rect); rect.setRect(option->rect.left() + frameWidth, option->rect.top() + frameWidth, - option->rect.width() - int(QStyleHelper::dpiScaled(19)) - 2 * frameWidth, + option->rect.width() - int(QStyleHelper::dpiScaled(19, option)) - 2 * frameWidth, option->rect.height() - 2 * frameWidth); if (const QStyleOptionComboBox *box = qstyleoption_cast<const QStyleOptionComboBox *>(option)) { if (!box->editable) { diff --git a/src/widgets/styles/qpixmapstyle.cpp b/src/widgets/styles/qpixmapstyle.cpp index 976bd2630e..05e8467528 100644 --- a/src/widgets/styles/qpixmapstyle.cpp +++ b/src/widgets/styles/qpixmapstyle.cpp @@ -122,9 +122,6 @@ QPixmapStyle::~QPixmapStyle() void QPixmapStyle::polish(QApplication *application) { QCommonStyle::polish(application); -#if 0 // Used to be included in Qt4 for Q_WS_WIN - QApplication::setEffectEnabled(Qt::UI_AnimateCombo, false); -#endif } /*! @@ -188,11 +185,6 @@ void QPixmapStyle::polish(QWidget *widget) frame->setContentsMargins(pix.margins.left(), desc.margins.top(), pix.margins.right(), desc.margins.bottom()); frame->setAttribute(Qt::WA_TranslucentBackground); -#if 0 // Used to be included in Qt4 for Q_WS_WIN - // FramelessWindowHint is needed on windows to make - // WA_TranslucentBackground work properly - frame->setWindowFlags(widget->windowFlags() | Qt::FramelessWindowHint); -#endif } } #endif // QT_CONFIG(combobox) diff --git a/src/widgets/styles/qstylehelper.cpp b/src/widgets/styles/qstylehelper.cpp index 0b910d46df..4e61b2d1ec 100644 --- a/src/widgets/styles/qstylehelper.cpp +++ b/src/widgets/styles/qstylehelper.cpp @@ -40,6 +40,8 @@ #include <qstyleoption.h> #include <qpainter.h> #include <qpixmapcache.h> +#include <private/qhighdpiscaling_p.h> +#include <private/qguiapplication_p.h> #include <private/qmath_p.h> #include <private/qstyle_p.h> #include <qmath.h> @@ -49,6 +51,7 @@ #include <qabstractscrollarea.h> #include <qwindow.h> +#include <qmetaobject.h> #include "qstylehelper_p.h" #include <qstringbuilder.h> @@ -79,15 +82,41 @@ QString uniqueName(const QString &key, const QStyleOption *option, const QSize & return tmp; } -qreal dpiScaled(qreal value) -{ -#ifdef Q_OS_MAC - // On mac the DPI is always 72 so we should not scale it - return value; +#ifdef Q_OS_DARWIN +static const qreal qstyleBaseDpi = 72; #else - static const qreal scale = qreal(qt_defaultDpiX()) / 96.0; - return value * scale; +static const qreal qstyleBaseDpi = 96; +#endif + +Q_WIDGETS_EXPORT qreal dpi(const QStyleOption *option) +{ +#ifndef Q_OS_DARWIN + // Prioritize the application override, except for on macOS where + // we have historically not supported the AA_Use96Dpi flag. + if (QCoreApplication::testAttribute(Qt::AA_Use96Dpi)) + return 96; #endif + + // Expect that QStyleOption::QFontMetrics::QFont has the correct DPI set + if (option) + return option->fontMetrics.fontDpi(); + + return qstyleBaseDpi; +} + +Q_WIDGETS_EXPORT qreal dpiScaled(qreal value, qreal dpi) +{ + return value * dpi / qstyleBaseDpi; +} + +Q_WIDGETS_EXPORT qreal dpiScaled(qreal value, const QPaintDevice *device) +{ + return dpiScaled(value, device->logicalDpiX()); +} + +Q_WIDGETS_EXPORT qreal dpiScaled(qreal value, const QStyleOption *option) +{ + return dpiScaled(value, dpi(option)); } #ifndef QT_NO_ACCESSIBILITY diff --git a/src/widgets/styles/qstylehelper_p.h b/src/widgets/styles/qstylehelper_p.h index fe052b8984..165608257a 100644 --- a/src/widgets/styles/qstylehelper_p.h +++ b/src/widgets/styles/qstylehelper_p.h @@ -40,6 +40,7 @@ #include <QtWidgets/private/qtwidgetsglobal_p.h> #include <QtCore/qpoint.h> #include <QtCore/qstring.h> +#include <QtGui/qpaintdevice.h> #include <QtGui/qpolygon.h> #include <QtCore/qstringbuilder.h> #include <QtGui/qaccessible.h> @@ -75,7 +76,13 @@ class QWindow; namespace QStyleHelper { QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size); - Q_WIDGETS_EXPORT qreal dpiScaled(qreal value); + + Q_WIDGETS_EXPORT qreal dpi(const QStyleOption *option); + + Q_WIDGETS_EXPORT qreal dpiScaled(qreal value, qreal dpi); + Q_WIDGETS_EXPORT qreal dpiScaled(qreal value, const QPaintDevice *device); + Q_WIDGETS_EXPORT qreal dpiScaled(qreal value, const QStyleOption *option); + #if QT_CONFIG(dial) qreal angle(const QPointF &p1, const QPointF &p2); QPolygonF calcLines(const QStyleOptionSlider *dial); diff --git a/src/widgets/styles/qstyleoption.cpp b/src/widgets/styles/qstyleoption.cpp index 4faf98a0a3..5b3efd598f 100644 --- a/src/widgets/styles/qstyleoption.cpp +++ b/src/widgets/styles/qstyleoption.cpp @@ -198,11 +198,6 @@ void QStyleOption::init(const QWidget *widget) state |= QStyle::State_Active; if (widget->isWindow()) state |= QStyle::State_Window; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - extern bool qt_mac_can_clickThrough(const QWidget *w); //qwidget_mac.cpp - if (!(state & QStyle::State_Active) && !qt_mac_can_clickThrough(widget)) - state &= ~QStyle::State_Enabled; -#endif switch (QStyleHelper::widgetSizePolicy(widget)) { case QStyleHelper::SizeSmall: state |= QStyle::State_Small; diff --git a/src/widgets/styles/qstyleoption.h b/src/widgets/styles/qstyleoption.h index 763575ff5b..7f5edf4279 100644 --- a/src/widgets/styles/qstyleoption.h +++ b/src/widgets/styles/qstyleoption.h @@ -118,7 +118,7 @@ public: QStyleOptionFocusRect(); QStyleOptionFocusRect(const QStyleOptionFocusRect &other) : QStyleOption(Version, Type) { *this = other; } - QStyleOptionFocusRect &operator=(const QStyleOptionFocusRect &other) = default; + QStyleOptionFocusRect &operator=(const QStyleOptionFocusRect &) = default; protected: QStyleOptionFocusRect(int version); @@ -143,7 +143,7 @@ public: QStyleOptionFrame(); QStyleOptionFrame(const QStyleOptionFrame &other) : QStyleOption(Version, Type) { *this = other; } - QStyleOptionFrame &operator=(const QStyleOptionFrame &other) = default; + QStyleOptionFrame &operator=(const QStyleOptionFrame &) = default; protected: QStyleOptionFrame(int version); @@ -173,7 +173,7 @@ public: QStyleOptionTabWidgetFrame(); inline QStyleOptionTabWidgetFrame(const QStyleOptionTabWidgetFrame &other) : QStyleOption(Version, Type) { *this = other; } - QStyleOptionTabWidgetFrame &operator=(const QStyleOptionTabWidgetFrame &other) = default; + QStyleOptionTabWidgetFrame &operator=(const QStyleOptionTabWidgetFrame &) = default; protected: QStyleOptionTabWidgetFrame(int version); @@ -197,7 +197,7 @@ public: QStyleOptionTabBarBase(); QStyleOptionTabBarBase(const QStyleOptionTabBarBase &other) : QStyleOption(Version, Type) { *this = other; } - QStyleOptionTabBarBase &operator=(const QStyleOptionTabBarBase &other) = default; + QStyleOptionTabBarBase &operator=(const QStyleOptionTabBarBase &) = default; protected: QStyleOptionTabBarBase(int version); @@ -229,7 +229,7 @@ public: QStyleOptionHeader(); QStyleOptionHeader(const QStyleOptionHeader &other) : QStyleOption(Version, Type) { *this = other; } - QStyleOptionHeader &operator=(const QStyleOptionHeader &other) = default; + QStyleOptionHeader &operator=(const QStyleOptionHeader &) = default; protected: QStyleOptionHeader(int version); @@ -252,7 +252,7 @@ public: QStyleOptionButton(); QStyleOptionButton(const QStyleOptionButton &other) : QStyleOption(Version, Type) { *this = other; } - QStyleOptionButton &operator=(const QStyleOptionButton &other) = default; + QStyleOptionButton &operator=(const QStyleOptionButton &) = default; protected: QStyleOptionButton(int version); @@ -290,7 +290,7 @@ public: QStyleOptionTab(); QStyleOptionTab(const QStyleOptionTab &other) : QStyleOption(Version, Type) { *this = other; } - QStyleOptionTab &operator=(const QStyleOptionTab &other) = default; + QStyleOptionTab &operator=(const QStyleOptionTab &) = default; protected: QStyleOptionTab(int version); @@ -321,7 +321,7 @@ public: int midLineWidth; QStyleOptionToolBar(); QStyleOptionToolBar(const QStyleOptionToolBar &other) : QStyleOption(Version, Type) { *this = other; } - QStyleOptionToolBar &operator=(const QStyleOptionToolBar &other) = default; + QStyleOptionToolBar &operator=(const QStyleOptionToolBar &) = default; protected: QStyleOptionToolBar(int version); @@ -349,7 +349,7 @@ public: QStyleOptionProgressBar(); QStyleOptionProgressBar(const QStyleOptionProgressBar &other) : QStyleOption(Version, Type) { *this = other; } - QStyleOptionProgressBar &operator=(const QStyleOptionProgressBar &other) = default; + QStyleOptionProgressBar &operator=(const QStyleOptionProgressBar &) = default; protected: QStyleOptionProgressBar(int version); @@ -380,7 +380,7 @@ public: QStyleOptionMenuItem(); QStyleOptionMenuItem(const QStyleOptionMenuItem &other) : QStyleOption(Version, Type) { *this = other; } - QStyleOptionMenuItem &operator=(const QStyleOptionMenuItem &other) = default; + QStyleOptionMenuItem &operator=(const QStyleOptionMenuItem &) = default; protected: QStyleOptionMenuItem(int version); @@ -400,7 +400,7 @@ public: QStyleOptionDockWidget(); QStyleOptionDockWidget(const QStyleOptionDockWidget &other) : QStyleOption(Version, Type) { *this = other; } - QStyleOptionDockWidget &operator=(const QStyleOptionDockWidget &other) = default; + QStyleOptionDockWidget &operator=(const QStyleOptionDockWidget &) = default; protected: QStyleOptionDockWidget(int version); @@ -452,7 +452,7 @@ public: QStyleOptionViewItem(); QStyleOptionViewItem(const QStyleOptionViewItem &other) : QStyleOption(Version, Type) { *this = other; } - QStyleOptionViewItem &operator=(const QStyleOptionViewItem &other) = default; + QStyleOptionViewItem &operator=(const QStyleOptionViewItem &) = default; protected: QStyleOptionViewItem(int version); @@ -483,7 +483,7 @@ public: QStyleOptionToolBox(); QStyleOptionToolBox(const QStyleOptionToolBox &other) : QStyleOption(Version, Type) { *this = other; } - QStyleOptionToolBox &operator=(const QStyleOptionToolBox &other) = default; + QStyleOptionToolBox &operator=(const QStyleOptionToolBox &) = default; protected: QStyleOptionToolBox(int version); @@ -503,7 +503,7 @@ public: QStyleOptionRubberBand(); QStyleOptionRubberBand(const QStyleOptionRubberBand &other) : QStyleOption(Version, Type) { *this = other; } - QStyleOptionRubberBand &operator=(const QStyleOptionRubberBand &other) = default; + QStyleOptionRubberBand &operator=(const QStyleOptionRubberBand &) = default; protected: QStyleOptionRubberBand(int version); @@ -522,7 +522,7 @@ public: QStyleOptionComplex(int version = QStyleOptionComplex::Version, int type = SO_Complex); QStyleOptionComplex(const QStyleOptionComplex &other) : QStyleOption(Version, Type) { *this = other; } - QStyleOptionComplex &operator=(const QStyleOptionComplex &other) = default; + QStyleOptionComplex &operator=(const QStyleOptionComplex &) = default; }; #if QT_CONFIG(slider) @@ -547,7 +547,7 @@ public: QStyleOptionSlider(); QStyleOptionSlider(const QStyleOptionSlider &other) : QStyleOptionComplex(Version, Type) { *this = other; } - QStyleOptionSlider &operator=(const QStyleOptionSlider &other) = default; + QStyleOptionSlider &operator=(const QStyleOptionSlider &) = default; protected: QStyleOptionSlider(int version); @@ -567,7 +567,7 @@ public: QStyleOptionSpinBox(); QStyleOptionSpinBox(const QStyleOptionSpinBox &other) : QStyleOptionComplex(Version, Type) { *this = other; } - QStyleOptionSpinBox &operator=(const QStyleOptionSpinBox &other) = default; + QStyleOptionSpinBox &operator=(const QStyleOptionSpinBox &) = default; protected: QStyleOptionSpinBox(int version); @@ -595,7 +595,7 @@ public: QStyleOptionToolButton(); QStyleOptionToolButton(const QStyleOptionToolButton &other) : QStyleOptionComplex(Version, Type) { *this = other; } - QStyleOptionToolButton &operator=(const QStyleOptionToolButton &other) = default; + QStyleOptionToolButton &operator=(const QStyleOptionToolButton &) = default; protected: QStyleOptionToolButton(int version); @@ -618,7 +618,7 @@ public: QStyleOptionComboBox(); QStyleOptionComboBox(const QStyleOptionComboBox &other) : QStyleOptionComplex(Version, Type) { *this = other; } - QStyleOptionComboBox &operator=(const QStyleOptionComboBox &other) = default; + QStyleOptionComboBox &operator=(const QStyleOptionComboBox &) = default; protected: QStyleOptionComboBox(int version); @@ -637,7 +637,7 @@ public: QStyleOptionTitleBar(); QStyleOptionTitleBar(const QStyleOptionTitleBar &other) : QStyleOptionComplex(Version, Type) { *this = other; } - QStyleOptionTitleBar &operator=(const QStyleOptionTitleBar &other) = default; + QStyleOptionTitleBar &operator=(const QStyleOptionTitleBar &) = default; protected: QStyleOptionTitleBar(int version); @@ -658,7 +658,7 @@ public: QStyleOptionGroupBox(); QStyleOptionGroupBox(const QStyleOptionGroupBox &other) : QStyleOptionComplex(Version, Type) { *this = other; } - QStyleOptionGroupBox &operator=(const QStyleOptionGroupBox &other) = default; + QStyleOptionGroupBox &operator=(const QStyleOptionGroupBox &) = default; protected: QStyleOptionGroupBox(int version); }; @@ -673,7 +673,7 @@ public: QStyleOptionSizeGrip(); QStyleOptionSizeGrip(const QStyleOptionSizeGrip &other) : QStyleOptionComplex(Version, Type) { *this = other; } - QStyleOptionSizeGrip &operator=(const QStyleOptionSizeGrip &other) = default; + QStyleOptionSizeGrip &operator=(const QStyleOptionSizeGrip &) = default; protected: QStyleOptionSizeGrip(int version); }; @@ -690,7 +690,7 @@ public: QStyleOptionGraphicsItem(); QStyleOptionGraphicsItem(const QStyleOptionGraphicsItem &other) : QStyleOption(Version, Type) { *this = other; } - QStyleOptionGraphicsItem &operator=(const QStyleOptionGraphicsItem &other) = default; + QStyleOptionGraphicsItem &operator=(const QStyleOptionGraphicsItem &) = default; static qreal levelOfDetailFromTransform(const QTransform &worldTransform); protected: QStyleOptionGraphicsItem(int version); diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index ea653459d3..dd225fbec3 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -5153,13 +5153,6 @@ QSize QStyleSheetStyle::sizeFromContents(ContentsType ct, const QStyleOption *op sz = csz + QSize(vertical ? 0 : spaceForIcon, vertical ? spaceForIcon : 0); return subRule.boxSize(subRule.adjustSize(sz)); } -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (baseStyle()->inherits("QMacStyle")) { - //adjust the size after the call to the style because the mac style ignore the size arguments anyway. - //this might cause the (max-){width,height} property to include the native style border while they should not. - return subRule.adjustSize(baseStyle()->sizeFromContents(ct, opt, csz, w)); - } -#endif sz = subRule.adjustSize(csz); break; } diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index c13f6e637d..72c803cb99 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -423,7 +423,7 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW ret = QWindowsStylePrivate::fixedPixelMetric(pm); if (ret != QWindowsStylePrivate::InvalidMetric) - return int(QStyleHelper::dpiScaled(ret)); + return int(QStyleHelper::dpiScaled(ret, opt)); ret = 0; @@ -469,7 +469,7 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW break; case PM_SplitterWidth: - ret = qMax(int(QStyleHelper::dpiScaled(4)), QApplication::globalStrut().width()); + ret = qMax(int(QStyleHelper::dpiScaled(4, opt)), QApplication::globalStrut().width()); break; default: @@ -793,8 +793,9 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPen oldPen = p->pen(); p->setPen(QPen(opt->palette.shadow().color(), 0)); QRectF rect = opt->rect; - const qreal topLevelAdjustment = QStyleHelper::dpiScaled(0.5); - const qreal bottomRightAdjustment = QStyleHelper::dpiScaled(-1.5); + const qreal dpi = QStyleHelper::dpi(opt); + const qreal topLevelAdjustment = QStyleHelper::dpiScaled(0.5, dpi); + const qreal bottomRightAdjustment = QStyleHelper::dpiScaled(-1.5, dpi); rect.adjust(topLevelAdjustment, topLevelAdjustment, bottomRightAdjustment, bottomRightAdjustment); p->drawRect(rect); @@ -2303,8 +2304,9 @@ QSize QWindowsStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, int defwidth = 0; if (btn->features & QStyleOptionButton::AutoDefaultButton) defwidth = 2 * proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget); - int minwidth = int(QStyleHelper::dpiScaled(75.)); - int minheight = int(QStyleHelper::dpiScaled(23.)); + const qreal dpi = QStyleHelper::dpi(opt); + int minwidth = int(QStyleHelper::dpiScaled(75, dpi)); + int minheight = int(QStyleHelper::dpiScaled(23, dpi)); #ifndef QT_QWS_SMALL_PUSHBUTTON if (w < minwidth + defwidth && !btn->text.isEmpty()) diff --git a/src/widgets/util/qcompleter.h b/src/widgets/util/qcompleter.h index 5620b55589..5448fc313c 100644 --- a/src/widgets/util/qcompleter.h +++ b/src/widgets/util/qcompleter.h @@ -75,12 +75,14 @@ public: UnfilteredPopupCompletion, InlineCompletion }; + Q_ENUM(CompletionMode) enum ModelSorting { UnsortedModel = 0, CaseSensitivelySortedModel, CaseInsensitivelySortedModel }; + Q_ENUM(ModelSorting) QCompleter(QObject *parent = nullptr); QCompleter(QAbstractItemModel *model, QObject *parent = nullptr); diff --git a/src/widgets/util/qflickgesture.cpp b/src/widgets/util/qflickgesture.cpp index 55ec93c7d3..14a30ce7cf 100644 --- a/src/widgets/util/qflickgesture.cpp +++ b/src/widgets/util/qflickgesture.cpp @@ -462,21 +462,6 @@ QGestureRecognizer::Result QFlickGestureRecognizer::recognize(QGesture *state, } break; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // the only way to distinguish between real mouse wheels and wheel - // events generated by the native 2 finger swipe gesture is to listen - // for these events (according to Apple's Cocoa Event-Handling Guide) - - case QEvent::NativeGesture: { - QNativeGestureEvent *nge = static_cast<QNativeGestureEvent *>(event); - if (nge->gestureType == QNativeGestureEvent::GestureBegin) - d->macIgnoreWheel = true; - else if (nge->gestureType == QNativeGestureEvent::GestureEnd) - d->macIgnoreWheel = false; - break; - } -#endif - // consume all wheel events if the scroller is active case QEvent::Wheel: if (d->macIgnoreWheel || (scroller->state() != QScroller::Inactive)) diff --git a/src/widgets/util/qscroller_mac.mm b/src/widgets/util/qscroller_mac.mm deleted file mode 100644 index 6dbb483089..0000000000 --- a/src/widgets/util/qscroller_mac.mm +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtCore/qglobal.h> - -#if 0 // Used to be included in Qt4 for Q_WS_MAC - -#import <AppKit/AppKit.h> - -#include "qscroller_p.h" - -QT_BEGIN_NAMESPACE - -QPointF QScrollerPrivate::realDpi(int screen) const -{ - QMacAutoReleasePool pool; - NSArray *nsscreens = [NSScreen screens]; - - if (screen < 0 || screen >= int([nsscreens count])) - screen = 0; - - NSScreen *nsscreen = [nsscreens objectAtIndex:screen]; - CGDirectDisplayID display = [[[nsscreen deviceDescription] objectForKey:@"NSScreenNumber"] intValue]; - - CGSize mmsize = CGDisplayScreenSize(display); - if (mmsize.width > 0 && mmsize.height > 0) { - return QPointF(CGDisplayPixelsWide(display) / mmsize.width, - CGDisplayPixelsHigh(display) / mmsize.height) * qreal(25.4); - } else { - return QPointF(); - } -} - -QT_END_NAMESPACE - -#endif diff --git a/src/widgets/util/qscrollerproperties.cpp b/src/widgets/util/qscrollerproperties.cpp index c26fba2cd3..df6b899fe4 100644 --- a/src/widgets/util/qscrollerproperties.cpp +++ b/src/widgets/util/qscrollerproperties.cpp @@ -40,9 +40,6 @@ #include <QPointer> #include <QObject> #include <QtCore/qmath.h> -#if 0 // Used to be included in Qt4 for Q_WS_WIN -# include <QLibrary> -#endif #include "qscrollerproperties.h" #include "private/qscrollerproperties_p.h" @@ -73,10 +70,6 @@ QScrollerPropertiesPrivate *QScrollerPropertiesPrivate::defaults() spp.overshootDragDistanceFactor = qreal(1); spp.overshootScrollDistanceFactor = qreal(0.5); spp.overshootScrollTime = qreal(0.7); -# if 0 // Used to be included in Qt4 for Q_WS_WIN - if (QLibrary::resolve(QLatin1String("UxTheme"), "BeginPanningFeedback")) - spp.overshootScrollTime = qreal(0.35); -# endif spp.hOvershootPolicy = QScrollerProperties::OvershootWhenScrollable; spp.vOvershootPolicy = QScrollerProperties::OvershootWhenScrollable; spp.frameRate = QScrollerProperties::Standard; diff --git a/src/widgets/util/qsystemtrayicon.cpp b/src/widgets/util/qsystemtrayicon.cpp index a38a50d3df..fd18888870 100644 --- a/src/widgets/util/qsystemtrayicon.cpp +++ b/src/widgets/util/qsystemtrayicon.cpp @@ -626,16 +626,6 @@ void QBalloonTip::balloon(const QPoint& pos, int msecs, bool showArrow) } QPainterPath path; -#if defined(QT_NO_XSHAPE) && 0 /* Used to be included in Qt4 for Q_WS_X11 */ - // XShape is required for setting the mask, so we just - // draw an ugly square when its not available - path.moveTo(0, 0); - path.lineTo(sz.width() - 1, 0); - path.lineTo(sz.width() - 1, sz.height() - 1); - path.lineTo(0, sz.height() - 1); - path.lineTo(0, 0); - move(qMax(pos.x() - sz.width(), scr.left()), pos.y()); -#else path.moveTo(ml + rc, mt); if (arrowAtTop && arrowAtLeft) { if (showArrow) { @@ -685,7 +675,6 @@ void QBalloonTip::balloon(const QPoint& pos, int msecs, bool showArrow) painter1.setBrush(QBrush(Qt::color1)); painter1.drawPath(path); setMask(bitmap); -#endif // Draw the border pixmap = QPixmap(sz); diff --git a/src/widgets/util/util.pri b/src/widgets/util/util.pri index a3bd8897f1..363291528e 100644 --- a/src/widgets/util/util.pri +++ b/src/widgets/util/util.pri @@ -54,7 +54,3 @@ qtConfig(xcb) { } else { SOURCES += util/qsystemtrayicon_qpa.cpp } - -mac { - OBJECTIVE_SOURCES += util/qscroller_mac.mm -} diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp index 55b2dcd662..b295e66574 100644 --- a/src/widgets/widgets/qabstractscrollarea.cpp +++ b/src/widgets/widgets/qabstractscrollarea.cpp @@ -62,10 +62,6 @@ #include <private/qapplication_p.h> -#if 0 // Used to be included in Qt4 for Q_WS_MAC -#include <private/qt_mac_p.h> -#include <private/qt_cocoa_helpers_mac_p.h> -#endif #ifdef Q_OS_WIN # include <qt_windows.h> #endif @@ -169,9 +165,6 @@ QAbstractScrollAreaPrivate::QAbstractScrollAreaPrivate() shownOnce(false), inResize(false), sizeAdjustPolicy(QAbstractScrollArea::AdjustIgnored), viewport(0), cornerWidget(0), left(0), top(0), right(0), bottom(0), xoffset(0), yoffset(0), viewportFilter(0) -#if 0 // Used to be included in Qt4 for Q_WS_WIN - , singleFingerPanEnabled(false) -#endif { } @@ -322,16 +315,6 @@ void QAbstractScrollAreaPrivate::init() #endif } -#if 0 // Used to be included in Qt4 for Q_WS_WIN -void QAbstractScrollAreaPrivate::setSingleFingerPanEnabled(bool on) -{ - singleFingerPanEnabled = on; - QWidgetPrivate *dd = static_cast<QWidgetPrivate *>(QObjectPrivate::get(viewport)); - if (dd) - dd->winSetupGestures(); -} -#endif - void QAbstractScrollAreaPrivate::layoutChildren() { bool needH = false; @@ -362,38 +345,6 @@ void QAbstractScrollAreaPrivate::layoutChildren_helper(bool *needHorizontalScrol const int hscrollOverlap = hbar->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarOverlap, &opt, hbar); const int vscrollOverlap = vbar->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarOverlap, &opt, vbar); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - QWidget * const window = q->window(); - - // Use small scroll bars for tool windows, to match the native size grip. - bool hbarIsSmall = hbar->testAttribute(Qt::WA_MacSmallSize); - bool vbarIsSmall = vbar->testAttribute(Qt::WA_MacSmallSize); - const Qt::WindowType windowType = window->windowType(); - if (windowType == Qt::Tool) { - if (!hbarIsSmall) { - hbar->setAttribute(Qt::WA_MacMiniSize, false); - hbar->setAttribute(Qt::WA_MacNormalSize, false); - hbar->setAttribute(Qt::WA_MacSmallSize, true); - } - if (!vbarIsSmall) { - vbar->setAttribute(Qt::WA_MacMiniSize, false); - vbar->setAttribute(Qt::WA_MacNormalSize, false); - vbar->setAttribute(Qt::WA_MacSmallSize, true); - } - } else { - if (hbarIsSmall) { - hbar->setAttribute(Qt::WA_MacMiniSize, false); - hbar->setAttribute(Qt::WA_MacNormalSize, false); - hbar->setAttribute(Qt::WA_MacSmallSize, false); - } - if (vbarIsSmall) { - vbar->setAttribute(Qt::WA_MacMiniSize, false); - vbar->setAttribute(Qt::WA_MacNormalSize, false); - vbar->setAttribute(Qt::WA_MacSmallSize, false); - } - } -#endif - const int hsbExt = hbar->sizeHint().height(); const int vsbExt = vbar->sizeHint().width(); const QPoint extPoint(vsbExt, hsbExt); @@ -403,30 +354,6 @@ void QAbstractScrollAreaPrivate::layoutChildren_helper(bool *needHorizontalScrol const bool hasCornerWidget = (cornerWidget != 0); -// If the scroll bars are at the very right and bottom of the window we -// move their positions to be aligned with the size grip. -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // Check if a native sizegrip is present. - bool hasMacReverseSizeGrip = false; - bool hasMacSizeGrip = false; - bool nativeGripPresent = false; - if (q->testAttribute(Qt::WA_WState_Created)) - nativeGripPresent = qt_mac_checkForNativeSizeGrip(q); - - if (nativeGripPresent) { - // Look for a native size grip at the visual window bottom right and at the - // absolute window bottom right. In reverse mode, the native size grip does not - // swich side, so we need to check if it is on the "wrong side". - const QPoint scrollAreaBottomRight = q->mapTo(window, widgetRect.bottomRight() - QPoint(frameWidth, frameWidth)); - const QPoint windowBottomRight = window->rect().bottomRight(); - const QPoint visualWindowBottomRight = QStyle::visualPos(opt.direction, opt.rect, windowBottomRight); - const QPoint offset = windowBottomRight - scrollAreaBottomRight; - const QPoint visualOffset = visualWindowBottomRight - scrollAreaBottomRight; - hasMacSizeGrip = (visualOffset.manhattanLength() < vsbExt); - hasMacReverseSizeGrip = (hasMacSizeGrip == false && (offset.manhattanLength() < hsbExt)); - } -#endif - QPoint cornerOffset((needv && vscrollOverlap == 0) ? vsbExt : 0, (needh && hscrollOverlap == 0) ? hsbExt : 0); QRect controlsRect; QRect viewportRect; @@ -458,12 +385,6 @@ void QAbstractScrollAreaPrivate::layoutChildren_helper(bool *needHorizontalScrol if (hasCornerWidget && ((needv && vscrollOverlap == 0) || (needh && hscrollOverlap == 0))) cornerOffset = extPoint; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // Also move the scroll bars if they are covered by the native Mac size grip. - if (hasMacSizeGrip) - cornerOffset = extPoint; -#endif - // The corner point is where the scroll bar rects, the corner widget rect and the // viewport rect meets. const QPoint cornerPoint(controlsRect.bottomRight() + QPoint(1, 1) - cornerOffset); @@ -475,13 +396,6 @@ void QAbstractScrollAreaPrivate::layoutChildren_helper(bool *needHorizontalScrol else cornerPaintingRect = QRect(); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (hasMacReverseSizeGrip) - reverseCornerPaintingRect = QRect(controlsRect.bottomRight() + QPoint(1, 1) - extPoint, extSize); - else - reverseCornerPaintingRect = QRect(); -#endif - // move the scrollbars away from top/left headers int vHeaderRight = 0; int hHeaderBottom = 0; @@ -501,10 +415,7 @@ void QAbstractScrollAreaPrivate::layoutChildren_helper(bool *needHorizontalScrol #endif // QT_CONFIG(itemviews) if (needh) { QRect horizontalScrollBarRect(QPoint(controlsRect.left() + vHeaderRight, cornerPoint.y()), QPoint(cornerPoint.x() - 1, controlsRect.bottom())); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (hasMacReverseSizeGrip) - horizontalScrollBarRect.adjust(vsbExt, 0, 0, 0); -#endif + if (!hasCornerWidget && htransient) horizontalScrollBarRect.adjust(0, 0, cornerOffset.x(), 0); scrollBarContainers[Qt::Horizontal]->setGeometry(QStyle::visualRect(opt.direction, opt.rect, horizontalScrollBarRect)); @@ -617,11 +528,9 @@ void QAbstractScrollArea::setViewport(QWidget *widget) d->viewport->setParent(this); d->viewport->setFocusProxy(this); d->viewport->installEventFilter(d->viewportFilter.data()); -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC #ifndef QT_NO_GESTURES d->viewport->grabGesture(Qt::PanGesture); #endif -#endif d->layoutChildren(); #ifndef QT_NO_OPENGL QWidgetPrivate::get(d->viewport)->initializeViewportFramebuffer(); @@ -1043,13 +952,6 @@ bool QAbstractScrollArea::event(QEvent *e) QPainter p(this); style()->drawPrimitive(QStyle::PE_PanelScrollAreaCorner, &option, &p, this); } -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (d->reverseCornerPaintingRect.isValid()) { - option.rect = d->reverseCornerPaintingRect; - QPainter p(this); - style()->drawPrimitive(QStyle::PE_PanelScrollAreaCorner, &option, &p, this); - } -#endif } QFrame::paintEvent((QPaintEvent*)e); break; @@ -1122,38 +1024,10 @@ bool QAbstractScrollArea::event(QEvent *e) hBar->setValue(se->contentPos().x()); vBar->setValue(se->contentPos().y()); -#if 0 // Used to be included in Qt4 for Q_WS_WIN - typedef BOOL (*PtrBeginPanningFeedback)(HWND); - typedef BOOL (*PtrUpdatePanningFeedback)(HWND, LONG, LONG, BOOL); - typedef BOOL (*PtrEndPanningFeedback)(HWND, BOOL); - - static PtrBeginPanningFeedback ptrBeginPanningFeedback = 0; - static PtrUpdatePanningFeedback ptrUpdatePanningFeedback = 0; - static PtrEndPanningFeedback ptrEndPanningFeedback = 0; - - if (!ptrBeginPanningFeedback) - ptrBeginPanningFeedback = (PtrBeginPanningFeedback) QLibrary::resolve(QLatin1String("UxTheme"), "BeginPanningFeedback"); - if (!ptrUpdatePanningFeedback) - ptrUpdatePanningFeedback = (PtrUpdatePanningFeedback) QLibrary::resolve(QLatin1String("UxTheme"), "UpdatePanningFeedback"); - if (!ptrEndPanningFeedback) - ptrEndPanningFeedback = (PtrEndPanningFeedback) QLibrary::resolve(QLatin1String("UxTheme"), "EndPanningFeedback"); - - if (ptrBeginPanningFeedback && ptrUpdatePanningFeedback && ptrEndPanningFeedback) { - WId wid = window()->winId(); - - if (!se->overshootDistance().isNull() && d->overshoot.isNull()) - ptrBeginPanningFeedback(wid); - if (!se->overshootDistance().isNull()) - ptrUpdatePanningFeedback(wid, -se->overshootDistance().x(), -se->overshootDistance().y(), false); - if (se->overshootDistance().isNull() && !d->overshoot.isNull()) - ptrEndPanningFeedback(wid, true); - } else -#endif - { - QPoint delta = d->overshoot - se->overshootDistance().toPoint(); - if (!delta.isNull()) - viewport()->move(viewport()->pos() + delta); - } + QPoint delta = d->overshoot - se->overshootDistance().toPoint(); + if (!delta.isNull()) + viewport()->move(viewport()->pos() + delta); + d->overshoot = se->overshootDistance().toPoint(); return true; @@ -1546,13 +1420,6 @@ void QAbstractScrollAreaPrivate::_q_vslide(int y) void QAbstractScrollAreaPrivate::_q_showOrHideScrollBars() { layoutChildren(); -#if 0 // Used to be included in Qt4 for Q_WS_WIN - // Need to re-subscribe to gestures as the content changes to make sure we - // enable/disable panning when needed. - QWidgetPrivate *dd = static_cast<QWidgetPrivate *>(QObjectPrivate::get(viewport)); - if (dd) - dd->winSetupGestures(); -#endif } QPoint QAbstractScrollAreaPrivate::contentsOffset() const diff --git a/src/widgets/widgets/qabstractscrollarea_p.h b/src/widgets/widgets/qabstractscrollarea_p.h index 732a2ab40d..6d78b9db6d 100644 --- a/src/widgets/widgets/qabstractscrollarea_p.h +++ b/src/widgets/widgets/qabstractscrollarea_p.h @@ -85,9 +85,7 @@ public: QWidget *viewport; QWidget *cornerWidget; QRect cornerPaintingRect; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - QRect reverseCornerPaintingRect; -#endif + int left, top, right, bottom; // viewport margin int xoffset, yoffset; @@ -112,11 +110,6 @@ public: inline bool viewportEvent(QEvent *event) { return q_func()->viewportEvent(event); } QScopedPointer<QObject> viewportFilter; - -#if 0 // Used to be included in Qt4 for Q_WS_WIN - bool singleFingerPanEnabled; - void setSingleFingerPanEnabled(bool on = true); -#endif }; class QAbstractScrollAreaFilter : public QObject diff --git a/src/widgets/widgets/qabstractslider.cpp b/src/widgets/widgets/qabstractslider.cpp index 129d540f50..dc325ab871 100644 --- a/src/widgets/widgets/qabstractslider.cpp +++ b/src/widgets/widgets/qabstractslider.cpp @@ -721,15 +721,10 @@ bool QAbstractSliderPrivate::scrollByDelta(Qt::Orientation orientation, Qt::Keyb offset_accumulated = 0; offset_accumulated += stepsToScrollF; -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC + // Don't scroll more than one page in any case: stepsToScroll = qBound(-pageStep, int(offset_accumulated), pageStep); -#else - // Native UI-elements on Mac can scroll hundreds of lines at a time as - // a result of acceleration. So keep the same behaviour in Qt, and - // don't restrict stepsToScroll to certain maximum (pageStep): - stepsToScroll = int(offset_accumulated); -#endif + offset_accumulated -= int(offset_accumulated); if (stepsToScroll == 0) { // We moved less than a line, but might still have accumulated partial scroll, diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp index f5708788b8..d49d9dbd66 100644 --- a/src/widgets/widgets/qabstractspinbox.cpp +++ b/src/widgets/widgets/qabstractspinbox.cpp @@ -1321,7 +1321,9 @@ void QAbstractSpinBox::contextMenuEvent(QContextMenuEvent *event) d->reset(); QAction *selAll = new QAction(tr("&Select All"), menu); +#if QT_CONFIG(shortcut) selAll->setShortcut(QKeySequence::SelectAll); +#endif menu->insertAction(d->edit->d_func()->selectAllAction, selAll); menu->removeAction(d->edit->d_func()->selectAllAction); diff --git a/src/widgets/widgets/qcalendarwidget.cpp b/src/widgets/widgets/qcalendarwidget.cpp index 78706b1854..ec19b64d4a 100644 --- a/src/widgets/widgets/qcalendarwidget.cpp +++ b/src/widgets/widgets/qcalendarwidget.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -57,6 +57,7 @@ #include <private/qapplication_p.h> #include <qbasictimer.h> #include <qstylepainter.h> +#include <qcalendar.h> #include <vector> @@ -90,16 +91,15 @@ public: QCalendarDateSectionValidator() {} virtual ~QCalendarDateSectionValidator() {} virtual Section handleKey(int key) = 0; - virtual QDate applyToDate(const QDate &date) const = 0; - virtual void setDate(const QDate &date) = 0; + virtual QDate applyToDate(QDate date, QCalendar cal = QCalendar()) const = 0; + virtual void setDate(QDate date, QCalendar cal = QCalendar()) = 0; virtual QString text() const = 0; - virtual QString text(const QDate &date, int repeat) const = 0; + virtual QString text(QDate date, QCalendar cal, int repeat) const = 0; QLocale m_locale; protected: static QString highlightString(const QString &str, int pos); -private: }; QString QCalendarDateSectionValidator::highlightString(const QString &str, int pos) @@ -117,10 +117,10 @@ class QCalendarDayValidator : public QCalendarDateSectionValidator public: QCalendarDayValidator(); virtual Section handleKey(int key) override; - virtual QDate applyToDate(const QDate &date) const override; - virtual void setDate(const QDate &date) override; + virtual QDate applyToDate(QDate date, QCalendar cal) const override; + virtual void setDate(QDate date, QCalendar cal) override; virtual QString text() const override; - virtual QString text(const QDate &date, int repeat) const override; + virtual QString text(QDate date, QCalendar cal, int repeat) const override; private: int m_pos; int m_day; @@ -181,21 +181,18 @@ QCalendarDateSectionValidator::Section QCalendarDayValidator::handleKey(int key) return QCalendarDateSectionValidator::ThisSection; } -QDate QCalendarDayValidator::applyToDate(const QDate &date) const +QDate QCalendarDayValidator::applyToDate(QDate date, QCalendar cal) const { - int day = m_day; - if (day < 1) - day = 1; - else if (day > 31) - day = 31; - if (day > date.daysInMonth()) - day = date.daysInMonth(); - return QDate(date.year(), date.month(), day); + auto parts = cal.partsFromDate(date); + if (!parts.isValid()) + return QDate(); + parts.day = qMin(qMax(1, m_day), cal.daysInMonth(parts.year, parts.month)); + return cal.dateFromParts(parts); } -void QCalendarDayValidator::setDate(const QDate &date) +void QCalendarDayValidator::setDate(QDate date, QCalendar cal) { - m_day = m_oldDay = date.day(); + m_day = m_oldDay = date.day(cal); m_pos = 0; } @@ -204,16 +201,16 @@ QString QCalendarDayValidator::text() const return highlightString(formatNumber(m_day, 2), m_pos); } -QString QCalendarDayValidator::text(const QDate &date, int repeat) const +QString QCalendarDayValidator::text(QDate date, QCalendar cal, int repeat) const { if (repeat <= 1) { - return QString::number(date.day()); + return QString::number(date.day(cal)); } else if (repeat == 2) { - return formatNumber(date.day(), 2); + return formatNumber(date.day(cal), 2); } else if (repeat == 3) { - return m_locale.dayName(date.dayOfWeek(), QLocale::ShortFormat); + return m_locale.dayName(date.dayOfWeek(cal), QLocale::ShortFormat); } else /* repeat >= 4 */ { - return m_locale.dayName(date.dayOfWeek(), QLocale::LongFormat); + return m_locale.dayName(date.dayOfWeek(cal), QLocale::LongFormat); } } @@ -225,10 +222,10 @@ class QCalendarMonthValidator : public QCalendarDateSectionValidator public: QCalendarMonthValidator(); virtual Section handleKey(int key) override; - virtual QDate applyToDate(const QDate &date) const override; - virtual void setDate(const QDate &date) override; + virtual QDate applyToDate(QDate date, QCalendar cal) const override; + virtual void setDate(QDate date, QCalendar cal) override; virtual QString text() const override; - virtual QString text(const QDate &date, int repeat) const override; + virtual QString text(QDate date, QCalendar cal, int repeat) const override; private: int m_pos; int m_month; @@ -289,23 +286,19 @@ QCalendarDateSectionValidator::Section QCalendarMonthValidator::handleKey(int ke return QCalendarDateSectionValidator::ThisSection; } -QDate QCalendarMonthValidator::applyToDate(const QDate &date) const +QDate QCalendarMonthValidator::applyToDate(QDate date, QCalendar cal) const { - int month = m_month; - if (month < 1) - month = 1; - else if (month > 12) - month = 12; - QDate newDate(date.year(), m_month, 1); - int day = date.day(); - if (day > newDate.daysInMonth()) - day = newDate.daysInMonth(); - return QDate(date.year(), month, day); + auto parts = cal.partsFromDate(date); + if (!parts.isValid()) + return QDate(); + parts.month = qMin(qMax(1, m_month), cal.monthsInYear(parts.year)); + parts.day = qMin(parts.day, cal.daysInMonth(parts.year, m_month)); // m_month or parts.month ? + return cal.dateFromParts(parts); } -void QCalendarMonthValidator::setDate(const QDate &date) +void QCalendarMonthValidator::setDate(QDate date, QCalendar cal) { - m_month = m_oldMonth = date.month(); + m_month = m_oldMonth = date.month(cal); m_pos = 0; } @@ -314,16 +307,16 @@ QString QCalendarMonthValidator::text() const return highlightString(formatNumber(m_month, 2), m_pos); } -QString QCalendarMonthValidator::text(const QDate &date, int repeat) const +QString QCalendarMonthValidator::text(QDate date, QCalendar cal, int repeat) const { if (repeat <= 1) { - return QString::number(date.month()); + return QString::number(date.month(cal)); } else if (repeat == 2) { - return formatNumber(date.month(), 2); + return formatNumber(date.month(cal), 2); } else if (repeat == 3) { - return m_locale.standaloneMonthName(date.month(), QLocale::ShortFormat); + return cal.standaloneMonthName(m_locale, date.month(cal), QLocale::ShortFormat); } else /*if (repeat >= 4)*/ { - return m_locale.standaloneMonthName(date.month(), QLocale::LongFormat); + return cal.standaloneMonthName(m_locale, date.month(cal), QLocale::LongFormat); } } @@ -335,10 +328,10 @@ class QCalendarYearValidator : public QCalendarDateSectionValidator public: QCalendarYearValidator(); virtual Section handleKey(int key) override; - virtual QDate applyToDate(const QDate &date) const override; - virtual void setDate(const QDate &date) override; + virtual QDate applyToDate(QDate date, QCalendar cal) const override; + virtual void setDate(QDate date, QCalendar cal) override; virtual QString text() const override; - virtual QString text(const QDate &date, int repeat) const override; + virtual QString text(QDate date, QCalendar cal, int repeat) const override; private: int pow10(int n); int m_pos; @@ -349,6 +342,8 @@ private: QCalendarYearValidator::QCalendarYearValidator() : QCalendarDateSectionValidator(), m_pos(0), m_year(2000), m_oldYear(2000) { + // TODO: What to use (for non-Gregorian calendars) as default year? + // Maybe 1360 for Jalali, 1420 for Islamic, etc. } int QCalendarYearValidator::pow10(int n) @@ -397,21 +392,20 @@ QCalendarDateSectionValidator::Section QCalendarYearValidator::handleKey(int key return QCalendarDateSectionValidator::ThisSection; } -QDate QCalendarYearValidator::applyToDate(const QDate &date) const +QDate QCalendarYearValidator::applyToDate(QDate date, QCalendar cal) const { - int year = m_year; - if (year < 1) - year = 1; - QDate newDate(year, date.month(), 1); - int day = date.day(); - if (day > newDate.daysInMonth()) - day = newDate.daysInMonth(); - return QDate(year, date.month(), day); + auto parts = cal.partsFromDate(date); + if (!parts.isValid()) + return QDate(); + // This widget does not support negative years (some calendars may support) + parts.year = qMax(1, m_year); + parts.day = qMin(parts.day, cal.daysInMonth(parts.year, parts.month)); + return cal.dateFromParts(parts); } -void QCalendarYearValidator::setDate(const QDate &date) +void QCalendarYearValidator::setDate(QDate date, QCalendar cal) { - m_year = m_oldYear = date.year(); + m_year = m_oldYear = date.year(cal); m_pos = 0; } @@ -420,11 +414,11 @@ QString QCalendarYearValidator::text() const return highlightString(formatNumber(m_year, 4), m_pos); } -QString QCalendarYearValidator::text(const QDate &date, int repeat) const +QString QCalendarYearValidator::text(QDate date, QCalendar cal, int repeat) const { if (repeat < 4) - return formatNumber(date.year() % 100, 2); - return QString::number(date.year()); + return formatNumber(date.year(cal) % 100, 2); + return QString::number(date.year(cal)); } /////////////////////////////////// @@ -446,18 +440,18 @@ public: QCalendarDateValidator(); ~QCalendarDateValidator(); - void handleKeyEvent(QKeyEvent *keyEvent); - QString currentText() const; + void handleKeyEvent(QKeyEvent *keyEvent, QCalendar cal); + QString currentText(QCalendar cal) const; QDate currentDate() const { return m_currentDate; } void setFormat(const QString &format); - void setInitialDate(const QDate &date); + void setInitialDate(QDate date, QCalendar cal); void setLocale(const QLocale &locale); private: void toNextToken(); void toPreviousToken(); - void applyToDate(); + void applyToDate(QCalendar cal); int countRepeat(const QString &str, int index) const; void clear(); @@ -507,17 +501,17 @@ int QCalendarDateValidator::countRepeat(const QString &str, int index) const return count; } -void QCalendarDateValidator::setInitialDate(const QDate &date) +void QCalendarDateValidator::setInitialDate(QDate date, QCalendar cal) { - m_yearValidator.setDate(date); - m_monthValidator.setDate(date); - m_dayValidator.setDate(date); + m_yearValidator.setDate(date, cal); + m_monthValidator.setDate(date, cal); + m_dayValidator.setDate(date, cal); m_initialDate = date; m_currentDate = date; m_lastSectionMove = QCalendarDateSectionValidator::ThisSection; } -QString QCalendarDateValidator::currentText() const +QString QCalendarDateValidator::currentText(QCalendar cal) const { QString str; const int numSeps = m_separators.size(); @@ -529,7 +523,7 @@ QString QCalendarDateValidator::currentText() const if (i == m_currentToken) str += token.validator->text(); else - str += token.validator->text(m_currentDate, token.repeat); + str += token.validator->text(m_currentDate, cal, token.repeat); } } return str; @@ -591,11 +585,11 @@ void QCalendarDateValidator::setFormat(const QString &format) m_separators += separator; } -void QCalendarDateValidator::applyToDate() +void QCalendarDateValidator::applyToDate(QCalendar cal) { - m_currentDate = m_yearValidator.applyToDate(m_currentDate); - m_currentDate = m_monthValidator.applyToDate(m_currentDate); - m_currentDate = m_dayValidator.applyToDate(m_currentDate); + m_currentDate = m_yearValidator.applyToDate(m_currentDate, cal); + m_currentDate = m_monthValidator.applyToDate(m_currentDate, cal); + m_currentDate = m_dayValidator.applyToDate(m_currentDate, cal); } void QCalendarDateValidator::toNextToken() @@ -614,7 +608,7 @@ void QCalendarDateValidator::toPreviousToken() m_currentToken %= m_tokens.size(); } -void QCalendarDateValidator::handleKeyEvent(QKeyEvent *keyEvent) +void QCalendarDateValidator::handleKeyEvent(QKeyEvent *keyEvent,QCalendar cal) { if (m_currentToken < 0) return; @@ -631,7 +625,7 @@ void QCalendarDateValidator::handleKeyEvent(QKeyEvent *keyEvent) m_lastSectionMove = m_tokens[m_currentToken].validator->handleKey(key); - applyToDate(); + applyToDate(cal); if (m_lastSectionMove == QCalendarDateSectionValidator::NextSection) toNextToken(); else if (m_lastSectionMove == QCalendarDateSectionValidator::PrevSection) @@ -645,7 +639,8 @@ class QCalendarTextNavigator: public QObject Q_OBJECT public: QCalendarTextNavigator(QObject *parent = 0) - : QObject(parent), m_dateText(0), m_dateFrame(0), m_dateValidator(0), m_widget(0), m_editDelay(1500), m_date(QDate::currentDate()) { } + : QObject(parent), m_dateText(0), m_dateFrame(0), m_dateValidator(0), + m_widget(0), m_editDelay(1500), m_date(QDate::currentDate()) {} QWidget *widget() const; void setWidget(QWidget *widget); @@ -653,13 +648,13 @@ public: int dateEditAcceptDelay() const; void setDateEditAcceptDelay(int delay); - void setDate(const QDate &date); + void setDate(QDate date); bool eventFilter(QObject *o, QEvent *e) override; void timerEvent(QTimerEvent *e) override; signals: - void dateChanged(const QDate &date); + void dateChanged(QDate date); void editingFinished(); private: @@ -676,6 +671,7 @@ private: int m_editDelay; QDate m_date; + const QCalendar m_calendar; }; QWidget *QCalendarTextNavigator::widget() const @@ -688,7 +684,7 @@ void QCalendarTextNavigator::setWidget(QWidget *widget) m_widget = widget; } -void QCalendarTextNavigator::setDate(const QDate &date) +void QCalendarTextNavigator::setDate(QDate date) { m_date = date; } @@ -700,7 +696,7 @@ void QCalendarTextNavigator::updateDateLabel() m_acceptTimer.start(m_editDelay, this); - m_dateText->setText(m_dateValidator->currentText()); + m_dateText->setText(m_dateValidator->currentText(m_calendar)); QSize s = m_dateFrame->sizeHint(); QRect r = m_widget->geometry(); // later, just the table section @@ -740,7 +736,7 @@ void QCalendarTextNavigator::createDateLabel() m_dateValidator = new QCalendarDateValidator(); m_dateValidator->setLocale(m_widget->locale()); m_dateValidator->setFormat(m_widget->locale().dateFormat(QLocale::ShortFormat)); - m_dateValidator->setInitialDate(m_date); + m_dateValidator->setInitialDate(m_date, m_calendar); m_dateFrame->setAutoFillBackground(true); m_dateFrame->setBackgroundRole(QPalette::Window); @@ -775,7 +771,7 @@ bool QCalendarTextNavigator::eventFilter(QObject *o, QEvent *e) #endif } else if (e->type() == QEvent::KeyPress) { createDateLabel(); - m_dateValidator->handleKeyEvent(ke); + m_dateValidator->handleKeyEvent(ke, m_calendar); updateDateLabel(); } ke->accept(); @@ -895,12 +891,15 @@ public: } void showMonth(int year, int month); - void setDate(const QDate &d); + void setDate(QDate d); - void setMinimumDate(const QDate &date); - void setMaximumDate(const QDate &date); + void setCalendar(QCalendar c); + QCalendar calendar() const; - void setRange(const QDate &min, const QDate &max); + void setMinimumDate(QDate date); + void setMaximumDate(QDate date); + + void setRange(QDate min, QDate max); void setHorizontalHeaderFormat(QCalendarWidget::HorizontalHeaderFormat format); @@ -914,7 +913,7 @@ public: Qt::DayOfWeek dayOfWeekForColumn(int section) const; int columnForDayOfWeek(Qt::DayOfWeek day) const; QDate dateForCell(int row, int column) const; - void cellForDate(const QDate &date, int *row, int *column) const; + void cellForDate(QDate date, int *row, int *column) const; QString dayName(Qt::DayOfWeek day) const; void setView(QCalendarView *view) @@ -922,10 +921,11 @@ public: void internalUpdate(); QDate referenceDate() const; - int columnForFirstOfMonth(const QDate &date) const; + int columnForFirstOfMonth(QDate date) const; int m_firstColumn; int m_firstRow; + QCalendar m_calendar; QDate m_date; QDate m_minimumDate; QDate m_maximumDate; @@ -951,9 +951,9 @@ public: virtual void keyboardSearch(const QString & search) override { Q_UNUSED(search) } signals: - void showDate(const QDate &date); - void changeDate(const QDate &date, bool changeMonth); - void clicked(const QDate &date); + void showDate(QDate date); + void changeDate(QDate date, bool changeMonth); + void clicked(QDate date); void editingFinished(); protected: QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) override; @@ -984,8 +984,8 @@ QCalendarModel::QCalendarModel(QObject *parent) m_date(QDate::currentDate()), m_minimumDate(QDate::fromJulianDay(1)), m_maximumDate(9999, 12, 31), - m_shownYear(m_date.year()), - m_shownMonth(m_date.month()), + m_shownYear(m_date.year(m_calendar)), + m_shownMonth(m_date.month(m_calendar)), m_firstDay(QLocale().firstDayOfWeek()), m_horizontalHeaderFormat(QCalendarWidget::ShortDayNames), m_weekNumbersShown(true), @@ -1028,9 +1028,10 @@ will be rendered in 2nd or 3rd row, showing more dates from previous month. */ QDate QCalendarModel::referenceDate() const { + // TODO: Check this int refDay = 1; while (refDay <= 31) { - QDate refDate(m_shownYear, m_shownMonth, refDay); + QDate refDate(m_shownYear, m_shownMonth, refDay, m_calendar); if (refDate.isValid()) return refDate; refDay += 1; @@ -1038,9 +1039,10 @@ QDate QCalendarModel::referenceDate() const return QDate(); } -int QCalendarModel::columnForFirstOfMonth(const QDate &date) const +int QCalendarModel::columnForFirstOfMonth(QDate date) const { - return (columnForDayOfWeek(static_cast<Qt::DayOfWeek>(date.dayOfWeek())) - (date.day() % 7) + 8) % 7; + return (columnForDayOfWeek(static_cast<Qt::DayOfWeek>(m_calendar.dayOfWeek(date))) + - (date.day(m_calendar) % 7) + 8) % 7; } QDate QCalendarModel::dateForCell(int row, int column) const @@ -1056,11 +1058,12 @@ QDate QCalendarModel::dateForCell(int row, int column) const if (columnForFirstOfShownMonth - m_firstColumn < MinimumDayOffset) row -= 1; - const int requestedDay = 7 * (row - m_firstRow) + column - columnForFirstOfShownMonth - refDate.day() + 1; + const int requestedDay = + 7 * (row - m_firstRow) + column - columnForFirstOfShownMonth - refDate.day(m_calendar) + 1; return refDate.addDays(requestedDay); } -void QCalendarModel::cellForDate(const QDate &date, int *row, int *column) const +void QCalendarModel::cellForDate(QDate date, int *row, int *column) const { if (!row && !column) return; @@ -1075,7 +1078,8 @@ void QCalendarModel::cellForDate(const QDate &date, int *row, int *column) const return; const int columnForFirstOfShownMonth = columnForFirstOfMonth(refDate); - const int requestedPosition = refDate.daysTo(date) - m_firstColumn + columnForFirstOfShownMonth + refDate.day() - 1; + const int requestedPosition = (refDate.daysTo(date) - m_firstColumn + + columnForFirstOfShownMonth + refDate.day(m_calendar) - 1); int c = requestedPosition % 7; int r = requestedPosition / 7; @@ -1148,7 +1152,7 @@ QTextCharFormat QCalendarModel::formatForCell(int row, int col) const format.merge(m_dateFormats.value(date)); if(date < m_minimumDate || date > m_maximumDate) format.setBackground(pal.brush(cg, QPalette::Window)); - if (m_shownMonth != date.month()) + if (m_shownMonth != date.month(m_calendar)) format.setForeground(pal.brush(QPalette::Disabled, QPalette::Text)); } return format; @@ -1174,7 +1178,7 @@ QVariant QCalendarModel::data(const QModelIndex &index, int role) const return dayName(dayOfWeekForColumn(column)); QDate date = dateForCell(row, column); if (date.isValid()) - return date.day(); + return date.day(m_calendar); return QString(); } @@ -1202,7 +1206,7 @@ Qt::ItemFlags QCalendarModel::flags(const QModelIndex &index) const return QAbstractTableModel::flags(index); } -void QCalendarModel::setDate(const QDate &d) +void QCalendarModel::setDate(QDate d) { m_date = d; if (m_date < m_minimumDate) @@ -1211,6 +1215,20 @@ void QCalendarModel::setDate(const QDate &d) m_date = m_maximumDate; } +void QCalendarModel::setCalendar(QCalendar c) +{ + m_calendar = c; + m_shownYear = m_date.year(c); + m_shownMonth = m_date.month(c); + internalUpdate(); + m_view->internalUpdate(); +} + +QCalendar QCalendarModel::calendar() const +{ + return m_calendar; +} + void QCalendarModel::showMonth(int year, int month) { if (m_shownYear == year && m_shownMonth == month) @@ -1222,7 +1240,7 @@ void QCalendarModel::showMonth(int year, int month) internalUpdate(); } -void QCalendarModel::setMinimumDate(const QDate &d) +void QCalendarModel::setMinimumDate(QDate d) { if (!d.isValid() || d == m_minimumDate) return; @@ -1235,7 +1253,7 @@ void QCalendarModel::setMinimumDate(const QDate &d) internalUpdate(); } -void QCalendarModel::setMaximumDate(const QDate &d) +void QCalendarModel::setMaximumDate(QDate d) { if (!d.isValid() || d == m_maximumDate) return; @@ -1248,7 +1266,7 @@ void QCalendarModel::setMaximumDate(const QDate &d) internalUpdate(); } -void QCalendarModel::setRange(const QDate &min, const QDate &max) +void QCalendarModel::setRange(QDate min, QDate max) { m_minimumDate = min; m_maximumDate = max; @@ -1341,6 +1359,8 @@ QModelIndex QCalendarView::moveCursor(CursorAction cursorAction, Qt::KeyboardMod if (!calendarModel) return QTableView::moveCursor(cursorAction, modifiers); + QCalendar cal = calendarModel->calendar(); + if (readOnly) return currentIndex(); @@ -1359,17 +1379,27 @@ QModelIndex QCalendarView::moveCursor(CursorAction cursorAction, Qt::KeyboardMod case QAbstractItemView::MoveRight: currentDate = currentDate.addDays(isRightToLeft() ? -1 : 1); break; - case QAbstractItemView::MoveHome: - currentDate = QDate(currentDate.year(), currentDate.month(), 1); + case QAbstractItemView::MoveHome: { + auto parts = cal.partsFromDate(currentDate); + if (parts.isValid()) { + parts.day = 1; + currentDate = cal.dateFromParts(parts); + } + } break; - case QAbstractItemView::MoveEnd: - currentDate = QDate(currentDate.year(), currentDate.month(), currentDate.daysInMonth()); + case QAbstractItemView::MoveEnd: { + auto parts = cal.partsFromDate(currentDate); + if (parts.isValid()) { + parts.day = cal.daysInMonth(parts.year, parts.month); + currentDate = cal.dateFromParts(parts); + } + } break; case QAbstractItemView::MovePageUp: - currentDate = currentDate.addMonths(-1); + currentDate = currentDate.addMonths(-1, cal); break; case QAbstractItemView::MovePageDown: - currentDate = currentDate.addMonths(1); + currentDate = currentDate.addMonths(1, cal); break; case QAbstractItemView::MoveNext: case QAbstractItemView::MovePrevious: @@ -1422,8 +1452,9 @@ void QCalendarView::wheelEvent(QWheelEvent *event) const int numDegrees = event->angleDelta().y() / 8; const int numSteps = numDegrees / 15; const QModelIndex index = currentIndex(); - QDate currentDate = static_cast<QCalendarModel*>(model())->dateForCell(index.row(), index.column()); - currentDate = currentDate.addMonths(-numSteps); + QCalendarModel *calendarModel = static_cast<QCalendarModel*>(model()); + QDate currentDate = calendarModel->dateForCell(index.row(), index.column()); + currentDate = currentDate.addMonths(-numSteps, calendarModel->calendar()); emit showDate(currentDate); } #endif @@ -1566,7 +1597,7 @@ public: { } virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; - void paintCell(QPainter *painter, const QRect &rect, const QDate &date) const; + void paintCell(QPainter *painter, const QRect &rect, QDate date) const; private: QCalendarWidgetPrivate *calendarWidgetPrivate; @@ -1585,7 +1616,6 @@ protected: { Q_UNUSED(e) -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC QStyleOptionToolButton opt; initStyleOption(&opt); @@ -1598,7 +1628,7 @@ protected: toolPalette.setColor(QPalette::ButtonText, toolPalette.color(QPalette::HighlightedText)); setPalette(toolPalette); } -#endif + QToolButton::paintEvent(e); } }; @@ -1628,11 +1658,11 @@ public: void showMonth(int year, int month); void update(); - void paintCell(QPainter *painter, const QRect &rect, const QDate &date) const; + void paintCell(QPainter *painter, const QRect &rect, QDate date) const; - void _q_slotShowDate(const QDate &date); - void _q_slotChangeDate(const QDate &date); - void _q_slotChangeDate(const QDate &date, bool changeMonth); + void _q_slotShowDate(QDate date); + void _q_slotChangeDate(QDate date); + void _q_slotChangeDate(QDate date, bool changeMonth); void _q_editingFinished(); void _q_monthChanged(QAction*); void _q_prevMonthClicked(); @@ -1645,7 +1675,7 @@ public: void updateMonthMenu(); void updateMonthMenuNames(); void updateNavigationBar(); - void updateCurrentPage(const QDate &newDate); + void updateCurrentPage(QDate newDate); inline QDate getCurrentDate(); void setNavigatorEnabled(bool enable); @@ -1684,7 +1714,7 @@ void QCalendarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opt } } -void QCalendarDelegate::paintCell(QPainter *painter, const QRect &rect, const QDate &date) const +void QCalendarDelegate::paintCell(QPainter *painter, const QRect &rect, QDate date) const { storedOption.rect = rect; int row = -1; @@ -1757,7 +1787,7 @@ void QCalendarWidgetPrivate::createNavigationBar(QWidget *widget) monthButton->setPopupMode(QToolButton::InstantPopup); monthMenu = new QMenu(monthButton); for (int i = 1; i <= 12; i++) { - QString monthName(q->locale().standaloneMonthName(i, QLocale::LongFormat)); + QString monthName(m_model->m_calendar.standaloneMonthName(q->locale(), i, QLocale::LongFormat)); QAction *act = monthMenu->addAction(monthName); act->setData(i); monthToAction[i] = act; @@ -1773,8 +1803,8 @@ void QCalendarWidgetPrivate::createNavigationBar(QWidget *widget) monthButton->setFont(font); yearButton->setFont(font); yearEdit->setFrame(false); - yearEdit->setMinimum(m_model->m_minimumDate.year()); - yearEdit->setMaximum(m_model->m_maximumDate.year()); + yearEdit->setMinimum(m_model->m_minimumDate.year(m_model->m_calendar)); + yearEdit->setMaximum(m_model->m_maximumDate.year(m_model->m_calendar)); yearEdit->hide(); spaceHolder = new QSpacerItem(0,0); @@ -1804,7 +1834,7 @@ void QCalendarWidgetPrivate::createNavigationBar(QWidget *widget) yearEdit->setObjectName(QLatin1String("qt_calendar_yearedit")); updateMonthMenu(); - showMonth(m_model->m_date.year(), m_model->m_date.month()); + showMonth(m_model->m_date.year(m_model->m_calendar), m_model->m_date.month(m_model->m_calendar)); } void QCalendarWidgetPrivate::updateButtonIcons() @@ -1816,22 +1846,24 @@ void QCalendarWidgetPrivate::updateButtonIcons() void QCalendarWidgetPrivate::updateMonthMenu() { - int beg = 1, end = 12; + int maxMonths = m_model->m_calendar.monthsInYear(m_model->m_shownYear); + int beg = 1, end = maxMonths; bool prevEnabled = true; bool nextEnabled = true; - if (m_model->m_shownYear == m_model->m_minimumDate.year()) { - beg = m_model->m_minimumDate.month(); - if (m_model->m_shownMonth == m_model->m_minimumDate.month()) + QCalendar cal = m_model->calendar(); + if (m_model->m_shownYear == m_model->m_minimumDate.year(cal)) { + beg = m_model->m_minimumDate.month(cal); + if (m_model->m_shownMonth == m_model->m_minimumDate.month(cal)) prevEnabled = false; } - if (m_model->m_shownYear == m_model->m_maximumDate.year()) { - end = m_model->m_maximumDate.month(); - if (m_model->m_shownMonth == m_model->m_maximumDate.month()) + if (m_model->m_shownYear == m_model->m_maximumDate.year(cal)) { + end = m_model->m_maximumDate.month(cal); + if (m_model->m_shownMonth == m_model->m_maximumDate.month(cal)) nextEnabled = false; } prevMonth->setEnabled(prevEnabled); nextMonth->setEnabled(nextEnabled); - for (int i = 1; i <= 12; i++) { + for (int i = 1; i <= maxMonths; i++) { bool monthEnabled = true; if (i < beg || i > end) monthEnabled = false; @@ -1844,14 +1876,15 @@ void QCalendarWidgetPrivate::updateMonthMenuNames() Q_Q(QCalendarWidget); for (int i = 1; i <= 12; i++) { - QString monthName(q->locale().standaloneMonthName(i, QLocale::LongFormat)); + QString monthName(m_model->m_calendar.standaloneMonthName(q->locale(), i, QLocale::LongFormat)); monthToAction[i]->setText(monthName); } } -void QCalendarWidgetPrivate::updateCurrentPage(const QDate &date) +void QCalendarWidgetPrivate::updateCurrentPage(QDate date) { Q_Q(QCalendarWidget); + QCalendar cal = m_model->calendar(); QDate newDate = date; QDate minDate = q->minimumDate(); @@ -1860,7 +1893,7 @@ void QCalendarWidgetPrivate::updateCurrentPage(const QDate &date) newDate = minDate; if (maxDate.isValid()&& maxDate.daysTo(newDate) > 0) newDate = maxDate; - showMonth(newDate.year(), newDate.month()); + showMonth(newDate.year(cal), newDate.month(cal)); int row = -1, col = -1; m_model->cellForDate(newDate, &row, &col); if (row != -1 && col != -1) @@ -1874,7 +1907,7 @@ void QCalendarWidgetPrivate::_q_monthChanged(QAction *act) { monthButton->setText(act->text()); QDate currentDate = getCurrentDate(); - QDate newDate = currentDate.addMonths(act->data().toInt()-currentDate.month()); + QDate newDate = currentDate.addMonths(act->data().toInt() - currentDate.month(m_model->m_calendar), m_model->m_calendar); updateCurrentPage(newDate); } @@ -1886,27 +1919,28 @@ QDate QCalendarWidgetPrivate::getCurrentDate() void QCalendarWidgetPrivate::_q_prevMonthClicked() { - QDate currentDate = getCurrentDate().addMonths(-1); + QDate currentDate = getCurrentDate().addMonths(-1, m_model->m_calendar); updateCurrentPage(currentDate); } void QCalendarWidgetPrivate::_q_nextMonthClicked() { - QDate currentDate = getCurrentDate().addMonths(1); + QDate currentDate = getCurrentDate().addMonths(1, m_model->m_calendar); updateCurrentPage(currentDate); } void QCalendarWidgetPrivate::_q_yearEditingFinished() { Q_Q(QCalendarWidget); - yearButton->setText(yearEdit->text()); + yearButton->setText(q->locale().toString(yearEdit->value())); yearEdit->hide(); q->setFocusPolicy(oldFocusPolicy); qApp->removeEventFilter(q); spaceHolder->changeSize(0, 0); yearButton->show(); QDate currentDate = getCurrentDate(); - currentDate = currentDate.addYears(yearEdit->text().toInt() - currentDate.year()); + int newYear = q->locale().toInt(yearEdit->text()); + currentDate = currentDate.addYears(newYear - currentDate.year(m_model->m_calendar), m_model->m_calendar); updateCurrentPage(currentDate); } @@ -1945,7 +1979,7 @@ void QCalendarWidgetPrivate::updateNavigationBar() { Q_Q(QCalendarWidget); - QString monthName = q->locale().standaloneMonthName(m_model->m_shownMonth, QLocale::LongFormat); + QString monthName = m_model->m_calendar.standaloneMonthName(q->locale(), m_model->m_shownMonth, QLocale::LongFormat); monthButton->setText(monthName); yearEdit->setValue(m_model->m_shownYear); @@ -1965,29 +1999,29 @@ void QCalendarWidgetPrivate::update() } } -void QCalendarWidgetPrivate::paintCell(QPainter *painter, const QRect &rect, const QDate &date) const +void QCalendarWidgetPrivate::paintCell(QPainter *painter, const QRect &rect, QDate date) const { Q_Q(const QCalendarWidget); q->paintCell(painter, rect, date); } -void QCalendarWidgetPrivate::_q_slotShowDate(const QDate &date) +void QCalendarWidgetPrivate::_q_slotShowDate(QDate date) { updateCurrentPage(date); } -void QCalendarWidgetPrivate::_q_slotChangeDate(const QDate &date) +void QCalendarWidgetPrivate::_q_slotChangeDate(QDate date) { _q_slotChangeDate(date, true); } -void QCalendarWidgetPrivate::_q_slotChangeDate(const QDate &date, bool changeMonth) +void QCalendarWidgetPrivate::_q_slotChangeDate(QDate date, bool changeMonth) { QDate oldDate = m_model->m_date; m_model->setDate(date); QDate newDate = m_model->m_date; if (changeMonth) - showMonth(newDate.year(), newDate.month()); + showMonth(newDate.year(m_model->m_calendar), newDate.month(m_model->m_calendar)); if (oldDate != newDate) { update(); Q_Q(QCalendarWidget); @@ -2243,7 +2277,7 @@ QSize QCalendarWidget::minimumSizeHint() const QFontMetrics fm = d->monthButton->fontMetrics(); int monthW = 0; for (int i = 1; i < 12; i++) { - QString monthName = locale().standaloneMonthName(i, QLocale::LongFormat); + QString monthName = d->m_model->m_calendar.standaloneMonthName(locale(), i, QLocale::LongFormat); monthW = qMax(monthW, fm.boundingRect(monthName).width()); } const int buttonDecoMargin = d->monthButton->sizeHint().width() - fm.boundingRect(d->monthButton->text()).width(); @@ -2303,7 +2337,8 @@ void QCalendarWidget::setSelectedDate(const QDate &date) d->m_model->setDate(date); d->update(); QDate newDate = d->m_model->m_date; - d->showMonth(newDate.year(), newDate.month()); + QCalendar cal = d->m_model->m_calendar; + d->showMonth(newDate.year(cal), newDate.month(cal)); emit selectionChanged(); } @@ -2349,14 +2384,15 @@ void QCalendarWidget::setCurrentPage(int year, int month) { Q_D(QCalendarWidget); QDate currentDate = d->getCurrentDate(); - int day = currentDate.day(); - int daysInMonths = QDate(year, month, 1).daysInMonth(); + QCalendar cal = d->m_model->m_calendar; + int day = currentDate.day(cal); + int daysInMonths = cal.daysInMonth(year, month); if (day > daysInMonths) day = daysInMonths; d->showMonth(year, month); - QDate newDate(year, month, day); + QDate newDate(year, month, day, d->m_model->m_calendar); int row = -1, col = -1; d->m_model->cellForDate(newDate, &row, &col); if (row != -1 && col != -1) { @@ -2374,9 +2410,10 @@ void QCalendarWidget::setCurrentPage(int year, int month) void QCalendarWidget::showNextMonth() { + Q_D(const QCalendarWidget); int year = yearShown(); int month = monthShown(); - if (month == 12) { + if (month == d->m_model->m_calendar.maxMonthsInYear()) { ++year; month = 1; } else { @@ -2394,11 +2431,13 @@ void QCalendarWidget::showNextMonth() void QCalendarWidget::showPreviousMonth() { + Q_D(const QCalendarWidget); + int year = yearShown(); int month = monthShown(); if (month == 1) { --year; - month = 12; + month = d->m_model->m_calendar.maxMonthsInYear(); } else { --month; } @@ -2444,8 +2483,10 @@ void QCalendarWidget::showPreviousYear() */ void QCalendarWidget::showSelectedDate() { + Q_D(const QCalendarWidget); + QDate currentDate = selectedDate(); - setCurrentPage(currentDate.year(), currentDate.month()); + setCurrentPage(currentDate.year(d->m_model->m_calendar), currentDate.month(d->m_model->m_calendar)); } /*! @@ -2455,8 +2496,10 @@ void QCalendarWidget::showSelectedDate() */ void QCalendarWidget::showToday() { + Q_D(const QCalendarWidget); + QDate currentDate = QDate::currentDate(); - setCurrentPage(currentDate.year(), currentDate.month()); + setCurrentPage(currentDate.year(d->m_model->m_calendar), currentDate.month(d->m_model->m_calendar)); } /*! @@ -2499,12 +2542,12 @@ void QCalendarWidget::setMinimumDate(const QDate &date) QDate oldDate = d->m_model->m_date; d->m_model->setMinimumDate(date); - d->yearEdit->setMinimum(d->m_model->m_minimumDate.year()); + d->yearEdit->setMinimum(d->m_model->m_minimumDate.year(d->m_model->m_calendar)); d->updateMonthMenu(); QDate newDate = d->m_model->m_date; if (oldDate != newDate) { d->update(); - d->showMonth(newDate.year(), newDate.month()); + d->showMonth(newDate.year(d->m_model->m_calendar), newDate.month(d->m_model->m_calendar)); d->m_navigator->setDate(newDate); emit selectionChanged(); } @@ -2550,12 +2593,12 @@ void QCalendarWidget::setMaximumDate(const QDate &date) QDate oldDate = d->m_model->m_date; d->m_model->setMaximumDate(date); - d->yearEdit->setMaximum(d->m_model->m_maximumDate.year()); + d->yearEdit->setMaximum(d->m_model->m_maximumDate.year(d->m_model->m_calendar)); d->updateMonthMenu(); QDate newDate = d->m_model->m_date; if (oldDate != newDate) { d->update(); - d->showMonth(newDate.year(), newDate.month()); + d->showMonth(newDate.year(d->m_model->m_calendar), newDate.month(d->m_model->m_calendar)); d->m_navigator->setDate(newDate); emit selectionChanged(); } @@ -2590,13 +2633,13 @@ void QCalendarWidget::setDateRange(const QDate &min, const QDate &max) QDate oldDate = d->m_model->m_date; d->m_model->setRange(min, max); - d->yearEdit->setMinimum(d->m_model->m_minimumDate.year()); - d->yearEdit->setMaximum(d->m_model->m_maximumDate.year()); + d->yearEdit->setMinimum(d->m_model->m_minimumDate.year(d->m_model->m_calendar)); + d->yearEdit->setMaximum(d->m_model->m_maximumDate.year(d->m_model->m_calendar)); d->updateMonthMenu(); QDate newDate = d->m_model->m_date; if (oldDate != newDate) { d->update(); - d->showMonth(newDate.year(), newDate.month()); + d->showMonth(newDate.year(d->m_model->m_calendar), newDate.month(d->m_model->m_calendar)); d->m_navigator->setDate(newDate); emit selectionChanged(); } @@ -2703,6 +2746,22 @@ bool QCalendarWidget::isGridVisible() const return d->m_view->showGrid(); } +QCalendar QCalendarWidget::calendar() const +{ + Q_D(const QCalendarWidget); + return d->m_model->m_calendar; +} + +void QCalendarWidget::setCalendar(QCalendar c) +{ + Q_D(QCalendarWidget); + d->m_model->setCalendar(c); + d->updateMonthMenuNames(); + d->yearEdit->setMinimum(d->m_model->m_minimumDate.year(d->m_model->m_calendar)); + d->yearEdit->setMaximum(d->m_model->m_maximumDate.year(d->m_model->m_calendar)); + d->updateNavigationBar(); +} + void QCalendarWidget::setGridVisible(bool show) { Q_D(QCalendarWidget); @@ -3043,6 +3102,9 @@ bool QCalendarWidget::event(QEvent *event) d->updateMonthMenuNames(); d->updateNavigationBar(); d->m_view->updateGeometry(); + // TODO: fix this known bug of calendaring API: + // Changing locale before calendar works, but reverse order causes + // invalid month names (in C Locale apparently). break; case QEvent::FontChange: case QEvent::ApplicationFontChange: diff --git a/src/widgets/widgets/qcalendarwidget.h b/src/widgets/widgets/qcalendarwidget.h index 44ba340289..08825a0ff3 100644 --- a/src/widgets/widgets/qcalendarwidget.h +++ b/src/widgets/widgets/qcalendarwidget.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -112,6 +112,9 @@ public: bool isNavigationBarVisible() const; bool isGridVisible() const; + QCalendar calendar() const; + void setCalendar(QCalendar calendar); + SelectionMode selectionMode() const; void setSelectionMode(SelectionMode mode); diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 8b54d61e8e..e73c63f657 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -64,7 +64,9 @@ #include <qheaderview.h> #include <qmath.h> #include <qmetaobject.h> +#if QT_CONFIG(proxymodel) #include <qabstractproxymodel.h> +#endif #include <qstylehints.h> #include <private/qguiapplication_p.h> #include <private/qhighdpiscaling_p.h> @@ -200,6 +202,7 @@ QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewIt void QComboBoxPrivate::_q_completerActivated(const QModelIndex &index) { Q_Q(QComboBox); +#if QT_CONFIG(proxymodel) if (index.isValid() && q->completer()) { QAbstractProxyModel *proxy = qobject_cast<QAbstractProxyModel *>(q->completer()->completionModel()); if (proxy) { @@ -221,6 +224,7 @@ void QComboBoxPrivate::_q_completerActivated(const QModelIndex &index) emitActivated(currentIndex); } } +#endif # ifdef QT_KEYPAD_NAVIGATION if ( QApplicationPrivate::keypadNavigationEnabled() @@ -443,13 +447,6 @@ void QComboBoxPrivateContainer::paintEvent(QPaintEvent *e) void QComboBoxPrivateContainer::leaveEvent(QEvent *) { -// On Mac using the Mac style we want to clear the selection -// when the mouse moves outside the popup. -#if 0 // Used to be included in Qt4 for Q_WS_MAC - QStyleOptionComboBox opt = comboStyleOption(); - if (combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo)) - view->clearSelection(); -#endif } QComboBoxPrivateContainer::QComboBoxPrivateContainer(QAbstractItemView *itemView, QComboBox *parent) diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp index 3c92d4be0e..e26993fb23 100644 --- a/src/widgets/widgets/qdatetimeedit.cpp +++ b/src/widgets/widgets/qdatetimeedit.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -312,6 +312,22 @@ void QDateTimeEdit::setTime(const QTime &time) } +QCalendar QDateTimeEdit::calendar() const +{ + Q_D(const QDateTimeEdit); + return d->calendar; +} + +void QDateTimeEdit::setCalendar(QCalendar calendar) +{ + Q_D(QDateTimeEdit); + // Set invalid date time to prevent runtime crashes on calendar change + QDateTime previousValue = d->value.toDateTime(); + setDateTime(QDateTime()); + d->setCalendar(calendar); + setDateTime(previousValue); +} + /*! \property QDateTimeEdit::minimumDateTime \since 4.4 @@ -1125,16 +1141,6 @@ void QDateTimeEdit::keyPressEvent(QKeyEvent *event) select = false; break; } -#if 0 // Used to be included in Qt4 for Q_WS_MAC - else -#ifdef QT_KEYPAD_NAVIGATION - if (!QApplicationPrivate::keypadNavigationEnabled()) -#endif - { - select = (event->modifiers() & Qt::ShiftModifier); - break; - } -#endif } Q_FALLTHROUGH(); case Qt::Key_Backtab: @@ -1354,7 +1360,7 @@ void QDateTimeEdit::stepBy(int steps) QString QDateTimeEdit::textFromDateTime(const QDateTime &dateTime) const { Q_D(const QDateTimeEdit); - return locale().toString(dateTime, d->displayFormat); + return locale().toString(dateTime, d->displayFormat, d->calendar); } @@ -1646,7 +1652,7 @@ QDateEdit::~QDateEdit() QDateTimeEditPrivate::QDateTimeEditPrivate() - : QDateTimeParser(QVariant::DateTime, QDateTimeParser::DateTimeEdit) + : QDateTimeParser(QVariant::DateTime, QDateTimeParser::DateTimeEdit, QCalendar()) { hasHadFocus = false; formatExplicitlySet = false; @@ -1671,10 +1677,6 @@ QDateTimeEditPrivate::QDateTimeEditPrivate() #endif } -QDateTimeEditPrivate::~QDateTimeEditPrivate() -{ -} - void QDateTimeEditPrivate::updateTimeSpec() { minimum = minimum.toDateTime().toTimeSpec(spec); @@ -2018,8 +2020,7 @@ QDateTime QDateTimeEditPrivate::stepBy(int sectionIndex, int steps, bool test) c val = (wrapping ? min + val - max - 1 : max); } - - const int oldDay = v.date().day(); + const int oldDay = v.date().day(calendar); setDigit(v, sectionIndex, val); // if this sets year or month it will make @@ -2038,10 +2039,10 @@ QDateTime QDateTimeEditPrivate::stepBy(int sectionIndex, int steps, bool test) c if (steps > 0) { setDigit(v, sectionIndex, min); if (!(sn.type & DaySectionMask) && sections & DateSectionMask) { - const int daysInMonth = v.date().daysInMonth(); - if (v.date().day() < oldDay && v.date().day() < daysInMonth) { + const int daysInMonth = v.date().daysInMonth(calendar); + if (v.date().day(calendar) < oldDay && v.date().day(calendar) < daysInMonth) { const int adds = qMin(oldDay, daysInMonth); - v = v.addDays(adds - v.date().day()); + v = v.addDays(adds - v.date().day(calendar)); } } @@ -2053,10 +2054,10 @@ QDateTime QDateTimeEditPrivate::stepBy(int sectionIndex, int steps, bool test) c } else { setDigit(v, sectionIndex, max); if (!(sn.type & DaySectionMask) && sections & DateSectionMask) { - const int daysInMonth = v.date().daysInMonth(); - if (v.date().day() < oldDay && v.date().day() < daysInMonth) { + const int daysInMonth = v.date().daysInMonth(calendar); + if (v.date().day(calendar) < oldDay && v.date().day(calendar) < daysInMonth) { const int adds = qMin(oldDay, daysInMonth); - v = v.addDays(adds - v.date().day()); + v = v.addDays(adds - v.date().day(calendar)); } } @@ -2070,7 +2071,7 @@ QDateTime QDateTimeEditPrivate::stepBy(int sectionIndex, int steps, bool test) c setDigit(v, sectionIndex, (steps > 0 ? localmax : localmin)); } } - if (!test && oldDay != v.date().day() && !(sn.type & DaySectionMask)) { + if (!test && oldDay != v.date().day(calendar) && !(sn.type & DaySectionMask)) { // this should not happen when called from stepEnabled cachedDay = qMax<int>(oldDay, cachedDay); } @@ -2523,7 +2524,7 @@ void QDateTimeEditPrivate::initCalendarPopup(QCalendarWidget *cw) { Q_Q(QDateTimeEdit); if (!monthCalendar) { - monthCalendar = new QCalendarPopup(q, cw); + monthCalendar = new QCalendarPopup(q, cw, calendar); monthCalendar->setObjectName(QLatin1String("qt_datetimedit_calendar")); QObject::connect(monthCalendar, SIGNAL(newDateSelected(QDate)), q, SLOT(setDate(QDate))); QObject::connect(monthCalendar, SIGNAL(hidingCalendar(QDate)), q, SLOT(setDate(QDate))); @@ -2584,8 +2585,8 @@ void QDateTimeEditPrivate::syncCalendarWidget() } } -QCalendarPopup::QCalendarPopup(QWidget * parent, QCalendarWidget *cw) - : QWidget(parent, Qt::Popup) +QCalendarPopup::QCalendarPopup(QWidget *parent, QCalendarWidget *cw, QCalendar ca) + : QWidget(parent, Qt::Popup), calendarSystem(ca) { setAttribute(Qt::WA_WindowPropagation); @@ -2601,6 +2602,7 @@ QCalendarWidget *QCalendarPopup::verifyCalendarInstance() { if (calendar.isNull()) { QCalendarWidget *cw = new QCalendarWidget(this); + cw->setCalendar(calendarSystem); cw->setVerticalHeaderFormat(QCalendarWidget::NoVerticalHeader); #ifdef QT_KEYPAD_NAVIGATION if (QApplicationPrivate::keypadNavigationEnabled()) @@ -2634,13 +2636,13 @@ void QCalendarPopup::setCalendarWidget(QCalendarWidget *cw) } -void QCalendarPopup::setDate(const QDate &date) +void QCalendarPopup::setDate(QDate date) { oldDate = date; verifyCalendarInstance()->setSelectedDate(date); } -void QCalendarPopup::setDateRange(const QDate &min, const QDate &max) +void QCalendarPopup::setDateRange(QDate min, QDate max) { QCalendarWidget *cw = verifyCalendarInstance(); cw->setMinimumDate(min); @@ -2684,7 +2686,7 @@ void QCalendarPopup::dateSelectionChanged() dateChanged = true; emit newDateSelected(verifyCalendarInstance()->selectedDate()); } -void QCalendarPopup::dateSelected(const QDate &date) +void QCalendarPopup::dateSelected(QDate date) { dateChanged = true; emit activated(date); diff --git a/src/widgets/widgets/qdatetimeedit.h b/src/widgets/widgets/qdatetimeedit.h index b6fb35fc71..03994675ae 100644 --- a/src/widgets/widgets/qdatetimeedit.h +++ b/src/widgets/widgets/qdatetimeedit.h @@ -42,6 +42,7 @@ #include <QtWidgets/qtwidgetsglobal.h> #include <QtCore/qdatetime.h> +#include <QtCore/qcalendar.h> #include <QtCore/qvariant.h> #include <QtWidgets/qabstractspinbox.h> @@ -102,6 +103,9 @@ public: QDate date() const; QTime time() const; + QCalendar calendar() const; + void setCalendar(QCalendar calendar); + QDateTime minimumDateTime() const; void clearMinimumDateTime(); void setMinimumDateTime(const QDateTime &dt); diff --git a/src/widgets/widgets/qdatetimeedit_p.h b/src/widgets/widgets/qdatetimeedit_p.h index c05e7d9b48..dcf8863c8b 100644 --- a/src/widgets/widgets/qdatetimeedit_p.h +++ b/src/widgets/widgets/qdatetimeedit_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -52,6 +52,7 @@ // #include <QtWidgets/private/qtwidgetsglobal_p.h> +#include <QtCore/qcalendar.h> #include "QtWidgets/qcalendarwidget.h" #include "QtWidgets/qspinbox.h" #include "QtWidgets/qtoolbutton.h" @@ -70,7 +71,6 @@ class Q_AUTOTEST_EXPORT QDateTimeEditPrivate : public QAbstractSpinBoxPrivate, p Q_DECLARE_PUBLIC(QDateTimeEdit) public: QDateTimeEditPrivate(); - ~QDateTimeEditPrivate(); void init(const QVariant &var); void readLocaleSettings(); @@ -145,21 +145,22 @@ class QCalendarPopup : public QWidget { Q_OBJECT public: - explicit QCalendarPopup(QWidget *parent = nullptr, QCalendarWidget *cw = nullptr); + explicit QCalendarPopup(QWidget *parent = nullptr, QCalendarWidget *cw = nullptr, + QCalendar ca = QCalendar()); QDate selectedDate() { return verifyCalendarInstance()->selectedDate(); } - void setDate(const QDate &date); - void setDateRange(const QDate &min, const QDate &max); + void setDate(QDate date); + void setDateRange(QDate min, QDate max); void setFirstDayOfWeek(Qt::DayOfWeek dow) { verifyCalendarInstance()->setFirstDayOfWeek(dow); } QCalendarWidget *calendarWidget() const { return const_cast<QCalendarPopup*>(this)->verifyCalendarInstance(); } void setCalendarWidget(QCalendarWidget *cw); Q_SIGNALS: - void activated(const QDate &date); - void newDateSelected(const QDate &newDate); - void hidingCalendar(const QDate &oldDate); + void activated(QDate date); + void newDateSelected(QDate newDate); + void hidingCalendar(QDate oldDate); void resetButton(); private Q_SLOTS: - void dateSelected(const QDate &date); + void dateSelected(QDate date); void dateSelectionChanged(); protected: @@ -174,6 +175,7 @@ private: QPointer<QCalendarWidget> calendar; QDate oldDate; bool dateChanged; + QCalendar calendarSystem; }; QT_END_NAMESPACE diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp index 55ae42db04..5900326087 100644 --- a/src/widgets/widgets/qdockarealayout.cpp +++ b/src/widgets/widgets/qdockarealayout.cpp @@ -138,11 +138,8 @@ bool QDockAreaLayoutItem::skip() const QSize QDockAreaLayoutItem::minimumSize() const { - if (widgetItem != 0) { - int left, top, right, bottom; - widgetItem->widget()->getContentsMargins(&left, &top, &right, &bottom); - return widgetItem->minimumSize() + QSize(left+right, top+bottom); - } + if (widgetItem) + return widgetItem->minimumSize().grownBy(widgetItem->widget()->contentsMargins()); if (subinfo != 0) return subinfo->minimumSize(); return QSize(0, 0); @@ -150,11 +147,8 @@ QSize QDockAreaLayoutItem::minimumSize() const QSize QDockAreaLayoutItem::maximumSize() const { - if (widgetItem != 0) { - int left, top, right, bottom; - widgetItem->widget()->getContentsMargins(&left, &top, &right, &bottom); - return widgetItem->maximumSize()+ QSize(left+right, top+bottom); - } + if (widgetItem) + return widgetItem->maximumSize().grownBy(widgetItem->widget()->contentsMargins()); if (subinfo != 0) return subinfo->maximumSize(); return QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); @@ -180,11 +174,8 @@ QSize QDockAreaLayoutItem::sizeHint() const { if (placeHolderItem != 0) return QSize(0, 0); - if (widgetItem != 0) { - int left, top, right, bottom; - widgetItem->widget()->getContentsMargins(&left, &top, &right, &bottom); - return widgetItem->sizeHint() + QSize(left+right, top+bottom); - } + if (widgetItem) + return widgetItem->sizeHint().grownBy(widgetItem->widget()->contentsMargins()); if (subinfo != 0) return subinfo->sizeHint(); return QSize(-1, -1); @@ -1934,11 +1925,6 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*> QDockAreaLayoutItem item(new QDockWidgetItem(widget)); if (flags & StateFlagFloating) { bool drawer = false; -#if 0 // Used to be included in Qt4 for Q_WS_MAC // drawer support - extern bool qt_mac_is_macdrawer(const QWidget *); //qwidget_mac.cpp - extern bool qt_mac_set_drawer_preferred_edge(QWidget *, Qt::DockWidgetArea); //qwidget_mac.cpp - drawer = qt_mac_is_macdrawer(widget); -#endif if (!testing) { widget->hide(); @@ -1949,13 +1935,6 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*> int x, y, w, h; stream >> x >> y >> w >> h; -#if 0 // Used to be included in Qt4 for Q_WS_MAC // drawer support - if (drawer) { - mainWindow->window()->createWinId(); - widget->window()->createWinId(); - qt_mac_set_drawer_preferred_edge(widget, toDockWidgetArea(dockPos)); - } else -#endif if (!testing) widget->setGeometry(QDockAreaLayout::constrainedRect(QRect(x, y, w, h), widget)); @@ -2049,9 +2028,8 @@ void QDockAreaLayoutInfo::updateSeparatorWidgets() const } j++; -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC sepWidget->raise(); -#endif + QRect sepRect = separatorRect(i).adjusted(-2, -2, 2, 2); sepWidget->setGeometry(sepRect); sepWidget->setMask( QRegion(separatorRect(i).translated( - sepRect.topLeft()))); @@ -3090,10 +3068,6 @@ bool QDockAreaLayout::restoreDockWidget(QDockWidget *dockWidget) dockWidget->d_func()->setWindowState(true, true, r); } dockWidget->setVisible(!placeHolder->hidden); -#if 0 // Used to be included in Qt4 for Q_WS_X11 - if (placeHolder->window) // gets rid of the X11BypassWindowManager window flag - dockWidget->d_func()->setWindowState(true); -#endif item->placeHolderItem = 0; delete placeHolder; @@ -3340,9 +3314,8 @@ void QDockAreaLayout::updateSeparatorWidgets() const } j++; -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC sepWidget->raise(); -#endif + QRect sepRect = separatorRect(i).adjusted(-2, -2, 2, 2); sepWidget->setGeometry(sepRect); sepWidget->setMask( QRegion(separatorRect(i).translated( - sepRect.topLeft()))); diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp index 28a7cee2a0..05ec3aface 100644 --- a/src/widgets/widgets/qdockwidget.cpp +++ b/src/widgets/widgets/qdockwidget.cpp @@ -381,11 +381,10 @@ QSize QDockWidgetLayout::sizeFromContent(const QSize &content, bool floating) co if (content.height() < 0) result.setHeight(-1); - int left, top, right, bottom; - w->getContentsMargins(&left, &top, &right, &bottom); + const QMargins margins = w->contentsMargins(); //we need to subtract the contents margin (it will be added by the caller) - QSize min = w->minimumSize() - QSize(left + right, top + bottom); - QSize max = w->maximumSize() - QSize(left + right, top + bottom); + QSize min = w->minimumSize().shrunkBy(margins); + QSize max = w->maximumSize().shrunkBy(margins); /* A floating dockwidget will automatically get its minimumSize set to the layout's minimum size + deco. We're *not* interested in this, we only take minimumSize() @@ -977,11 +976,7 @@ bool QDockWidgetPrivate::mouseMoveEvent(QMouseEvent *event) && (event->pos() - state->pressPos).manhattanLength() > QApplication::startDragDistance()) { startDrag(); -#if 0 // Used to be included in Qt4 for Q_WS_WIN - grabMouseWhileInWindow(); -#else q->grabMouse(); -#endif ret = true; } } @@ -1029,13 +1024,6 @@ void QDockWidgetPrivate::nonClientAreaMouseEvent(QMouseEvent *event) QWidget *tl = q->topLevelWidget(); QRect geo = tl->geometry(); QRect titleRect = tl->frameGeometry(); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if ((features & QDockWidget::DockWidgetVerticalTitleBar)) { - titleRect.setTop(geo.top()); - titleRect.setBottom(geo.bottom()); - titleRect.setRight(geo.left() - 1); - } else -#endif { titleRect.setLeft(geo.left()); titleRect.setRight(geo.right()); @@ -1588,17 +1576,6 @@ bool QDockWidget::event(QEvent *event) if (d->mouseMoveEvent(static_cast<QMouseEvent *>(event))) return true; break; -#if 0 // Used to be included in Qt4 for Q_WS_WIN - case QEvent::Leave: - if (d->state != 0 && d->state->dragging && !d->state->nca) { - // This is a workaround for loosing the mouse on Vista. - QPoint pos = QCursor::pos(); - QMouseEvent fake(QEvent::MouseMove, mapFromGlobal(pos), pos, Qt::NoButton, - QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers()); - d->mouseMoveEvent(&fake); - } - break; -#endif case QEvent::MouseButtonRelease: if (d->mouseReleaseEvent(static_cast<QMouseEvent *>(event))) return true; diff --git a/src/widgets/widgets/qmaccocoaviewcontainer_mac.mm b/src/widgets/widgets/qmaccocoaviewcontainer_mac.mm index 0b64b2a2bb..88baf0410b 100644 --- a/src/widgets/widgets/qmaccocoaviewcontainer_mac.mm +++ b/src/widgets/widgets/qmaccocoaviewcontainer_mac.mm @@ -82,8 +82,32 @@ The following is a snippet showing how to subclass QMacCocoaViewContainer to wrap an NSSearchField. - \snippet macmainwindow.mm 0 + \code + SearchWidget::SearchWidget(QWidget *parent) + : QMacCocoaViewContainer(0, parent) + { + // Many Cocoa objects create temporary autorelease objects, + // so create a pool to catch them. + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + // Create the NSSearchField, set it on the QCocoaViewContainer. + NSSearchField *search = [[NSSearchField alloc] init]; + setCocoaView(search); + + // Use a Qt menu for the search field menu. + QMenu *qtMenu = createMenu(this); + NSMenu *nsMenu = qtMenu->macMenu(0); + [[search cell] setSearchMenuTemplate:nsMenu]; + + // Release our reference, since our super class takes ownership and we + // don't need it anymore. + [search release]; + + // Clean up our pool as we no longer need it. + [pool release]; + } + \endcode */ QT_BEGIN_NAMESPACE diff --git a/src/widgets/widgets/qmdiarea.cpp b/src/widgets/widgets/qmdiarea.cpp index c7b7e5bf97..6e3de1b1ff 100644 --- a/src/widgets/widgets/qmdiarea.cpp +++ b/src/widgets/widgets/qmdiarea.cpp @@ -2493,13 +2493,6 @@ bool QMdiArea::event(QEvent *event) { Q_D(QMdiArea); switch (event->type()) { -#if 0 // Used to be included in Qt4 for Q_WS_WIN - // QWidgetPrivate::hide_helper activates another sub-window when closing a - // modal dialog on Windows (see activateWindow() inside the ifdef). - case QEvent::WindowUnblocked: - d->activateCurrentWindow(); - break; -#endif case QEvent::WindowActivate: { d->isActivated = true; if (d->childWindows.isEmpty()) @@ -2557,11 +2550,7 @@ bool QMdiArea::eventFilter(QObject *object, QEvent *event) QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); // Ingore key events without a Ctrl modifier (except for press/release on the modifier itself). -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (!(keyEvent->modifiers() & Qt::MetaModifier) && keyEvent->key() != Qt::Key_Meta) -#else if (!(keyEvent->modifiers() & Qt::ControlModifier) && keyEvent->key() != Qt::Key_Control) -#endif return QAbstractScrollArea::eventFilter(object, event); // Find closest mdi area (in case we have a nested workspace). @@ -2576,11 +2565,7 @@ bool QMdiArea::eventFilter(QObject *object, QEvent *event) // 3) Ctrl-Shift-Tab (Tab, Tab, ...) -> iterate through all windows in the opposite // direction (activatePreviousSubWindow()) switch (keyEvent->key()) { -#if 0 // Used to be included in Qt4 for Q_WS_MAC - case Qt::Key_Meta: -#else case Qt::Key_Control: -#endif if (keyPress) area->d_func()->startTabToPreviousTimer(); else diff --git a/src/widgets/widgets/qmdisubwindow.cpp b/src/widgets/widgets/qmdisubwindow.cpp index 474cce983c..d58a1d06db 100644 --- a/src/widgets/widgets/qmdisubwindow.cpp +++ b/src/widgets/widgets/qmdisubwindow.cpp @@ -288,13 +288,6 @@ static inline bool isHoverControl(QStyle::SubControl control) return control != QStyle::SC_None && control != QStyle::SC_TitleBarLabel; } -#if 0 // Used to be included in Qt4 for Q_WS_WIN -static inline QRgb colorref2qrgb(COLORREF col) -{ - return qRgb(GetRValue(col),GetGValue(col),GetBValue(col)); -} -#endif - #ifndef QT_NO_TOOLTIP static void showToolTip(QHelpEvent *helpEvent, QWidget *widget, const QStyleOptionComplex &opt, QStyle::ComplexControl complexControl, QStyle::SubControl subControl) @@ -1926,43 +1919,7 @@ QPalette QMdiSubWindowPrivate::desktopPalette() const QPalette newPalette = q->palette(); bool colorsInitialized = false; -#if 0 // Used to be included in Qt4 for Q_WS_WIN // ask system properties on windows -#ifndef SPI_GETGRADIENTCAPTIONS -#define SPI_GETGRADIENTCAPTIONS 0x1008 -#endif -#ifndef COLOR_GRADIENTACTIVECAPTION -#define COLOR_GRADIENTACTIVECAPTION 27 -#endif -#ifndef COLOR_GRADIENTINACTIVECAPTION -#define COLOR_GRADIENTINACTIVECAPTION 28 -#endif - if (QGuiApplication::desktopSettingsAware()) { - newPalette.setColor(QPalette::Active, QPalette::Highlight, - colorref2qrgb(GetSysColor(COLOR_ACTIVECAPTION))); - newPalette.setColor(QPalette::Inactive, QPalette::Highlight, - colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTION))); - newPalette.setColor(QPalette::Active, QPalette::HighlightedText, - colorref2qrgb(GetSysColor(COLOR_CAPTIONTEXT))); - newPalette.setColor(QPalette::Inactive, QPalette::HighlightedText, - colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTIONTEXT))); - colorsInitialized = true; - BOOL hasGradient = false; - SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &hasGradient, 0); - - if (hasGradient) { - newPalette.setColor(QPalette::Active, QPalette::Base, - colorref2qrgb(GetSysColor(COLOR_GRADIENTACTIVECAPTION))); - newPalette.setColor(QPalette::Inactive, QPalette::Base, - colorref2qrgb(GetSysColor(COLOR_GRADIENTINACTIVECAPTION))); - } else { - newPalette.setColor(QPalette::Active, QPalette::Base, - newPalette.color(QPalette::Active, QPalette::Highlight)); - newPalette.setColor(QPalette::Inactive, QPalette::Base, - newPalette.color(QPalette::Inactive, QPalette::Highlight)); - } - } -#endif if (!colorsInitialized) { newPalette.setColor(QPalette::Active, QPalette::Highlight, newPalette.color(QPalette::Active, QPalette::Highlight)); diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp index 8843797430..0a81931b57 100644 --- a/src/widgets/widgets/qplaintextedit.cpp +++ b/src/widgets/widgets/qplaintextedit.cpp @@ -825,9 +825,6 @@ void QPlainTextEditPrivate::init(const QString &txt) viewport->setCursor(Qt::IBeamCursor); #endif originalOffsetY = 0; -#if 0 // Used to be included in Qt4 for Q_WS_WIN - setSingleFingerPanEnabled(true); -#endif } void QPlainTextEditPrivate::_q_textChanged() diff --git a/src/widgets/widgets/qpushbutton.cpp b/src/widgets/widgets/qpushbutton.cpp index b578aa0b18..f48b5706f7 100644 --- a/src/widgets/widgets/qpushbutton.cpp +++ b/src/widgets/widgets/qpushbutton.cpp @@ -684,38 +684,6 @@ bool QPushButton::event(QEvent *e) return QAbstractButton::event(e); } -#if 0 // Used to be included in Qt4 for Q_WS_MAC -/* \reimp */ -bool QPushButton::hitButton(const QPoint &pos) const -{ - QStyleOptionButton opt; - initStyleOption(&opt); - if (qt_mac_buttonIsRenderedFlat(this, &opt)) - return QAbstractButton::hitButton(pos); - - // Now that we know we are using the native style, let's proceed. - Q_D(const QPushButton); - QPushButtonPrivate *nonConst = const_cast<QPushButtonPrivate *>(d); - // In OSX buttons are round, which causes the hit method to be special. - // We cannot simply relay on detecting if something is inside the rect or not, - // we need to check if it is inside the "rounded area" or not. A point might - // be inside the rect but not inside the rounded area. - // Notice this method is only reimplemented for OSX. - return nonConst->hitButton(pos); -} - -bool QPushButtonPrivate::hitButton(const QPoint &pos) -{ - Q_Q(QPushButton); - QRect roundedRect(q->rect().left() + QMacStylePrivate::PushButtonLeftOffset, - q->rect().top() + QMacStylePrivate::PushButtonContentPadding, - q->rect().width() - QMacStylePrivate::PushButtonRightOffset, - q->rect().height() - QMacStylePrivate::PushButtonBottomOffset); - return roundedRect.contains(pos); -} -#endif - - QT_END_NAMESPACE #include "moc_qpushbutton.cpp" diff --git a/src/widgets/widgets/qpushbutton_p.h b/src/widgets/widgets/qpushbutton_p.h index a58675fe64..439b6e35d6 100644 --- a/src/widgets/widgets/qpushbutton_p.h +++ b/src/widgets/widgets/qpushbutton_p.h @@ -73,9 +73,6 @@ public: inline void init() { resetLayoutItemMargins(); } static QPushButtonPrivate* get(QPushButton *b) { return b->d_func(); } -#if 0 // Used to be included in Qt4 for Q_WS_MAC - bool hitButton(const QPoint &pos); -#endif #if QT_CONFIG(menu) QPoint adjustedMenuPosition(); #endif diff --git a/src/widgets/widgets/qrubberband.cpp b/src/widgets/widgets/qrubberband.cpp index ade8675db8..af730f8023 100644 --- a/src/widgets/widgets/qrubberband.cpp +++ b/src/widgets/widgets/qrubberband.cpp @@ -45,10 +45,6 @@ #include "qstyle.h" #include "qstyleoption.h" -#if 0 // Used to be included in Qt4 for Q_WS_MAC -# include <private/qt_mac_p.h> -# include <private/qt_cocoa_helpers_mac_p.h> -#endif #include <qdebug.h> @@ -140,18 +136,9 @@ QRubberBand::QRubberBand(Shape s, QWidget *p) Q_D(QRubberBand); d->shape = s; setAttribute(Qt::WA_TransparentForMouseEvents); -#if 1 // Used to be excluded in Qt4 for Q_WS_WIN setAttribute(Qt::WA_NoSystemBackground); -#endif setAttribute(Qt::WA_WState_ExplicitShowHide); setVisible(false); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (isWindow()) { - createWinId(); - extern OSWindowRef qt_mac_window_for(const QWidget *); //qwidget_mac.cpp - macWindowSetHasShadow(qt_mac_window_for(this), false); - } -#endif } /*! diff --git a/src/widgets/widgets/qsizegrip.cpp b/src/widgets/widgets/qsizegrip.cpp index dc5a7158dd..835af9c7b8 100644 --- a/src/widgets/widgets/qsizegrip.cpp +++ b/src/widgets/widgets/qsizegrip.cpp @@ -50,10 +50,6 @@ #include "qdebug.h" #include <QDesktopWidget> -#if 0 // Used to be included in Qt4 for Q_WS_MAC -#include <private/qt_mac_p.h> -#endif - #include <private/qwidget_p.h> #include <private/qdesktopwidget_p.h> #include <QtWidgets/qabstractscrollarea.h> @@ -81,9 +77,7 @@ public: Qt::Corner m_corner; bool gotMousePress; QPointer<QWidget> tlw; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - void updateMacSizer(bool hide) const; -#endif + Qt::Corner corner() const; inline bool atBottom() const { @@ -119,9 +113,7 @@ public: updateTopLevelWidget(); if (tlw && showSizeGrip) { Qt::WindowStates sizeGripNotVisibleState = Qt::WindowFullScreen; -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC sizeGripNotVisibleState |= Qt::WindowMaximized; -#endif // Don't show the size grip if the tlw is maximized or in full screen mode. showSizeGrip = !(tlw->windowState() & sizeGripNotVisibleState); } @@ -141,18 +133,6 @@ QSizeGripPrivate::QSizeGripPrivate() { } -#if 0 // Used to be included in Qt4 for Q_WS_MAC -void QSizeGripPrivate::updateMacSizer(bool hide) const -{ - Q_Q(const QSizeGrip); - if (QApplication::closingDown() || !parent) - return; - QWidget *topLevelWindow = qt_sizegrip_topLevelWidget(const_cast<QSizeGrip *>(q)); - if(topLevelWindow && topLevelWindow->isWindow()) - QWidgetPrivate::qt_mac_update_sizer(topLevelWindow, hide ? -1 : 1); -} -#endif - Qt::Corner QSizeGripPrivate::corner() const { Q_Q(const QSizeGrip); @@ -227,7 +207,7 @@ void QSizeGripPrivate::init() Q_Q(QSizeGrip); m_corner = q->isLeftToRight() ? Qt::BottomRightCorner : Qt::BottomLeftCorner; -#if !defined(QT_NO_CURSOR) && !0 /* Used to be included in Qt4 for Q_WS_MAC */ +#if !defined(QT_NO_CURSOR) q->setCursor(m_corner == Qt::TopLeftCorner || m_corner == Qt::BottomRightCorner ? Qt::SizeFDiagCursor : Qt::SizeBDiagCursor); #endif @@ -440,7 +420,7 @@ void QSizeGrip::moveEvent(QMoveEvent * /*moveEvent*/) return; d->m_corner = d->corner(); -#if !defined(QT_NO_CURSOR) && !0 /* Used to be included in Qt4 for Q_WS_MAC */ +#if !defined(QT_NO_CURSOR) setCursor(d->m_corner == Qt::TopLeftCorner || d->m_corner == Qt::BottomRightCorner ? Qt::SizeFDiagCursor : Qt::SizeBDiagCursor); #endif @@ -451,9 +431,6 @@ void QSizeGrip::moveEvent(QMoveEvent * /*moveEvent*/) */ void QSizeGrip::showEvent(QShowEvent *showEvent) { -#if 0 // Used to be included in Qt4 for Q_WS_MAC - d_func()->updateMacSizer(false); -#endif QWidget::showEvent(showEvent); } @@ -462,9 +439,6 @@ void QSizeGrip::showEvent(QShowEvent *showEvent) */ void QSizeGrip::hideEvent(QHideEvent *hideEvent) { -#if 0 // Used to be included in Qt4 for Q_WS_MAC - d_func()->updateMacSizer(true); -#endif QWidget::hideEvent(hideEvent); } @@ -486,9 +460,7 @@ bool QSizeGrip::eventFilter(QObject *o, QEvent *e) return QWidget::eventFilter(o, e); } Qt::WindowStates sizeGripNotVisibleState = Qt::WindowFullScreen; -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC sizeGripNotVisibleState |= Qt::WindowMaximized; -#endif // Don't show the size grip if the tlw is maximized or in full screen mode. setVisible(!(d->tlw->windowState() & sizeGripNotVisibleState)); setAttribute(Qt::WA_WState_ExplicitShowHide, false); diff --git a/src/widgets/widgets/qstatusbar.cpp b/src/widgets/widgets/qstatusbar.cpp index e9044e6cad..39f0f11daf 100644 --- a/src/widgets/widgets/qstatusbar.cpp +++ b/src/widgets/widgets/qstatusbar.cpp @@ -90,10 +90,6 @@ public: int savedStrut; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - QPoint dragStart; -#endif - int indexToLastNonPermanentWidget() const { int i = items.size() - 1; @@ -747,44 +743,7 @@ bool QStatusBar::event(QEvent *e) } } -// On Mac OS X Leopard it is possible to drag the window by clicking -// on the tool bar on most applications. -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC return QWidget::event(e); -#else - // Enable drag-click only if the status bar is the status bar for a - // QMainWindow with a unifed toolbar. - if (parent() == 0 || qobject_cast<QMainWindow *>(parent()) == 0 || - qobject_cast<QMainWindow *>(parent())->unifiedTitleAndToolBarOnMac() == false ) - return QWidget::event(e); - - // Check for mouse events. - QMouseEvent *mouseEvent; - if (e->type() == QEvent::MouseButtonPress || - e->type() == QEvent::MouseMove || - e->type() == QEvent::MouseButtonRelease) { - mouseEvent = static_cast <QMouseEvent*>(e); - } else { - return QWidget::event(e); - } - - // The following is a standard mouse drag handler. - if (e->type() == QEvent::MouseButtonPress && (mouseEvent->button() == Qt::LeftButton)) { - d->dragStart = mouseEvent->pos(); - } else if (e->type() == QEvent::MouseMove){ - if (d->dragStart == QPoint()) - return QWidget::event(e); - QPoint pos = mouseEvent->pos(); - QPoint delta = (pos - d->dragStart); - window()->move(window()->pos() + delta); - } else if (e->type() == QEvent::MouseButtonRelease && (mouseEvent->button() == Qt::LeftButton)){ - d->dragStart = QPoint(); - } else { - return QWidget::event(e); - } - - return true; -#endif } QT_END_NAMESPACE diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp index 18fda11ddf..7e1794efef 100644 --- a/src/widgets/widgets/qtabbar.cpp +++ b/src/widgets/widgets/qtabbar.cpp @@ -68,11 +68,6 @@ #include "private/qapplication_p.h" #include "private/qtabbar_p.h" -#if 0 // Used to be included in Qt4 for Q_WS_MAC -#include <private/qt_mac_p.h> -#include <private/qt_cocoa_helpers_mac_p.h> -#endif - QT_BEGIN_NAMESPACE namespace { @@ -1976,9 +1971,7 @@ void QTabBar::mousePressEvent(QMouseEvent *event) d->moveTabFinished(d->pressedIndex); d->pressedIndex = d->indexAtPos(event->pos()); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - d->previousPressedIndex = d->pressedIndex; -#endif + if (d->validIndex(d->pressedIndex)) { QStyleOptionTabBarBase optTabBase; optTabBase.init(this); @@ -2058,17 +2051,6 @@ void QTabBar::mouseMoveEvent(QMouseEvent *event) update(); } -#if 0 // Used to be included in Qt4 for Q_WS_MAC - } else if (!d->documentMode && event->buttons() == Qt::LeftButton && d->previousPressedIndex != -1) { - int newPressedIndex = d->indexAtPos(event->pos()); - if (d->pressedIndex == -1 && d->previousPressedIndex == newPressedIndex) { - d->pressedIndex = d->previousPressedIndex; - update(tabRect(d->pressedIndex)); - } else if(d->pressedIndex != newPressedIndex) { - d->pressedIndex = -1; - update(tabRect(d->previousPressedIndex)); - } -#endif } if (event->buttons() != Qt::LeftButton) { @@ -2162,9 +2144,7 @@ void QTabBar::mouseReleaseEvent(QMouseEvent *event) event->ignore(); return; } -#if 0 // Used to be included in Qt4 for Q_WS_MAC - d->previousPressedIndex = -1; -#endif + if (d->movable && d->dragInProgress && d->validIndex(d->pressedIndex)) { int length = d->tabList[d->pressedIndex].dragOffset; int width = verticalTabs(d->shape) diff --git a/src/widgets/widgets/qtabbar_p.h b/src/widgets/widgets/qtabbar_p.h index 458d486b10..5552c43548 100644 --- a/src/widgets/widgets/qtabbar_p.h +++ b/src/widgets/widgets/qtabbar_p.h @@ -93,9 +93,6 @@ public: selectionBehaviorOnRemove(QTabBar::SelectRightTab), paintWithOffsets(true), movable(false), dragInProgress(false), documentMode(false), autoHide(false), changeCurrentOnDrag(false), switchTabCurrentIndex(-1), switchTabTimerId(0), movingTab(nullptr) -#if 0 // Used to be included in Qt4 for Q_WS_MAC - , previousPressedIndex(-1) -#endif {} int currentIndex; @@ -232,9 +229,6 @@ public: int switchTabTimerId; QMovableTabWidget *movingTab; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - int previousPressedIndex; -#endif // shared by tabwidget and qtabbar static void initStyleBaseOption(QStyleOptionTabBarBase *optTabBase, QTabBar *tabbar, QSize size) { diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp index bd9e5f8159..0ccbad7eaa 100644 --- a/src/widgets/widgets/qtextedit.cpp +++ b/src/widgets/widgets/qtextedit.cpp @@ -200,9 +200,6 @@ void QTextEditPrivate::init(const QString &html) #ifndef QT_NO_CURSOR viewport->setCursor(Qt::IBeamCursor); #endif -#if 0 // Used to be included in Qt4 for Q_WS_WIN - setSingleFingerPanEnabled(true); -#endif } void QTextEditPrivate::_q_repaintContents(const QRectF &contentsRect) diff --git a/src/widgets/widgets/qtoolbar.cpp b/src/widgets/widgets/qtoolbar.cpp index d1a0f5ea78..58e9c4fd87 100644 --- a/src/widgets/widgets/qtoolbar.cpp +++ b/src/widgets/widgets/qtoolbar.cpp @@ -324,13 +324,8 @@ bool QToolBarPrivate::mouseMoveEvent(QMouseEvent *event) event->y() >= 0 && event->y() < q->height()); startDrag(moving); - if (!moving && !wasDragging) { -#if 0 // Used to be included in Qt4 for Q_WS_WIN - grabMouseWhileInWindow(); -#else + if (!moving && !wasDragging) q->grabMouse(); -#endif - } } if (state->dragging) { diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp index 46bc29eed7..9cdae4f28f 100644 --- a/src/widgets/widgets/qwidgetlinecontrol.cpp +++ b/src/widgets/widgets/qwidgetlinecontrol.cpp @@ -78,11 +78,6 @@ int QWidgetLineControl::redoTextLayout() const QTextLine l = m_textLayout.createLine(); m_textLayout.endLayout(); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (m_threadChecks) - m_textLayoutThread = QThread::currentThread(); -#endif - return qRound(l.ascent()); } diff --git a/src/widgets/widgets/qwidgetlinecontrol_p.h b/src/widgets/widgets/qwidgetlinecontrol_p.h index 940a17714f..8ebed25084 100644 --- a/src/widgets/widgets/qwidgetlinecontrol_p.h +++ b/src/widgets/widgets/qwidgetlinecontrol_p.h @@ -95,10 +95,6 @@ public: m_selstart(0), m_selend(0), m_passwordEchoEditing(false) , m_passwordEchoTimer(0) , m_passwordMaskDelay(-1) -#if 0 // Used to be included in Qt4 for Q_WS_MAC - , m_threadChecks(false) - , m_textLayoutThread(0) - #endif #if defined(QT_BUILD_INTERNAL) , m_passwordMaskDelayOverride(-1) #endif @@ -404,25 +400,9 @@ public: QTextLayout *textLayout() const { -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (m_threadChecks && QThread::currentThread() != m_textLayoutThread) - redoTextLayout(); -#endif return &m_textLayout; } -#if 0 // Used to be included in Qt4 for Q_WS_MAC - void setThreadChecks(bool threadChecks) - { - m_threadChecks = threadChecks; - } - - bool threadChecks() const - { - return m_threadChecks; - } -#endif - private: void init(const QString &txt); void removeSelectedText(); @@ -534,10 +514,6 @@ private: } int redoTextLayout() const; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - bool m_threadChecks; - mutable QThread *m_textLayoutThread; -#endif public: #if defined(QT_BUILD_INTERNAL) diff --git a/src/widgets/widgets/qwidgetresizehandler.cpp b/src/widgets/widgets/qwidgetresizehandler.cpp index e8d435429f..9dbba12aba 100644 --- a/src/widgets/widgets/qwidgetresizehandler.cpp +++ b/src/widgets/widgets/qwidgetresizehandler.cpp @@ -124,21 +124,6 @@ bool QWidgetResizeHandler::eventFilter(QObject *o, QEvent *ee) if (!widgetRect.contains(cursorPoint)) return false; if (e->button() == Qt::LeftButton) { -#if 0 // Used to be included in Qt4 for Q_WS_X11 - /* - Implicit grabs do not stop the X server from changing - the cursor in children, which looks *really* bad when - doing resizingk, so we grab the cursor. Note that we do - not do this on Windows since double clicks are lost due - to the grab (see change 198463). - */ - if (e->spontaneous()) -# if !defined(QT_NO_CURSOR) - widget->grabMouse(widget->cursor()); -# else - widget->grabMouse(); -# endif // QT_NO_CURSOR -#endif buttonDown = false; emit activate(); bool me = movingEnabled; |