diff options
24 files changed, 280 insertions, 186 deletions
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index 4f5ef6b193d..7fbcb72937f 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -77,6 +77,7 @@ qt_internal_add_module(Core global/qsysinfo.cpp global/qsysinfo.h global/qsystemdetection.h global/qtclasshelpermacros.h + global/qtclasshelper_p.h global/qtconfiginclude.h global/qtconfigmacros.h global/qtcoreglobal.h global/qtcoreglobal_p.h diff --git a/src/corelib/compat/removed_api.cpp b/src/corelib/compat/removed_api.cpp index 5b592bcfc76..4285e39a542 100644 --- a/src/corelib/compat/removed_api.cpp +++ b/src/corelib/compat/removed_api.cpp @@ -1465,6 +1465,13 @@ QNoDebug QMessageLogger::noDebug() const noexcept #include "qmutex.h" // removed, previously-inline API +#include "qobject.h" + +bool QObject::doSetProperty(const char *name, const QVariant *lvalue, QVariant *rvalue) +{ + return doSetProperty(name, *lvalue, rvalue); +} + #include "qstring.h" // inlined API // #include "qotherheader.h" diff --git a/src/corelib/global/qtclasshelper_p.h b/src/corelib/global/qtclasshelper_p.h new file mode 100644 index 00000000000..1e356726126 --- /dev/null +++ b/src/corelib/global/qtclasshelper_p.h @@ -0,0 +1,77 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default + +#ifndef QTCLASSHELPER_P_H +#define QTCLASSHELPER_P_H + +#include <QtCore/private/qglobal_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 <type_traits> +#include <utility> + +QT_BEGIN_NAMESPACE + +/* + Helper for setters overloaded on lvalue/rvalue. If the setter is doing a + lot of work around the actual assignment, a common pattern is to create a + private helper method + + void doSetFoo(const Foo &lvalue, Foo *rvalue); + + and implement the two setters inline by calling that function: + + void setFoo(const Foo &f) { doSetFoo(f, nullptr); } + void setFoo(Foo &&f) { doSetFoo(f, &f); } + + Then, in doSetFoo(), when assigning the argument to the member, use this + function: + + q_choose_assign(m_foo, lvalue, rvalue); + + or, when appending to a container, + + q_choose_append(m_container, lvalue, rvalue); + + The functions mandate (in the C++ sense) that all arguments are the same + type, so they deduce each argument separately and then static_assert that + they're the same. If we need std::exchange()-like mixed types later, it's + easy to relax. For now, avoid being overly general. +*/ +template <typename T, typename U, typename V> +decltype(auto) q_choose_assign(T &var, const U &lvalue, V *rvalue) +{ + static_assert(std::is_same_v<T, U>, "all arguments must be of the same type"); + static_assert(std::is_same_v<U, V>, "all arguments must be of the same type"); + if (rvalue) + return var = std::move(*rvalue); + else + return var = lvalue; +} + +template <typename Container, typename U, typename V> +decltype(auto) q_choose_append(Container &c, const U &lvalue, V *rvalue) +{ + static_assert(std::is_same_v<typename Container::value_type, U>, "arguments must match container"); + static_assert(std::is_same_v<U, V>, "all arguments must be of the same type"); + if (rvalue) + c.push_back(std::move(*rvalue)); + else + c.push_back(lvalue); + return c.back(); +} + +QT_END_NAMESPACE + +#endif // QTCLASSHELPER_P_H diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 8f4852c3027..3b92c5f48f2 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -1644,12 +1644,15 @@ void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority) QThreadData *data = locker.threadData; + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED // compressEvent() // if this is one of the compressible events, do compression if (receiver->d_func()->postedEvents.loadAcquire() && self && self->compressEvent(event, receiver, &data->postEventList)) { Q_TRACE(QCoreApplication_postEvent_event_compressed, receiver, event); return; } + QT_WARNING_POP // delete the event on exceptions to protect against memory leaks till the event is // properly owned in the postEventList diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h index 105bd7a291a..0c8e78170ee 100644 --- a/src/corelib/kernel/qcoreapplication.h +++ b/src/corelib/kernel/qcoreapplication.h @@ -211,6 +211,7 @@ protected: bool event(QEvent *) override; # if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) + QT_DEPRECATED_VERSION_X_6_10("This feature will be removed in Qt 7") virtual bool compressEvent(QEvent *, QObject *receiver, QPostEventList *); # endif #endif // QT_NO_QOBJECT diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 0d2ec8efd7a..46f2ad7d1c4 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -8,6 +8,7 @@ #include "qobject_p_p.h" #include "qmetaobject_p.h" +#include <QtCore/private/qtclasshelper_p.h> #include "qabstracteventdispatcher.h" #include "qabstracteventdispatcher_p.h" #include "qcoreapplication.h" @@ -4370,10 +4371,9 @@ int QObjectPrivate::signalIndex(const char *signalName, \overload setProperty */ -bool QObject::doSetProperty(const char *name, const QVariant *lvalue, QVariant *rvalue) +bool QObject::doSetProperty(const char *name, const QVariant &value, QVariant *rvalue) { Q_D(QObject); - const auto &value =*lvalue; const QMetaObject *meta = metaObject(); if (!name || !meta) return false; @@ -4392,18 +4392,12 @@ bool QObject::doSetProperty(const char *name, const QVariant *lvalue, QVariant * } else { if (idx == -1) { d->extraData->propertyNames.append(name); - if (rvalue) - d->extraData->propertyValues.append(std::move(*rvalue)); - else - d->extraData->propertyValues.append(*lvalue); + q_choose_append(d->extraData->propertyValues, value, rvalue); } else { if (value.userType() == d->extraData->propertyValues.at(idx).userType() && value == d->extraData->propertyValues.at(idx)) return false; - if (rvalue) - d->extraData->propertyValues[idx] = std::move(*rvalue); - else - d->extraData->propertyValues[idx] = *lvalue; + q_choose_assign(d->extraData->propertyValues[idx], value, rvalue); } } @@ -4418,7 +4412,7 @@ bool QObject::doSetProperty(const char *name, const QVariant *lvalue, QVariant * qWarning("%s::setProperty: Property \"%s\" invalid," " read-only or does not exist", metaObject()->className(), name); #endif - return rvalue ? p.write(this, std::move(*rvalue)) : p.write(this, *lvalue); + return rvalue ? p.write(this, std::move(*rvalue)) : p.write(this, value); } /*! diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 813ccdb6735..8c2cd74281e 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -387,7 +387,10 @@ protected: private: void doSetObjectName(const QString &name); +#if QT_CORE_REMOVED_SINCE(6, 10) bool doSetProperty(const char *name, const QVariant *lvalue, QVariant *rvalue); +#endif + bool doSetProperty(const char *name, const QVariant &value, QVariant *rvalue); Q_DISABLE_COPY(QObject) @@ -409,12 +412,12 @@ inline QMetaObject::Connection QObject::connect(const QObject *asender, const ch #if QT_CORE_INLINE_IMPL_SINCE(6, 6) bool QObject::setProperty(const char *name, const QVariant &value) { - return doSetProperty(name, &value, nullptr); + return doSetProperty(name, value, nullptr); } #endif // inline since 6.6 bool QObject::setProperty(const char *name, QVariant &&value) { - return doSetProperty(name, &value, &value); + return doSetProperty(name, value, &value); } template <class T> diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp index 31abed73cf9..48420219eaa 100644 --- a/src/corelib/plugin/qfactoryloader.cpp +++ b/src/corelib/plugin/qfactoryloader.cpp @@ -395,7 +395,7 @@ QFactoryLoader::~QFactoryLoader() #if QT_CONFIG(library) for (qsizetype i = 0; i < d->loadedLibraries.size(); ++i) { if (d->loadedLibraries.at(i)) { - auto &plugin = d->libraries.at(i); + auto &plugin = d->libraries[i]; delete plugin->inst.data(); plugin->unload(); } @@ -469,7 +469,7 @@ void QFactoryLoader::setExtraSearchPath(const QString &path) // must re-scan everything for (qsizetype i = 0; i < d->loadedLibraries.size(); ++i) { if (d->loadedLibraries.at(i)) { - auto &plugin = d->libraries.at(i); + auto &plugin = d->libraries[i]; delete plugin->inst.data(); } } @@ -489,8 +489,10 @@ QFactoryLoader::MetaDataList QFactoryLoader::metaData() const QList<QPluginParsedMetaData> metaData; #if QT_CONFIG(library) QMutexLocker locker(&d->mutex); + metaData.reserve(qsizetype(d->libraries.size())); for (const auto &library : d->libraries) metaData.append(library->metaData); + locker.unlock(); #endif QLatin1StringView iid(d->iid.constData(), d->iid.size()); @@ -513,10 +515,12 @@ QList<QCborArray> QFactoryLoader::metaDataKeys() const QList<QCborArray> metaData; #if QT_CONFIG(library) QMutexLocker locker(&d->mutex); + metaData.reserve(qsizetype(d->libraries.size())); for (const auto &library : d->libraries) { const QCborValue md = library->metaData.value(QtPluginMetaDataKeys::MetaData); metaData.append(md["Keys"_L1].toArray()); } + locker.unlock(); #endif QLatin1StringView iid(d->iid.constData(), d->iid.size()); diff --git a/src/corelib/serialization/qtextstream.cpp b/src/corelib/serialization/qtextstream.cpp index 9f0b8417aea..ad97fcc2b04 100644 --- a/src/corelib/serialization/qtextstream.cpp +++ b/src/corelib/serialization/qtextstream.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2016 The Qt Company Ltd. // Copyright (C) 2016 Intel Corporation. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:critical reason:data-parser //#define QTEXTSTREAM_DEBUG diff --git a/src/corelib/serialization/qtextstream.h b/src/corelib/serialization/qtextstream.h index 2b4caf549c7..e60be06d3cf 100644 --- a/src/corelib/serialization/qtextstream.h +++ b/src/corelib/serialization/qtextstream.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:header-decls-only #ifndef QTEXTSTREAM_H #define QTEXTSTREAM_H diff --git a/src/corelib/serialization/qtextstream_p.h b/src/corelib/serialization/qtextstream_p.h index d7e70200f95..7227c29c8fe 100644 --- a/src/corelib/serialization/qtextstream_p.h +++ b/src/corelib/serialization/qtextstream_p.h @@ -1,6 +1,7 @@ // Copyright (C) 2016 The Qt Company Ltd. // Copyright (C) 2016 Intel Corporation. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:header-decls-only #ifndef QTEXTSTREAM_P_H #define QTEXTSTREAM_P_H diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index abba4b12fb2..9d0631f832d 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -2376,6 +2376,18 @@ void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *whe \sa fromLatin1(), fromLocal8Bit(), fromUtf8() */ +/*! + \fn QString::QString(QStringView sv) + + Constructs a string initialized with the string view's data. + + The QString will be null if and only if \a sv is null. + + \since 6.8 + + \sa fromUtf16() +*/ + /* //! [from-std-string] Returns a copy of the \a str string. The given string is assumed to be diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 7a35f4c1845..99b416d4fd5 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -2106,7 +2106,9 @@ bool QGuiApplication::event(QEvent *e) */ bool QGuiApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventList *postedEvents) { + QT_IGNORE_DEPRECATIONS( return QCoreApplication::compressEvent(event, receiver, postedEvents); + ) } #endif diff --git a/src/gui/kernel/qguiapplication.h b/src/gui/kernel/qguiapplication.h index 0af6489428e..717b2e6e8cc 100644 --- a/src/gui/kernel/qguiapplication.h +++ b/src/gui/kernel/qguiapplication.h @@ -164,6 +164,7 @@ Q_SIGNALS: protected: bool event(QEvent *) override; # if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) + QT_DEPRECATED_VERSION_X_6_10("This feature will be removed in Qt 7") bool compressEvent(QEvent *, QObject *receiver, QPostEventList *) override; # endif diff --git a/src/gui/painting/qcolortransfergeneric_p.h b/src/gui/painting/qcolortransfergeneric_p.h index 6caebceb1a4..c2ebd937a44 100644 --- a/src/gui/painting/qcolortransfergeneric_p.h +++ b/src/gui/painting/qcolortransfergeneric_p.h @@ -65,6 +65,7 @@ private: // HLG from linear [0-12] -> [0-1] static float hlgFromLinear(float x) { + x = std::clamp(x, 0.f, 12.f); if (x > 1.f) return m_hlg_a * std::log(x - m_hlg_b) + m_hlg_c; return std::sqrt(x * 0.25f); @@ -73,6 +74,7 @@ private: // HLG to linear [0-1] -> [0-12] static float hlgToLinear(float x) { + x = std::clamp(x, 0.f, 1.f); if (x < 0.5f) return (x * x) * 4.f; return std::exp((x - m_hlg_c) / m_hlg_a) + m_hlg_b; @@ -86,6 +88,7 @@ private: // PQ to linear [0-1] -> [0-64] static float pqToLinear(float e) { + e = std::clamp(e, 0.f, 1.f); // m2-th root of E' const float eRoot = std::pow(e, 1.f / m_pq_m2); // rational transform @@ -99,6 +102,7 @@ private: // PQ from linear [0-64] -> [0-1] static float pqFromLinear(float fd) { + fd = std::clamp(fd, 0.f, 64.f); // scale Fd to Y const float y = fd * (1.f / m_pq_f); // yRoot = Y^m1 -- "root" because m1 is <1 diff --git a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp index 1356d93abab..e6c72b82bc5 100644 --- a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp +++ b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp @@ -314,23 +314,13 @@ QWaylandXdgSurface::QWaylandXdgSurface(QWaylandXdgShell *shell, ::xdg_surface *s Qt::WindowType type = static_cast<Qt::WindowType>(int(window->windowFlags() & Qt::WindowType_Mask)); auto *transientParent = window->transientParent(); - if (type == Qt::ToolTip) { - if (transientParent) { - setPopup(transientParent); - } else { - qCWarning(lcQpaWayland) << "Failed to create popup. Ensure popup " << window->window() << "has a transientParent set."; - QWindowSystemInterface::handleCloseEvent<QWindowSystemInterface::AsynchronousDelivery>(m_window->window()); - } - } else if (type == Qt::Popup ) { - if (transientParent && display->lastInputDevice()) { - setGrabPopup(transientParent, display->lastInputDevice(), display->lastInputSerial()); - } else { - qCWarning(lcQpaWayland) << "Failed to create grabbing popup. Ensure popup " << window->window() << "has a transientParent set and that parent window has received input."; - QWindowSystemInterface::handleCloseEvent<QWindowSystemInterface::AsynchronousDelivery>(m_window->window()); - } - } else { + if (type == Qt::ToolTip) + setPopup(transientParent); + else if (type == Qt::Popup ) + setGrabPopup(transientParent, display->lastInputDevice(), display->lastInputSerial()); + else setToplevel(); - } + setSizeHints(); } diff --git a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp index f1bb8bee478..90a5965bba6 100644 --- a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp +++ b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp @@ -8,6 +8,8 @@ #include <QtWaylandClient/private/qwaylandwindow_p.h> #include <QtWaylandClient/private/qwaylanddisplay_p.h> +#include <qpa/qwindowsysteminterface.h> + QT_BEGIN_NAMESPACE namespace QtWaylandClient { @@ -43,6 +45,22 @@ void QWaylandXdgShellIntegration::xdg_wm_base_ping(uint32_t serial) QWaylandShellSurface *QWaylandXdgShellIntegration::createShellSurface(QWaylandWindow *window) { + QWaylandDisplay *display = window->display(); + Qt::WindowType type = static_cast<Qt::WindowType>(int(window->windowFlags() & Qt::WindowType_Mask)); + auto *transientParent = window->transientParent(); + + if (type == Qt::ToolTip && !transientParent) { + qCWarning(lcQpaWayland) << "Failed to create popup. Ensure popup " << window->window() << "has a transientParent set."; + QWindowSystemInterface::handleCloseEvent<QWindowSystemInterface::AsynchronousDelivery>(window->window()); + return new QWaylandShellSurface(window); + } + + if (type == Qt::Popup && (!transientParent || !display->lastInputDevice())) { + qCWarning(lcQpaWayland) << "Failed to create grabbing popup. Ensure popup " << window->window() << "has a transientParent set and that parent window has received input."; + QWindowSystemInterface::handleCloseEvent<QWindowSystemInterface::AsynchronousDelivery>(window->window()); + return new QWaylandShellSurface(window); + } + return new QWaylandXdgSurface(mXdgShell.get(), get_xdg_surface(window->wlSurface()), window); } diff --git a/src/plugins/styles/modernwindows/qwindows11style.cpp b/src/plugins/styles/modernwindows/qwindows11style.cpp index 953fb1618a1..146a39a6864 100644 --- a/src/plugins/styles/modernwindows/qwindows11style.cpp +++ b/src/plugins/styles/modernwindows/qwindows11style.cpp @@ -38,27 +38,13 @@ QT_BEGIN_NAMESPACE static constexpr int topLevelRoundingRadius = 8; //Radius for toplevel items like popups for round corners static constexpr int secondLevelRoundingRadius = 4; //Radius for second level items like hovered menu item round corners - -enum WINUI3Color { - subtleHighlightColor, //Subtle highlight based on alpha used for hovered elements - subtlePressedColor, //Subtle highlight based on alpha used for pressed elements - frameColorLight, //Color of frame around flyouts and controls except for Checkbox and Radiobutton - frameColorStrong, //Color of frame around Checkbox and Radiobuttons - controlStrongFill, //Color of controls with strong filling such as the right side of a slider - controlStrokeSecondary, - controlStrokePrimary, - controlFillTertiary, //Color of filled sunken controls - controlFillSecondary, //Color of filled hovered controls - menuPanelFill, //Color of menu panel - textOnAccentPrimary, //Color of text on controls filled in accent color - textOnAccentSecondary, //Color of text of sunken controls in accent color - controlTextSecondary, //Color of text of sunken controls - controlStrokeOnAccentSecondary, //Color of frame around Buttons in accent color - controlFillSolid, //Color for solid fill - surfaceStroke, //Color of MDI window frames - controlAccentDisabled, - textAccentDisabled -}; +template <typename R, typename P, typename B> +static inline void drawRoundedRect(QPainter *p, R &&rect, P &&pen, B &&brush) +{ + p->setPen(pen); + p->setBrush(brush); + p->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius); +} static const QColor WINUI3ColorsLight [] { QColor(0x00,0x00,0x00,0x09), //subtleHighlightColor @@ -253,42 +239,24 @@ void QWindows11Style::drawComplexControl(ComplexControl control, const QStyleOpt QCachedPainter cp(painter, QLatin1StringView("win11_spinbox") % HexString<uint8_t>(colorSchemeIndex), sb, sb->rect.size()); if (cp.needsPainting()) { - if (sb->frame && (sub & SC_SpinBoxFrame)) { - const qreal sublineOffset = secondLevelRoundingRadius + 2.0; - cp->save(); - cp->setClipRect(option->rect.adjusted(-2, -2, 2, 2)); - cp->setPen(editSublineColor(option, colorSchemeIndex)); - cp->drawLine(option->rect.bottomLeft() + QPointF(sublineOffset, 0.5), - option->rect.bottomRight() + QPointF(-sublineOffset, 0.5)); - cp->restore(); - } - const QRectF frameRect = QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5)); - cp->setBrush(option->palette.brush(QPalette::Base)); - cp->setPen(highContrastTheme == true ? sb->palette.buttonText().color() - : WINUI3Colors[colorSchemeIndex][frameColorLight]); - cp->drawRoundedRect(frameRect, secondLevelRoundingRadius, secondLevelRoundingRadius); - const QPoint mousePos = widget ? widget->mapFromGlobal(QCursor::pos()) : QPoint(); - if (sub & SC_SpinBoxEditField) { - const QRect rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxEditField, - widget).adjusted(0, 0, 0, 1); - if (!(state & State_HasFocus) && rect.contains(mousePos)) { - cp->setPen(Qt::NoPen); - cp->setBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]); - cp->drawRoundedRect(option->rect.adjusted(2, 2, -2, -2), secondLevelRoundingRadius, - secondLevelRoundingRadius); - } - } + const auto frameRect = option->rect.marginsRemoved(QMargins(1, 1, 1, 1)); + drawRoundedRect(cp.painter(), frameRect, Qt::NoPen, option->palette.brush(QPalette::Base)); + + if (sb->frame && (sub & SC_SpinBoxFrame)) + drawLineEditFrame(cp.painter(), option); + + const bool isMouseOver = state & State_MouseOver; + const bool hasFocus = state & State_HasFocus; + if (isMouseOver && !hasFocus && !highContrastTheme) + drawRoundedRect(cp.painter(), frameRect, Qt::NoPen, winUI3Color(subtleHighlightColor)); + const auto drawUpDown = [&](QStyle::SubControl sc) { const bool isUp = sc == SC_SpinBoxUp; - QRect rect = proxy()->subControlRect(CC_SpinBox, option, isUp ? SC_SpinBoxUp : SC_SpinBoxDown, widget); - if (isUp) - rect.adjust(0, 0, 0, 1); - if (rect.contains(mousePos)) { - cp->setPen(Qt::NoPen); - cp->setBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]); - cp->drawRoundedRect(rect.adjusted(1, 1, -1, -1), secondLevelRoundingRadius, - secondLevelRoundingRadius); - } + const QRect rect = proxy()->subControlRect(CC_SpinBox, option, sc, widget); + if (sb->activeSubControls & sc) + drawRoundedRect(cp.painter(), rect.adjusted(1, 1, -1, -2), Qt::NoPen, + winUI3Color(subtleHighlightColor)); + cp->setFont(assetFont); cp->setPen(sb->palette.buttonText().color()); cp->setBrush(Qt::NoBrush); @@ -441,36 +409,23 @@ void QWindows11Style::drawComplexControl(ComplexControl control, const QStyleOpt #if QT_CONFIG(combobox) case CC_ComboBox: if (const QStyleOptionComboBox *combobox = qstyleoption_cast<const QStyleOptionComboBox *>(option)) { - QRectF rect = option->rect.marginsRemoved(QMargins(1, 1, 1, 1)); - painter->setBrush(combobox->palette.brush(QPalette::Base)); - painter->setPen(Qt::NoPen); - painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius); + const auto frameRect = option->rect.marginsRemoved(QMargins(1, 1, 1, 1)); + drawRoundedRect(painter, frameRect, Qt::NoPen, option->palette.brush(QPalette::Base)); - const bool comboboxHovered = state & State_MouseOver; - // In case the QComboBox is hovered overdraw the background with a alpha mask to - // highlight the QComboBox. - if (comboboxHovered && !highContrastTheme) { - painter->setBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]); - painter->setPen(Qt::NoPen); - painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius); - } + if (combobox->frame) + drawLineEditFrame(painter, option); + + const bool isMouseOver = state & State_MouseOver; + const bool hasFocus = state & State_HasFocus; + if (isMouseOver && !hasFocus && !highContrastTheme) + drawRoundedRect(painter, frameRect, Qt::NoPen, winUI3Color(subtleHighlightColor)); - rect.adjust(0.5,0.5,-0.5,-0.5); - painter->setBrush(Qt::NoBrush); - painter->setPen(highContrastTheme ? (comboboxHovered ? combobox->palette.accent().color() : combobox->palette.buttonText().color()) : WINUI3Colors[colorSchemeIndex][frameColorLight]); - painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius); if (sub & SC_ComboBoxArrow) { QRectF rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget).adjusted(4, 0, -4, 1); painter->setFont(assetFont); painter->setPen(combobox->palette.text().color()); painter->drawText(rect, QStringLiteral(u"\uE70D"), Qt::AlignVCenter | Qt::AlignHCenter); } - - if (combobox->editable) { - const qreal sublineOffset = secondLevelRoundingRadius; - painter->setPen(editSublineColor(option, colorSchemeIndex)); - painter->drawLine(rect.bottomLeft() + QPointF(sublineOffset, 1.0), rect.bottomRight() + QPointF(-sublineOffset, 1.0)); - } } break; #endif // QT_CONFIG(combobox) @@ -951,64 +906,39 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption break; } case PE_PanelLineEdit: - if (widget && widget->objectName() == QStringLiteral(u"qt_spinbox_lineedit")) - break; if (const auto *panel = qstyleoption_cast<const QStyleOptionFrame *>(option)) { - QRectF frameRect = option->rect.marginsRemoved(QMargins(1, 1, 1, 1)); - painter->setBrush(option->palette.brush(QPalette::Base)); - painter->setPen(Qt::NoPen); - painter->drawRoundedRect(frameRect, secondLevelRoundingRadius, secondLevelRoundingRadius); - // In case the QLineEdit is hovered overdraw the background with a alpha mask to - // highlight the QLineEdit. - if (state & State_MouseOver && !(state & State_HasFocus)) { - painter->setBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]); - painter->setPen(Qt::NoPen); - painter->drawRoundedRect(frameRect, secondLevelRoundingRadius, secondLevelRoundingRadius); - } + const auto frameRect = option->rect.marginsRemoved(QMargins(1, 1, 1, 1)); + drawRoundedRect(painter, frameRect, Qt::NoPen, option->palette.brush(QPalette::Base)); + if (panel->lineWidth > 0) proxy()->drawPrimitive(PE_FrameLineEdit, panel, painter, widget); + + const bool isMouseOver = state & State_MouseOver; + const bool hasFocus = state & State_HasFocus; + if (isMouseOver && !hasFocus && !highContrastTheme) + drawRoundedRect(painter, frameRect, Qt::NoPen, winUI3Color(subtleHighlightColor)); } break; - case PE_FrameLineEdit: { - const qreal sublineOffset = secondLevelRoundingRadius + 1.5; - if (widget && widget->parent() && qobject_cast<QComboBox*>(widget->parent())) - break; - QRectF rect = option->rect; - rect.adjust(1.5, 1.5, -1.5, -1.5); - painter->setBrush(Qt::NoBrush); - painter->setPen(highContrastTheme == true ? option->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorLight]); - painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius); - painter->setPen(editSublineColor(option, colorSchemeIndex)); - painter->drawLine(option->rect.bottomLeft() + QPointF(sublineOffset, 0.5), option->rect.bottomRight() + QPointF(-sublineOffset, 0.5)); - } + case PE_FrameLineEdit: + drawLineEditFrame(painter, option); break; case PE_Frame: { if (const auto *frame = qstyleoption_cast<const QStyleOptionFrame *>(option)) { - if (frame->frameShape == QFrame::NoFrame) - break; - QRectF rect = option->rect.adjusted(1,1,-1,-1); + const auto rect = option->rect.marginsRemoved(QMargins(1, 1, 1, 1)); if (qobject_cast<const QComboBoxPrivateContainer *>(widget)) { + QPen pen; if (highContrastTheme) - painter->setPen(QPen(option->palette.windowText().color(), 2)); + pen = QPen(option->palette.windowText().color(), 2); else - painter->setPen(Qt::NoPen); - painter->setBrush(WINUI3Colors[colorSchemeIndex][menuPanelFill]); - painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius); - } - painter->setBrush(option->palette.base()); - painter->setPen(Qt::NoPen); - painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius); + pen = Qt::NoPen; + drawRoundedRect(painter, rect, pen, WINUI3Colors[colorSchemeIndex][menuPanelFill]); + } else + drawRoundedRect(painter, rect, Qt::NoPen, option->palette.brush(QPalette::Base)); - painter->setBrush(Qt::NoBrush); - painter->setPen(WINUI3Colors[colorSchemeIndex][frameColorLight]); - painter->drawRoundedRect(rect.marginsRemoved(QMarginsF(0.5,0.5,0.5,0.5)), secondLevelRoundingRadius, secondLevelRoundingRadius); + if (frame->frameShape == QFrame::NoFrame) + break; - if (qobject_cast<const QTextEdit *>(widget)) { - QRegion clipRegion = option->rect; - QColor lineColor = state & State_HasFocus ? option->palette.accent().color() : option->palette.base().color(); - painter->setPen(lineColor); - painter->drawLine(option->rect.bottomLeft() + QPoint(1,-1), option->rect.bottomRight() + QPoint(-1,-1)); - } + drawLineEditFrame(painter, option, qobject_cast<const QTextEdit *>(widget) != nullptr); } break; } @@ -2442,12 +2372,33 @@ QColor QWindows11Style::buttonLabelColor(const QStyleOption *option, int colorSc : option->palette.buttonText().color(); } -QColor QWindows11Style::editSublineColor(const QStyleOption *option, int colorSchemeIndex) +void QWindows11Style::drawLineEditFrame(QPainter *p, const QStyleOption *o, bool isEditable) const +{ + const auto rect = QRectF(o->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5)); + const bool isHovered = o->state & State_MouseOver; + const auto frameCol = highContrastTheme + ? o->palette.color(isHovered ? QPalette::Accent + : QPalette::ButtonText) + : winUI3Color(frameColorLight); + drawRoundedRect(p, rect, frameCol, Qt::NoBrush); + + if (!isEditable) + return; + + QPainterStateGuard psg(p); + p->setClipRect(rect.marginsRemoved(QMarginsF(0, rect.height() - 0.5, 0, -1))); + const bool hasFocus = o->state & State_HasFocus; + const auto underlineCol = hasFocus + ? o->palette.color(QPalette::Accent) + : colorSchemeIndex == 0 ? QColor(0x80, 0x80, 0x80) + : QColor(0xa0, 0xa0, 0xa0); + const auto penUnderline = QPen(underlineCol, hasFocus ? 2 : 1); + drawRoundedRect(p, rect, penUnderline, Qt::NoBrush); +} + +QColor QWindows11Style::winUI3Color(enum WINUI3Color col) const { - const State state = option->state; - return state & State_HasFocus ? option->palette.accent().color() - : (colorSchemeIndex == 0 ? QColor(0x80, 0x80, 0x80) - : QColor(0xa0, 0xa0, 0xa0)); + return WINUI3Colors[colorSchemeIndex][col]; } #undef SET_IF_UNRESOLVED diff --git a/src/plugins/styles/modernwindows/qwindows11style_p.h b/src/plugins/styles/modernwindows/qwindows11style_p.h index 1be56fe3aa5..a8d675af954 100644 --- a/src/plugins/styles/modernwindows/qwindows11style_p.h +++ b/src/plugins/styles/modernwindows/qwindows11style_p.h @@ -21,7 +21,27 @@ QT_BEGIN_NAMESPACE class QWindows11StylePrivate; -class QWindows11Style; + +enum WINUI3Color { + subtleHighlightColor, //Subtle highlight based on alpha used for hovered elements + subtlePressedColor, //Subtle highlight based on alpha used for pressed elements + frameColorLight, //Color of frame around flyouts and controls except for Checkbox and Radiobutton + frameColorStrong, //Color of frame around Checkbox and Radiobuttons + controlStrongFill, //Color of controls with strong filling such as the right side of a slider + controlStrokeSecondary, + controlStrokePrimary, + controlFillTertiary, //Color of filled sunken controls + controlFillSecondary, //Color of filled hovered controls + menuPanelFill, //Color of menu panel + textOnAccentPrimary, //Color of text on controls filled in accent color + textOnAccentSecondary, //Color of text of sunken controls in accent color + controlTextSecondary, //Color of text of sunken controls + controlStrokeOnAccentSecondary, //Color of frame around Buttons in accent color + controlFillSolid, //Color for solid fill + surfaceStroke, //Color of MDI window frames + controlAccentDisabled, + textAccentDisabled +}; class QWindows11Style : public QWindowsVistaStyle { @@ -55,7 +75,8 @@ protected: private: static inline QBrush buttonFillBrush(const QStyleOption *option); static inline QColor buttonLabelColor(const QStyleOption *option, int colorSchemeIndex); - static inline QColor editSublineColor(const QStyleOption *option, int colorSchemeIndex); + void drawLineEditFrame(QPainter *p, const QStyleOption *o, bool isEditable = true) const; + inline QColor winUI3Color(enum WINUI3Color col) const; private: Q_DISABLE_COPY_MOVE(QWindows11Style) diff --git a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc index 4a5978566ed..df64db9f2cf 100644 --- a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc +++ b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc @@ -1341,6 +1341,19 @@ for an example. \row + \li QToolBox \target qtoolbox-widget + \li Supports the \l{box model}. + \br + \br + The individual tabs can by styled using the + \l{#tab-sub}{::tab} subcontrol. The tabs support the + \l{#only-one-ps}{:only-one}, \l{#first-ps}{:first}, + \l{#last-ps}{:last}, \l{#middle-ps}{:middle}, + \l{#previous-selected-ps}{:previous-selected}, + \l{#next-selected-ps}{:next-selected}, + \l{#selected-ps}{:selected} pseudo states. + + \row \li QToolButton \target qtoolbutton-widget \li Supports the \l{box model}. \br @@ -1374,19 +1387,6 @@ for an example. \row - \li QToolBox \target qtoolbox-widget - \li Supports the \l{box model}. - \br - \br - The individual tabs can by styled using the - \l{#tab-sub}{::tab} subcontrol. The tabs support the - \l{#only-one-ps}{:only-one}, \l{#first-ps}{:first}, - \l{#last-ps}{:last}, \l{#middle-ps}{:middle}, - \l{#previous-selected-ps}{:previous-selected}, - \l{#next-selected-ps}{:next-selected}, - \l{#selected-ps}{:selected} pseudo states. - - \row \li QToolTip \target qtooltip-widget \li Supports the \l{box model}. The \l{#opacity-prop}{opacity} property controls the opacity of the tooltip. diff --git a/src/widgets/kernel/qapplication.h b/src/widgets/kernel/qapplication.h index 83dfdc50bcd..c2c5f7264d4 100644 --- a/src/widgets/kernel/qapplication.h +++ b/src/widgets/kernel/qapplication.h @@ -141,6 +141,7 @@ public Q_SLOTS: protected: bool event(QEvent *) override; # if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) + QT_DEPRECATED_VERSION_X_6_10("This feature will be removed in Qt 7") bool compressEvent(QEvent *, QObject *receiver, QPostEventList *) override; # endif diff --git a/src/widgets/kernel/qtestsupport_widgets.cpp b/src/widgets/kernel/qtestsupport_widgets.cpp index f7b25b6643b..5a7200e58aa 100644 --- a/src/widgets/kernel/qtestsupport_widgets.cpp +++ b/src/widgets/kernel/qtestsupport_widgets.cpp @@ -16,14 +16,14 @@ QT_BEGIN_NAMESPACE -template <typename FunctorWindowGetter, typename FunctorPredicate, typename Timeout> -static bool qWaitForWidgetWindow(FunctorWindowGetter windowGetter, FunctorPredicate predicate, Timeout timeout) +template <typename Predicate> +static bool qWaitForWidgetWindow(QWidget *w, Predicate predicate, QDeadlineTimer timeout) { - if (!windowGetter()) + if (!w->window()->windowHandle()) return false; return QTest::qWaitFor([&]() { - if (QWindow *window = windowGetter()) + if (QWindow *window = w->window()->windowHandle()) return predicate(window); return false; }, timeout); @@ -55,9 +55,9 @@ Q_WIDGETS_EXPORT bool QTest::qWaitForWindowActive(QWidget *widget, int timeout) << "Falling back to qWaitForWindowExposed."; return qWaitForWindowExposed(widget, timeout); } - return qWaitForWidgetWindow([&]() { return widget->window()->windowHandle(); }, + return qWaitForWidgetWindow(widget, [&](QWindow *window) { return window->isActive(); }, - timeout); + QDeadlineTimer{timeout, Qt::TimerType::PreciseTimer}); } @@ -79,11 +79,10 @@ Q_WIDGETS_EXPORT bool QTest::qWaitForWindowActive(QWidget *widget, int timeout) */ Q_WIDGETS_EXPORT bool QTest::qWaitForWindowFocused(QWidget *widget, QDeadlineTimer timeout) { - return qWaitForWidgetWindow([&]() { - return widget->window()->windowHandle(); - }, [&](QWindow *window) { - return qGuiApp->focusWindow() == window; - }, timeout); + return qWaitForWidgetWindow(widget, + [&](QWindow *window) { + return qGuiApp->focusWindow() == window; + }, timeout); } /*! @@ -102,9 +101,9 @@ Q_WIDGETS_EXPORT bool QTest::qWaitForWindowFocused(QWidget *widget, QDeadlineTim */ Q_WIDGETS_EXPORT bool QTest::qWaitForWindowExposed(QWidget *widget, int timeout) { - return qWaitForWidgetWindow([&]() { return widget->window()->windowHandle(); }, + return qWaitForWidgetWindow(widget, [&](QWindow *window) { return window->isExposed(); }, - timeout); + QDeadlineTimer{timeout, Qt::TimerType::PreciseTimer}); } namespace QTest { diff --git a/src/xml/dom/qdom.cpp b/src/xml/dom/qdom.cpp index f3c7e2d9938..a6a502e5b47 100644 --- a/src/xml/dom/qdom.cpp +++ b/src/xml/dom/qdom.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:critical reason:data-parser #include <qplatformdefs.h> #include <qdom.h> diff --git a/src/xml/dom/qdomhelpers.cpp b/src/xml/dom/qdomhelpers.cpp index c41529f289d..dae25aa07d0 100644 --- a/src/xml/dom/qdomhelpers.cpp +++ b/src/xml/dom/qdomhelpers.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2019 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:critical reason:data-parser #include <QtXml/qtxmlglobal.h> |