From 28a264cfe2d161f2eba3b1efa3ea4985445cd2de Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 8 Mar 2019 10:55:14 +0100 Subject: Fix alpha blending regression with WA_StacksOnTop QOpenGLWidgets 0bc42886898 in Qt 5.6 introduced support for premultiplied alpha in the raster-rendered QWidget content. Unfortunately this introduced a regression for OpenGL content from QOpenGLWidgets with WA_StacksOnTop set: these used standard alpha blending in 5.5 and earlier, and switching them to premultiplied (in case the - unrelated - raster content has a _Premultiplied QImage format) breaks all content that was done with non-premultiplied alpha in mind, for example the qopenglwidget example's "Transparent background" checkbox. Restore the pre-5.6 behavior. Fixes: QTBUG-74285 Change-Id: I76fcadd53cd436efa2b619b8d6739270995d044f Reviewed-by: Allan Sandfeld Jensen --- src/gui/painting/qplatformbackingstore.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index afb4613ba5..c71d82546a 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -446,6 +446,11 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i d_ptr->blitter->setRedBlueSwizzle(false); } + // There is no way to tell if the OpenGL-rendered content is premultiplied or not. + // For compatibility, assume that it is not, and use normal alpha blend always. + if (d_ptr->premultiplied) + funcs->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + // Textures for renderToTexture widgets that have WA_AlwaysStackOnTop set. for (int i = 0; i < textures->count(); ++i) { if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) -- cgit v1.2.3 From 3b7db8ac90ba36949cb4168f07cc8dace47758a7 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Fri, 29 Mar 2019 10:36:21 +0100 Subject: Fix assert/crash when creating QBrush with null QGradient MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The QBrush constructor taking a QGradient would assert or crash if passed a null (NoGradient) gradient. But it is not necessary for the API to be as brittle as that: instead the result can simply be a null QBrush object, i.e. the same as the default QBrush() constructor creates (style == NoBrush). This issue comes up now since with the recent introduction of QGradient presets, the API opens for using QGradient directly, whereas earlier, only the subclasses QLinearGradient etc. were to be used. Fixes: QTBUG-74648 Change-Id: I1a9b1c4654e4375aa6684700a262cc0946851448 Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Tor Arne Vestbø --- src/gui/painting/qbrush.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index 860653cc4c..bcc23fa683 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -545,9 +545,11 @@ QBrush::QBrush(const QBrush &other) */ QBrush::QBrush(const QGradient &gradient) { - Q_ASSERT_X(gradient.type() != QGradient::NoGradient, "QBrush::QBrush", - "QGradient should not be used directly, use the linear, radial\n" - "or conical gradients instead"); + if (Q_UNLIKELY(gradient.type() == QGradient::NoGradient)) { + d.reset(nullBrushInstance()); + d->ref.ref(); + return; + } const Qt::BrushStyle enum_table[] = { Qt::LinearGradientPattern, @@ -1376,8 +1378,10 @@ QGradient::QGradient(Preset preset) }(); const QJsonValue presetData = jsonPresets[preset - 1]; - if (!presetData.isObject()) + if (!presetData.isObject()) { + qWarning("QGradient: Undefined preset %i", preset); return; + } m_type = LinearGradient; setCoordinateMode(ObjectMode); -- cgit v1.2.3 From 6ccbe7ffdfee0a69ba50d22f577075b1d8cb0b04 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Fri, 29 Mar 2019 00:29:00 +0100 Subject: macOS: When a menu item has an italic font it should respect this MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Id8d2c5c0d0407ead66700d38634f342f489a2842 Fixes: QTBUG-69489 Reviewed-by: Morten Johan Sørvig --- src/plugins/styles/mac/qmacstyle_mac.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 9a11c4d818..fd006b1ca3 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -4323,7 +4323,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter d->setupNSGraphicsContext(cgCtx, YES); [s.toNSString() drawInRect:textRect - withAttributes:@{ NSFontAttributeName:f, NSForegroundColorAttributeName:c }]; + withAttributes:@{ NSFontAttributeName:f, NSForegroundColorAttributeName:c, + NSObliquenessAttributeName: [NSNumber numberWithDouble: myFont.italic() ? 0.3 : 0.0]}]; d->restoreNSGraphicsContext(cgCtx); } else { -- cgit v1.2.3 From 409e3eab092ae9896f453b69f4b4749e654680bb Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Thu, 28 Mar 2019 10:42:38 +0100 Subject: QMacStyle - fix PE_InticatorTabClose handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit for the case a custom style sheet is in use and QStyleSheetStyle replaces the widget (close button) with its parent (QTabBar). We still need this button though to compare against tabButton on a hovered tab. This allows us to have, indeed, native-looking tabs as documented (aka similar to Safari or the "Terminal" application). Change-Id: I53ff78699e705db6d7c7b84774b8e188a1277535 Fixes: QTBUG-61092 Fixes: QTBUG-74689 Reviewed-by: Morten Johan Sørvig --- src/plugins/styles/mac/qmacstyle_mac.mm | 6 ++++-- src/widgets/styles/qstylesheetstyle.cpp | 9 ++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index fd006b1ca3..0745e917a2 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -3411,18 +3411,20 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai case PE_IndicatorTabClose: { // Make close button visible only on the hovered tab. QTabBar *tabBar = qobject_cast(w->parentWidget()); + const QWidget *closeBtn = w; if (!tabBar) { // QStyleSheetStyle instead of CloseButton (which has // a QTabBar as a parent widget) uses the QTabBar itself: tabBar = qobject_cast(const_cast(w)); + closeBtn = decltype(closeBtn)(property("_q_styleSheetRealCloseButton").value()); } if (tabBar) { const bool documentMode = tabBar->documentMode(); const QTabBarPrivate *tabBarPrivate = static_cast(QObjectPrivate::get(tabBar)); const int hoveredTabIndex = tabBarPrivate->hoveredTabIndex(); if (!documentMode || - (hoveredTabIndex != -1 && ((w == tabBar->tabButton(hoveredTabIndex, QTabBar::LeftSide)) || - (w == tabBar->tabButton(hoveredTabIndex, QTabBar::RightSide))))) { + (hoveredTabIndex != -1 && ((closeBtn == tabBar->tabButton(hoveredTabIndex, QTabBar::LeftSide)) || + (closeBtn == tabBar->tabButton(hoveredTabIndex, QTabBar::RightSide))))) { const bool hover = (opt->state & State_MouseOver); const bool selected = (opt->state & State_Selected); const bool pressed = (opt->state & State_Sunken); diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index 79fa20851f..73b147e622 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -4590,8 +4590,12 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op break; #if QT_CONFIG(tabbar) case PE_IndicatorTabClose: - if (w) + if (w) { + // QMacStyle needs a real widget, not its parent - to implement + // 'document mode' properly, drawing nothing if a tab is not hovered. + baseStyle()->setProperty("_q_styleSheetRealCloseButton", QVariant::fromValue((void *)w)); w = w->parentWidget(); //match on the QTabBar instead of the CloseButton + } pseudoElement = PseudoElement_TabBarTabCloseButton; #endif @@ -4609,6 +4613,9 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op } else { baseStyle()->drawPrimitive(pe, opt, p, w); } + + if (baseStyle()->property("_q_styleSheetRealCloseButton").toBool()) + baseStyle()->setProperty("_q_styleSheetRealCloseButton", QVariant(QVariant::Invalid)); } QPixmap QStyleSheetStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap& pixmap, -- cgit v1.2.3 From e4532224145a0a72cde9b40cb7fd39011624d1c1 Mon Sep 17 00:00:00 2001 From: Dmitry Kazakov Date: Sun, 10 Mar 2019 14:48:58 +0300 Subject: Fix tablet jitter on X11 We should get the correct stylus position from the valuators, not from the X11-provided global position. Global position is rounded to the nearest FP16 values, which is not enough for smooth painting. [ChangeLog][Platform Specific Changes][X11 / XCB] QTabletEvent coordinates now come from AbsX/AbsY valuators in the X11 event, in more precise 32.32 fixed-point format, scaled to fit the virtual desktop. It's possible to revert to using the legacy 16.16-format event_x/event_y coordinates as in previous releases by setting the QT_XCB_TABLET_LEGACY_COORDINATES environment variable. Task-number: QTBUG-45375 Fixes: QTBUG-48151 Change-Id: Ie701446b3586296bcb8fb09158f387ba6a7cbf07 Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 30 ++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 04ddd3c98c..91fd612cde 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -1208,6 +1208,11 @@ bool QXcbConnection::xi2HandleTabletEvent(const void *event, TabletData *tabletD return handled; } +inline qreal scaleOneValuator(qreal normValue, qreal screenMin, qreal screenSize) +{ + return screenMin + normValue * screenSize; +} + void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletData) { auto *ev = reinterpret_cast(event); @@ -1220,6 +1225,17 @@ void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletD QPointF global(fixed1616ToReal(ev->root_x), fixed1616ToReal(ev->root_y)); double pressure = 0, rotation = 0, tangentialPressure = 0; int xTilt = 0, yTilt = 0; + static const bool useValuators = !qEnvironmentVariableIsSet("QT_XCB_TABLET_LEGACY_COORDINATES"); + + // Valuators' values are relative to the physical size of the current virtual + // screen. Therefore we cannot use QScreen/QWindow geometry and should use + // QPlatformWindow/QPlatformScreen instead. + QRect physicalScreenArea; + if (Q_LIKELY(useValuators)) { + const QList siblings = window->screen()->handle()->virtualSiblings(); + for (const QPlatformScreen *screen : siblings) + physicalScreenArea |= screen->geometry(); + } for (QHash::iterator it = tabletData->valuatorInfo.begin(), ite = tabletData->valuatorInfo.end(); it != ite; ++it) { @@ -1228,6 +1244,20 @@ void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletD xi2GetValuatorValueIfSet(event, classInfo.number, &classInfo.curVal); double normalizedValue = (classInfo.curVal - classInfo.minVal) / (classInfo.maxVal - classInfo.minVal); switch (valuator) { + case QXcbAtom::AbsX: + if (Q_LIKELY(useValuators)) { + const qreal value = scaleOneValuator(normalizedValue, physicalScreenArea.x(), physicalScreenArea.width()); + global.setX(value); + local.setX(value - window->handle()->geometry().x()); + } + break; + case QXcbAtom::AbsY: + if (Q_LIKELY(useValuators)) { + qreal value = scaleOneValuator(normalizedValue, physicalScreenArea.y(), physicalScreenArea.height()); + global.setY(value); + local.setY(value - window->handle()->geometry().y()); + } + break; case QXcbAtom::AbsPressure: pressure = normalizedValue; break; -- cgit v1.2.3 From 954b73445cfbfef01207d51d1b986c6dd796c6d0 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 1 Apr 2019 15:22:15 +0200 Subject: Refine underflow check in QLocaleData::convertDoubleToFloat() A string can parse as a non-zero double that's smaller than the smallest float yet be a faithful representation of the smallest float. So rather than testing for non-zero doubles less than the smallest float, test for non-zero doubles that cast to float zero; these underflow. This means small values close below the smallest float shall round up to it, rather than down to zero, requiring a tweak to an existing test. Added a test for the boundary case (and tidied the test data). Fixes: QTBUG-74833 Change-Id: I4cb30b3c0e54683574b98253505607caaf88fbfb Reviewed-by: Thiago Macieira --- src/corelib/tools/qlocale_p.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h index a96ecf1c1c..7487c9128c 100644 --- a/src/corelib/tools/qlocale_p.h +++ b/src/corelib/tools/qlocale_p.h @@ -252,10 +252,8 @@ public: const float huge = std::numeric_limits::infinity(); return d < 0 ? -huge : huge; } - if (std::fabs(d) >= std::numeric_limits::min() // i.e. d != 0 - && std::fabs(d) < std::numeric_limits::min()) { - // Values smaller than std::numeric_limits::min() have - // failed already; match them. + if (d != 0 && float(d) == 0) { + // Values that underflow double already failed. Match them: if (ok != 0) *ok = false; return 0; -- cgit v1.2.3 From 685b8db13aa19e734f239678bae23607fcededbd Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Thu, 28 Mar 2019 16:49:57 +0300 Subject: Forward devicePixelRatio in QPixmap::mask() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also add a test checking that devicePixelRatio is forwarded to derivatives of QPixmap. Change-Id: Idb2b3f033ccc0fd49bf54b11f5dffbce5a19b006 Reviewed-by: Morten Johan Sørvig --- src/gui/image/qplatformpixmap.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/gui/image/qplatformpixmap.cpp b/src/gui/image/qplatformpixmap.cpp index 2209c3de4d..a2e01147c4 100644 --- a/src/gui/image/qplatformpixmap.cpp +++ b/src/gui/image/qplatformpixmap.cpp @@ -178,6 +178,7 @@ QBitmap QPlatformPixmap::mask() const if (mask.isNull()) // allocation failed return QBitmap(); + mask.setDevicePixelRatio(devicePixelRatio()); mask.setColorCount(2); mask.setColor(0, QColor(Qt::color0).rgba()); mask.setColor(1, QColor(Qt::color1).rgba()); -- cgit v1.2.3 From 011794130c8e4bb64dbc3c8c9b50849b278cdda3 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Thu, 28 Mar 2019 13:59:35 +0300 Subject: Forward physical parameters for derived QImages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit More specifically, for masks and rotated images. Add tests for it, also add tests that image metadata is forwarded for converted and copied images. Fixes: QTBUG-49259 Change-Id: I05d4a468b17f53a2625500b871c01b2c53b981a1 Reviewed-by: Morten Johan Sørvig --- src/gui/image/qimage.cpp | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 3e18ca6528..ed6f23ee56 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -1089,15 +1089,31 @@ void QImage::detach() } -static void copyMetadata(QImageData *dst, const QImageData *src) +static void copyPhysicalMetadata(QImageData *dst, const QImageData *src) { - // Doesn't copy colortable and alpha_clut, or offset. dst->dpmx = src->dpmx; dst->dpmy = src->dpmy; dst->devicePixelRatio = src->devicePixelRatio; +} + +static void copyMetadata(QImageData *dst, const QImageData *src) +{ + // Doesn't copy colortable and alpha_clut, or offset. + copyPhysicalMetadata(dst, src); dst->text = src->text; } +static void copyMetadata(QImage *dst, const QImage &src) +{ + dst->setDotsPerMeterX(src.dotsPerMeterX()); + dst->setDotsPerMeterY(src.dotsPerMeterY()); + dst->setDevicePixelRatio(src.devicePixelRatio()); + const auto textKeys = src.textKeys(); + for (const auto &key: textKeys) + dst->setText(key, src.text(key)); + +} + /*! \fn QImage QImage::copy(int x, int y, int width, int height) const \overload @@ -2924,8 +2940,10 @@ QImage QImage::createAlphaMask(Qt::ImageConversionFlags flags) const } QImage mask(d->width, d->height, Format_MonoLSB); - if (!mask.isNull()) + if (!mask.isNull()) { dither_to_Mono(mask.d, d, flags, true); + copyPhysicalMetadata(mask.d, d); + } return mask; } @@ -3043,6 +3061,7 @@ QImage QImage::createHeuristicMask(bool clipTight) const #undef PIX + copyPhysicalMetadata(m.d, d); return m; } #endif //QT_NO_IMAGE_HEURISTIC_MASK @@ -3086,6 +3105,8 @@ QImage QImage::createMaskFromColor(QRgb color, Qt::MaskMode mode) const } if (mode == Qt::MaskOutColor) maskImage.invertPixels(); + + copyPhysicalMetadata(maskImage.d, d); return maskImage; } @@ -4655,8 +4676,7 @@ QImage QImage::smoothScaled(int w, int h) const { static QImage rotated90(const QImage &image) { QImage out(image.height(), image.width(), image.format()); - out.setDotsPerMeterX(image.dotsPerMeterY()); - out.setDotsPerMeterY(image.dotsPerMeterX()); + copyMetadata(&out, image); if (image.colorCount() > 0) out.setColorTable(image.colorTable()); int w = image.width(); @@ -4684,8 +4704,7 @@ static QImage rotated180(const QImage &image) return image.mirrored(true, true); QImage out(image.width(), image.height(), image.format()); - out.setDotsPerMeterX(image.dotsPerMeterY()); - out.setDotsPerMeterY(image.dotsPerMeterX()); + copyMetadata(&out, image); if (image.colorCount() > 0) out.setColorTable(image.colorTable()); int w = image.width(); @@ -4697,8 +4716,7 @@ static QImage rotated180(const QImage &image) static QImage rotated270(const QImage &image) { QImage out(image.height(), image.width(), image.format()); - out.setDotsPerMeterX(image.dotsPerMeterY()); - out.setDotsPerMeterY(image.dotsPerMeterX()); + copyMetadata(&out, image); if (image.colorCount() > 0) out.setColorTable(image.colorTable()); int w = image.width(); -- cgit v1.2.3