diff options
Diffstat (limited to 'src/plugins')
262 files changed, 3420 insertions, 2454 deletions
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp index e74b1cf744..85a9f9b9e0 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp @@ -250,7 +250,7 @@ void QNetworkManagerEngine::interfacePropertiesChanged(const QMap<QString, QVari if (i.key() == QLatin1String("ActiveConnections")) { // Active connections changed, update configurations. - const auto activeConnections = qdbus_cast<QList<QDBusObjectPath> >(i.value().value<QDBusArgument>()); + const auto activeConnections = qdbus_cast<QList<QDBusObjectPath> >(qvariant_cast<QDBusArgument>(i.value())); QStringList identifiers = accessPointConfigurations.keys(); QStringList priorActiveConnections = activeConnectionsList.keys(); diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp index 35199eb7a2..2d6cba1791 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp @@ -193,7 +193,7 @@ QList <QDBusObjectPath> QNetworkManagerInterface::activeConnections() const { if (propertyMap.contains("ActiveConnections")) { - const QDBusArgument &dbusArgs = propertyMap.value("ActiveConnections").value<QDBusArgument>(); + const QDBusArgument &dbusArgs = qvariant_cast<QDBusArgument>(propertyMap.value("ActiveConnections")); QDBusObjectPath path; QList <QDBusObjectPath> list; @@ -403,7 +403,7 @@ quint32 QNetworkManagerInterfaceDevice::deviceType() const QDBusObjectPath QNetworkManagerInterfaceDevice::ip4config() const { if (propertyMap.contains("Ip4Config")) - return propertyMap.value("Ip4Config").value<QDBusObjectPath>(); + return qvariant_cast<QDBusObjectPath>(propertyMap.value("Ip4Config")); return QDBusObjectPath(); } @@ -411,7 +411,7 @@ void QNetworkManagerInterfaceDevice::propertiesSwap(QMap<QString,QVariant> map) { for (auto i = map.cbegin(), end = map.cend(); i != end; ++i) { if (i.key() == QLatin1String("AvailableConnections")) { //Device - const QDBusArgument &dbusArgs = i.value().value<QDBusArgument>(); + const QDBusArgument &dbusArgs = qvariant_cast<QDBusArgument>(i.value()); QDBusObjectPath path; QStringList paths; dbusArgs.beginArray(); @@ -489,7 +489,7 @@ QStringList QNetworkManagerInterfaceDeviceWired::availableConnections() { QStringList list; if (propertyMap.contains("AvailableConnections")) { - const QDBusArgument &dbusArgs = propertyMap.value("Carrier").value<QDBusArgument>(); + const QDBusArgument &dbusArgs = qvariant_cast<QDBusArgument>(propertyMap.value("Carrier")); QDBusObjectPath path; dbusArgs.beginArray(); while (!dbusArgs.atEnd()) { @@ -598,7 +598,7 @@ quint32 QNetworkManagerInterfaceDeviceWireless::bitrate() const QDBusObjectPath QNetworkManagerInterfaceDeviceWireless::activeAccessPoint() const { if (propertyMap.contains("ActiveAccessPoint")) - return propertyMap.value("ActiveAccessPoint").value<QDBusObjectPath>(); + return qvariant_cast<QDBusObjectPath>(propertyMap.value("ActiveAccessPoint")); return QDBusObjectPath(); } @@ -931,14 +931,14 @@ QNetworkManagerConnectionActive::~QNetworkManagerConnectionActive() QDBusObjectPath QNetworkManagerConnectionActive::connection() const { if (propertyMap.contains("Connection")) - return propertyMap.value("Connection").value<QDBusObjectPath>(); + return qvariant_cast<QDBusObjectPath>(propertyMap.value("Connection")); return QDBusObjectPath(); } QDBusObjectPath QNetworkManagerConnectionActive::specificObject() const { if (propertyMap.contains("SpecificObject")) - return propertyMap.value("SpecificObject").value<QDBusObjectPath>(); + return qvariant_cast<QDBusObjectPath>(propertyMap.value("SpecificObject")); return QDBusObjectPath(); } @@ -946,7 +946,7 @@ QStringList QNetworkManagerConnectionActive::devices() const { QStringList list; if (propertyMap.contains("Devices")) { - const QDBusArgument &dbusArgs = propertyMap.value("Devices").value<QDBusArgument>(); + const QDBusArgument &dbusArgs = qvariant_cast<QDBusArgument>(propertyMap.value("Devices")); QDBusObjectPath path; dbusArgs.beginArray(); diff --git a/src/plugins/bearer/qnetworksession_impl.cpp b/src/plugins/bearer/qnetworksession_impl.cpp index c6b678ab20..8eba9ccc42 100644 --- a/src/plugins/bearer/qnetworksession_impl.cpp +++ b/src/plugins/bearer/qnetworksession_impl.cpp @@ -65,7 +65,7 @@ static QBearerEngineImpl *getEngineFromId(const QString &id) } } - return 0; + return nullptr; } class QNetworkSessionManagerPrivate : public QObject @@ -73,7 +73,7 @@ class QNetworkSessionManagerPrivate : public QObject Q_OBJECT public: - QNetworkSessionManagerPrivate(QObject *parent = 0) : QObject(parent) {} + QNetworkSessionManagerPrivate(QObject *parent = nullptr) : QObject(parent) {} ~QNetworkSessionManagerPrivate() {} inline void forceSessionClose(const QNetworkConfiguration &config) @@ -119,7 +119,7 @@ void QNetworkSessionPrivateImpl::syncStateWithInterface() // Defer setting serviceConfig and activeConfig until open(). Q_FALLTHROUGH(); default: - engine = 0; + engine = nullptr; } networkConfigurationsChanged(); diff --git a/src/plugins/generic/tuiotouch/qtuiohandler.cpp b/src/plugins/generic/tuiotouch/qtuiohandler.cpp index cb82672acd..6ad4597b19 100644 --- a/src/plugins/generic/tuiotouch/qtuiohandler.cpp +++ b/src/plugins/generic/tuiotouch/qtuiohandler.cpp @@ -226,7 +226,7 @@ void QTuioHandler::process2DCurSource(const QOscMessage &message) return; } - if (QMetaType::Type(arguments.at(1).type()) != QMetaType::QByteArray) { + if (QMetaType::Type(arguments.at(1).userType()) != QMetaType::QByteArray) { qCWarning(lcTuioSource, "Ignoring malformed TUIO source message (bad argument type)"); return; } @@ -248,7 +248,7 @@ void QTuioHandler::process2DCurAlive(const QOscMessage &message) QMap<int, QTuioCursor> newActiveCursors; for (int i = 1; i < arguments.count(); ++i) { - if (QMetaType::Type(arguments.at(i).type()) != QMetaType::Int) { + if (QMetaType::Type(arguments.at(i).userType()) != QMetaType::Int) { qCWarning(lcTuioHandler) << "Ignoring malformed TUIO alive message (bad argument on position" << i << arguments << ')'; return; } @@ -293,12 +293,12 @@ void QTuioHandler::process2DCurSet(const QOscMessage &message) return; } - if (QMetaType::Type(arguments.at(1).type()) != QMetaType::Int || - QMetaType::Type(arguments.at(2).type()) != QMetaType::Float || - QMetaType::Type(arguments.at(3).type()) != QMetaType::Float || - QMetaType::Type(arguments.at(4).type()) != QMetaType::Float || - QMetaType::Type(arguments.at(5).type()) != QMetaType::Float || - QMetaType::Type(arguments.at(6).type()) != QMetaType::Float + if (QMetaType::Type(arguments.at(1).userType()) != QMetaType::Int || + QMetaType::Type(arguments.at(2).userType()) != QMetaType::Float || + QMetaType::Type(arguments.at(3).userType()) != QMetaType::Float || + QMetaType::Type(arguments.at(4).userType()) != QMetaType::Float || + QMetaType::Type(arguments.at(5).userType()) != QMetaType::Float || + QMetaType::Type(arguments.at(6).userType()) != QMetaType::Float ) { qCWarning(lcTuioSet) << "Ignoring malformed TUIO set message with bad types: " << arguments; return; @@ -391,7 +391,7 @@ void QTuioHandler::process2DObjSource(const QOscMessage &message) return; } - if (QMetaType::Type(arguments.at(1).type()) != QMetaType::QByteArray) { + if (QMetaType::Type(arguments.at(1).userType()) != QMetaType::QByteArray) { qCWarning(lcTuioSource, "Ignoring malformed TUIO source message (bad argument type)"); return; } @@ -413,7 +413,7 @@ void QTuioHandler::process2DObjAlive(const QOscMessage &message) QMap<int, QTuioToken> newActiveTokens; for (int i = 1; i < arguments.count(); ++i) { - if (QMetaType::Type(arguments.at(i).type()) != QMetaType::Int) { + if (QMetaType::Type(arguments.at(i).userType()) != QMetaType::Int) { qCWarning(lcTuioHandler) << "Ignoring malformed TUIO alive message (bad argument on position" << i << arguments << ')'; return; } @@ -458,16 +458,16 @@ void QTuioHandler::process2DObjSet(const QOscMessage &message) return; } - if (QMetaType::Type(arguments.at(1).type()) != QMetaType::Int || - QMetaType::Type(arguments.at(2).type()) != QMetaType::Int || - QMetaType::Type(arguments.at(3).type()) != QMetaType::Float || - QMetaType::Type(arguments.at(4).type()) != QMetaType::Float || - QMetaType::Type(arguments.at(5).type()) != QMetaType::Float || - QMetaType::Type(arguments.at(6).type()) != QMetaType::Float || - QMetaType::Type(arguments.at(7).type()) != QMetaType::Float || - QMetaType::Type(arguments.at(8).type()) != QMetaType::Float || - QMetaType::Type(arguments.at(9).type()) != QMetaType::Float || - QMetaType::Type(arguments.at(10).type()) != QMetaType::Float) { + if (QMetaType::Type(arguments.at(1).userType()) != QMetaType::Int || + QMetaType::Type(arguments.at(2).userType()) != QMetaType::Int || + QMetaType::Type(arguments.at(3).userType()) != QMetaType::Float || + QMetaType::Type(arguments.at(4).userType()) != QMetaType::Float || + QMetaType::Type(arguments.at(5).userType()) != QMetaType::Float || + QMetaType::Type(arguments.at(6).userType()) != QMetaType::Float || + QMetaType::Type(arguments.at(7).userType()) != QMetaType::Float || + QMetaType::Type(arguments.at(8).userType()) != QMetaType::Float || + QMetaType::Type(arguments.at(9).userType()) != QMetaType::Float || + QMetaType::Type(arguments.at(10).userType()) != QMetaType::Float) { qCWarning(lcTuioSet) << "Ignoring malformed TUIO set message with bad types: " << arguments; return; } diff --git a/src/plugins/imageformats/gif/main.cpp b/src/plugins/imageformats/gif/main.cpp index c171111fac..993871420c 100644 --- a/src/plugins/imageformats/gif/main.cpp +++ b/src/plugins/imageformats/gif/main.cpp @@ -62,7 +62,7 @@ QImageIOPlugin::Capabilities QGifPlugin::capabilities(QIODevice *device, const Q { if (format == "gif" || (device && device->isReadable() && QGifHandler::canRead(device))) return Capabilities(CanRead); - return 0; + return { }; } QImageIOHandler *QGifPlugin::create(QIODevice *device, const QByteArray &format) const diff --git a/src/plugins/imageformats/gif/qgifhandler.cpp b/src/plugins/imageformats/gif/qgifhandler.cpp index a6029b691c..61981b305f 100644 --- a/src/plugins/imageformats/gif/qgifhandler.cpp +++ b/src/plugins/imageformats/gif/qgifhandler.cpp @@ -147,8 +147,8 @@ private: */ QGIFFormat::QGIFFormat() { - globalcmap = 0; - localcmap = 0; + globalcmap = nullptr; + localcmap = nullptr; lncols = 0; gncols = 0; disposal = NoDisposal; @@ -160,9 +160,9 @@ QGIFFormat::QGIFFormat() lcmap = false; newFrame = false; partialNewFrame = false; - table[0] = 0; - table[1] = 0; - stack = 0; + table[0] = nullptr; + table[1] = nullptr; + stack = nullptr; } /*! @@ -550,7 +550,7 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, } oldcode=incode; const int h = image->height(); - QRgb *line = 0; + QRgb *line = nullptr; if (!out_of_bounds && h > y) line = (QRgb*)FAST_SCAN_LINE(bits, bpl, y); while (sp>stack) { @@ -1215,11 +1215,4 @@ int QGifHandler::currentImageNumber() const return frameNumber; } -#if QT_DEPRECATED_SINCE(5, 13) -QByteArray QGifHandler::name() const -{ - return "gif"; -} -#endif - QT_END_NAMESPACE diff --git a/src/plugins/imageformats/gif/qgifhandler_p.h b/src/plugins/imageformats/gif/qgifhandler_p.h index c6592043ce..f19777fa18 100644 --- a/src/plugins/imageformats/gif/qgifhandler_p.h +++ b/src/plugins/imageformats/gif/qgifhandler_p.h @@ -73,10 +73,6 @@ public: bool read(QImage *image) override; bool write(const QImage &image) override; -#if QT_DEPRECATED_SINCE(5, 13) - QByteArray name() const override; -#endif - static bool canRead(QIODevice *device); QVariant option(ImageOption option) const override; diff --git a/src/plugins/imageformats/ico/main.cpp b/src/plugins/imageformats/ico/main.cpp index baaf33e1fc..b00d8c7fd3 100644 --- a/src/plugins/imageformats/ico/main.cpp +++ b/src/plugins/imageformats/ico/main.cpp @@ -46,9 +46,9 @@ QImageIOPlugin::Capabilities QICOPlugin::capabilities(QIODevice *device, const Q if (format == "ico" || format == "cur") return Capabilities(CanRead | CanWrite); if (!format.isEmpty()) - return 0; + return { }; if (!device->isOpen()) - return 0; + return { }; Capabilities cap; if (device->isReadable() && QtIcoHandler::canRead(device)) diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp index c8e31dceac..88ff1f8391 100644 --- a/src/plugins/imageformats/ico/qicohandler.cpp +++ b/src/plugins/imageformats/ico/qicohandler.cpp @@ -535,8 +535,6 @@ QImage ICOReader::iconAt(int index) if (!mask.isNull()) { img = image; img.setAlphaChannel(mask); - // (Luckily, it seems that setAlphaChannel() does not ruin the alpha values - // of partially transparent pixels in those icons that have that) } } } @@ -615,13 +613,7 @@ bool ICOReader::write(QIODevice *device, const QVector<QImage> &images) } QImage maskImage(image.width(), image.height(), QImage::Format_Mono); image = image.convertToFormat(QImage::Format_ARGB32); - - if (image.hasAlphaChannel()) { - maskImage = image.createAlphaMask(); - } else { - maskImage.fill(0xff); - } - maskImage = maskImage.convertToFormat(QImage::Format_Mono); + maskImage.fill(Qt::color1); int nbits = 32; int bpl_bmp = ((image.width()*nbits+31)/32)*4; @@ -671,7 +663,7 @@ bool ICOReader::write(QIODevice *device, const QVector<QImage> &images) *b++ = qRed(*p); *b++ = qAlpha(*p); if (qAlpha(*p) > 0) // Even mostly transparent pixels must not be masked away - maskImage.setPixel(x, y, Qt::color1); // (i.e. createAlphaMask() takes away too much) + maskImage.setPixel(x, y, 0); p++; x++; } @@ -679,7 +671,6 @@ bool ICOReader::write(QIODevice *device, const QVector<QImage> &images) } delete[] buf; - maskImage.invertPixels(); // seems as though it needs this // NOTE! !! The mask is only flipped vertically - not horizontally !! for (y = maskImage.height() - 1; y >= 0; y--) buffer.write((char*)maskImage.scanLine(y), maskImage.bytesPerLine()); @@ -818,17 +809,6 @@ bool QtIcoHandler::write(const QImage &image) return ICOReader::write(device, imgs); } -#if QT_DEPRECATED_SINCE(5, 13) -/*! - * Return the common identifier of the format. - * For ICO format this will return "ico". - */ -QByteArray QtIcoHandler::name() const -{ - return "ico"; -} -#endif - /*! \reimp */ diff --git a/src/plugins/imageformats/ico/qicohandler.h b/src/plugins/imageformats/ico/qicohandler.h index 328dfce47e..0d44a67dfc 100644 --- a/src/plugins/imageformats/ico/qicohandler.h +++ b/src/plugins/imageformats/ico/qicohandler.h @@ -54,10 +54,6 @@ public: bool read(QImage *image) override; bool write(const QImage &image) override; -#if QT_DEPRECATED_SINCE(5, 13) - QByteArray name() const override; -#endif - int imageCount() const override; bool jumpToImage(int imageNumber) override; bool jumpToNextImage() override; diff --git a/src/plugins/imageformats/jpeg/main.cpp b/src/plugins/imageformats/jpeg/main.cpp index 58442053a1..83f13c4a9d 100644 --- a/src/plugins/imageformats/jpeg/main.cpp +++ b/src/plugins/imageformats/jpeg/main.cpp @@ -51,9 +51,9 @@ QImageIOPlugin::Capabilities QJpegPlugin::capabilities(QIODevice *device, const if (format == "jpeg" || format == "jpg") return Capabilities(CanRead | CanWrite); if (!format.isEmpty()) - return 0; + return { }; if (!device->isOpen()) - return 0; + return { }; Capabilities cap; if (device->isReadable() && QJpegHandler::canRead(device)) diff --git a/src/plugins/imageformats/jpeg/qjpeghandler.cpp b/src/plugins/imageformats/jpeg/qjpeghandler.cpp index 1f1675e490..fed585a82e 100644 --- a/src/plugins/imageformats/jpeg/qjpeghandler.cpp +++ b/src/plugins/imageformats/jpeg/qjpeghandler.cpp @@ -248,13 +248,12 @@ static bool ensureValidImage(QImage *dest, struct jpeg_decompress_struct *info, static bool read_jpeg_image(QImage *outImage, QSize scaledSize, QRect scaledClipRect, - QRect clipRect, volatile int inQuality, + QRect clipRect, int quality, Rgb888ToRgb32Converter converter, j_decompress_ptr info, struct my_error_mgr* err ) { if (!setjmp(err->setjmp_buffer)) { // -1 means default quality. - int quality = inQuality; if (quality < 0) quality = 75; @@ -529,7 +528,14 @@ static inline void write_icc_profile(const QImage &image, j_compress_ptr cinfo) } } -static bool write_jpeg_image(const QImage &image, QIODevice *device, volatile int sourceQuality, const QString &description, bool optimize, bool progressive) +static bool do_write_jpeg_image(struct jpeg_compress_struct &cinfo, + JSAMPROW *row_pointer, + const QImage &image, + QIODevice *device, + int sourceQuality, + const QString &description, + bool optimize, + bool progressive) { bool success = false; const QVector<QRgb> cmap = image.colorTable(); @@ -537,10 +543,6 @@ static bool write_jpeg_image(const QImage &image, QIODevice *device, volatile in if (image.format() == QImage::Format_Invalid || image.format() == QImage::Format_Alpha8) return false; - struct jpeg_compress_struct cinfo; - JSAMPROW row_pointer[1]; - row_pointer[0] = 0; - struct my_jpeg_destination_mgr *iod_dest = new my_jpeg_destination_mgr(device); struct my_error_mgr jerr; @@ -713,6 +715,27 @@ static bool write_jpeg_image(const QImage &image, QIODevice *device, volatile in } delete iod_dest; + return success; +} + +static bool write_jpeg_image(const QImage &image, + QIODevice *device, + int sourceQuality, + const QString &description, + bool optimize, + bool progressive) +{ + // protect these objects from the setjmp/longjmp pair inside + // do_write_jpeg_image (by making them non-local). + struct jpeg_compress_struct cinfo; + JSAMPROW row_pointer[1]; + row_pointer[0] = nullptr; + + const bool success = do_write_jpeg_image(cinfo, row_pointer, + image, device, + sourceQuality, description, + optimize, progressive); + delete [] row_pointer[0]; return success; } @@ -728,7 +751,7 @@ public: }; QJpegHandlerPrivate(QJpegHandler *qq) - : quality(75), transformation(QImageIOHandler::TransformationNone), iod_src(0), + : quality(75), transformation(QImageIOHandler::TransformationNone), iod_src(nullptr), rgb888ToRgb32ConverterPtr(qt_convert_rgb888_to_rgb32), state(Ready), optimize(false), progressive(false), q(qq) {} @@ -738,7 +761,7 @@ public: { jpeg_destroy_decompress(&info); delete iod_src; - iod_src = 0; + iod_src = nullptr; } } @@ -931,7 +954,7 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device) QByteArray exifData; - for (jpeg_saved_marker_ptr marker = info.marker_list; marker != NULL; marker = marker->next) { + for (jpeg_saved_marker_ptr marker = info.marker_list; marker != nullptr; marker = marker->next) { if (marker->marker == JPEG_COM) { QString key, value; QString s = QString::fromUtf8((const char *)marker->data, marker->data_length); @@ -1161,11 +1184,4 @@ void QJpegHandler::setOption(ImageOption option, const QVariant &value) } } -#if QT_DEPRECATED_SINCE(5, 13) -QByteArray QJpegHandler::name() const -{ - return "jpeg"; -} -#endif - QT_END_NAMESPACE diff --git a/src/plugins/imageformats/jpeg/qjpeghandler_p.h b/src/plugins/imageformats/jpeg/qjpeghandler_p.h index fafa930c11..43ca17317a 100644 --- a/src/plugins/imageformats/jpeg/qjpeghandler_p.h +++ b/src/plugins/imageformats/jpeg/qjpeghandler_p.h @@ -68,10 +68,6 @@ public: bool read(QImage *image) override; bool write(const QImage &image) override; -#if QT_DEPRECATED_SINCE(5, 13) - QByteArray name() const override; -#endif - static bool canRead(QIODevice *device); QVariant option(ImageOption option) const override; diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp index f2429f24ff..47ac54927b 100644 --- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp +++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp @@ -285,7 +285,7 @@ void QIBusPlatformInputContext::commitText(const QDBusVariant &text) if (!input) return; - const QDBusArgument arg = text.variant().value<QDBusArgument>(); + const QDBusArgument arg = qvariant_cast<QDBusArgument>(text.variant()); QIBusText t; if (debug) @@ -311,7 +311,7 @@ void QIBusPlatformInputContext::updatePreeditText(const QDBusVariant &text, uint if (!input) return; - const QDBusArgument arg = text.variant().value<QDBusArgument>(); + const QDBusArgument arg = qvariant_cast<QDBusArgument>(text.variant()); QIBusText t; arg >> t; diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h index 8e7b8df120..e9c9c55f6a 100644 --- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h +++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h @@ -61,7 +61,7 @@ public: explicit QIBusFilterEventWatcher(const QDBusPendingCall &call, QObject *parent = nullptr, QWindow *window = nullptr, - const Qt::KeyboardModifiers modifiers = nullptr, + const Qt::KeyboardModifiers modifiers = { }, const QVariantList arguments = QVariantList()) : QDBusPendingCallWatcher(call, parent) , m_window(window) diff --git a/src/plugins/platforminputcontexts/ibus/qibusproxy.cpp b/src/plugins/platforminputcontexts/ibus/qibusproxy.cpp index 156e9b7c90..6b46e106ab 100644 --- a/src/plugins/platforminputcontexts/ibus/qibusproxy.cpp +++ b/src/plugins/platforminputcontexts/ibus/qibusproxy.cpp @@ -83,10 +83,10 @@ QIBusEngineDesc QIBusProxy::getGlobalEngine() QVariant variant = reply.value().variant(); if (!variant.isValid()) return desc; - QVariant child = variant.value<QDBusVariant>().variant(); + QVariant child = qvariant_cast<QDBusVariant>(variant).variant(); if (!child.isValid()) return desc; - const QDBusArgument argument = child.value<QDBusArgument>(); + const QDBusArgument argument = qvariant_cast<QDBusArgument>(child); argument >> desc; return desc; } diff --git a/src/plugins/platforminputcontexts/ibus/qibustypes.cpp b/src/plugins/platforminputcontexts/ibus/qibustypes.cpp index a2551f1320..443df271a8 100644 --- a/src/plugins/platforminputcontexts/ibus/qibustypes.cpp +++ b/src/plugins/platforminputcontexts/ibus/qibustypes.cpp @@ -62,7 +62,7 @@ void QIBusSerializable::deserializeFrom(const QDBusArgument &argument) argument >> key; argument >> value; argument.endMapEntry(); - attachments[key] = value.variant().value<QDBusArgument>(); + attachments[key] = qvariant_cast<QDBusArgument>(value.variant()); } argument.endMap(); } @@ -201,7 +201,7 @@ void QIBusAttributeList::deserializeFrom(const QDBusArgument &arg) arg >> var; QIBusAttribute attr; - var.variant().value<QDBusArgument>() >> attr; + qvariant_cast<QDBusArgument>(var.variant()) >> attr; attributes.append(std::move(attr)); } arg.endArray(); @@ -268,7 +268,7 @@ void QIBusText::deserializeFrom(const QDBusArgument &argument) argument >> text; QDBusVariant variant; argument >> variant; - variant.variant().value<QDBusArgument>() >> attributes; + qvariant_cast<QDBusArgument>(variant.variant()) >> attributes; argument.endStructure(); } diff --git a/src/plugins/platforms/android/androidcontentfileengine.cpp b/src/plugins/platforms/android/androidcontentfileengine.cpp index 1444407195..3e3bdc2592 100644 --- a/src/plugins/platforms/android/androidcontentfileengine.cpp +++ b/src/plugins/platforms/android/androidcontentfileengine.cpp @@ -44,9 +44,10 @@ #include <QDebug> -AndroidContentFileEngine::AndroidContentFileEngine(const QString &fileName) - : QFSFileEngine(fileName) +AndroidContentFileEngine::AndroidContentFileEngine(const QString &f) + : m_file(f) { + setFileName(f); } bool AndroidContentFileEngine::open(QIODevice::OpenMode openMode) @@ -78,6 +79,48 @@ bool AndroidContentFileEngine::open(QIODevice::OpenMode openMode) return QFSFileEngine::open(openMode, fd, QFile::AutoCloseHandle); } +qint64 AndroidContentFileEngine::size() const +{ + const jlong size = QJNIObjectPrivate::callStaticMethod<jlong>( + "org/qtproject/qt5/android/QtNative", "getSize", + "(Landroid/content/Context;Ljava/lang/String;)J", QtAndroidPrivate::context(), + QJNIObjectPrivate::fromString(fileName(DefaultName)).object()); + return (qint64)size; +} + +AndroidContentFileEngine::FileFlags AndroidContentFileEngine::fileFlags(FileFlags type) const +{ + FileFlags commonFlags(ReadOwnerPerm|ReadUserPerm|ReadGroupPerm|ReadOtherPerm|ExistsFlag); + FileFlags flags; + const bool exists = QJNIObjectPrivate::callStaticMethod<jboolean>( + "org/qtproject/qt5/android/QtNative", "checkFileExists", + "(Landroid/content/Context;Ljava/lang/String;)Z", QtAndroidPrivate::context(), + QJNIObjectPrivate::fromString(fileName(DefaultName)).object()); + if (!exists) + return flags; + flags = FileType | commonFlags; + return type & flags; +} + +QString AndroidContentFileEngine::fileName(FileName f) const +{ + switch (f) { + case PathName: + case AbsolutePathName: + case CanonicalPathName: + case DefaultName: + case AbsoluteName: + case CanonicalName: + return m_file; + case BaseName: + { + const int pos = m_file.lastIndexOf(QChar(QLatin1Char('/'))); + return m_file.mid(pos); + } + default: + return QString(); + } +} AndroidContentFileEngineHandler::AndroidContentFileEngineHandler() = default; AndroidContentFileEngineHandler::~AndroidContentFileEngineHandler() = default; diff --git a/src/plugins/platforms/android/androidcontentfileengine.h b/src/plugins/platforms/android/androidcontentfileengine.h index db3def03d6..09e5d77553 100644 --- a/src/plugins/platforms/android/androidcontentfileengine.h +++ b/src/plugins/platforms/android/androidcontentfileengine.h @@ -47,6 +47,12 @@ class AndroidContentFileEngine : public QFSFileEngine public: AndroidContentFileEngine(const QString &fileName); bool open(QIODevice::OpenMode openMode) override; + qint64 size() const override; + FileFlags fileFlags(FileFlags type = FileInfoAll) const override; + QString fileName(FileName file = DefaultName) const override; +private: + QString m_file; + }; class AndroidContentFileEngineHandler : public QAbstractFileEngineHandler diff --git a/src/plugins/platforms/android/qandroidplatformfiledialoghelper.cpp b/src/plugins/platforms/android/qandroidplatformfiledialoghelper.cpp index fb979ab6cc..7b5f2f16f8 100644 --- a/src/plugins/platforms/android/qandroidplatformfiledialoghelper.cpp +++ b/src/plugins/platforms/android/qandroidplatformfiledialoghelper.cpp @@ -40,7 +40,6 @@ #include "qandroidplatformfiledialoghelper.h" #include <androidjnimain.h> -#include <private/qjni_p.h> #include <jni.h> QT_BEGIN_NAMESPACE @@ -50,9 +49,11 @@ namespace QtAndroidFileDialogHelper { #define RESULT_OK -1 #define REQUEST_CODE 1305 // Arbitrary +const char JniIntentClass[] = "android/content/Intent"; + QAndroidPlatformFileDialogHelper::QAndroidPlatformFileDialogHelper() - : QPlatformFileDialogHelper() - , m_selectedFile() + : QPlatformFileDialogHelper(), + m_activity(QtAndroid::activity()) { } @@ -61,92 +62,165 @@ bool QAndroidPlatformFileDialogHelper::handleActivityResult(jint requestCode, ji if (requestCode != REQUEST_CODE) return false; - if (resultCode == RESULT_OK) { - const QJNIObjectPrivate intent = QJNIObjectPrivate::fromLocalRef(data); - const QJNIObjectPrivate uri = intent.callObjectMethod("getData", "()Landroid/net/Uri;"); - const QString uriStr = uri.callObjectMethod("toString", "()Ljava/lang/String;").toString(); - m_selectedFile = QUrl(uriStr); - Q_EMIT fileSelected(m_selectedFile); - Q_EMIT accept(); - } else { + if (resultCode != RESULT_OK) { Q_EMIT reject(); + return true; } - return true; -} - -bool QAndroidPlatformFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) -{ - Q_UNUSED(windowFlags) - Q_UNUSED(windowModality) - Q_UNUSED(parent) - - if (options()->fileMode() != QFileDialogOptions::FileMode::ExistingFile) - return false; + const QJNIObjectPrivate intent = QJNIObjectPrivate::fromLocalRef(data); - QtAndroidPrivate::registerActivityResultListener(this); + const QJNIObjectPrivate uri = intent.callObjectMethod("getData", "()Landroid/net/Uri;"); + if (uri.isValid()) { + takePersistableUriPermission(uri); + m_selectedFile.append(QUrl(uri.toString())); + Q_EMIT fileSelected(m_selectedFile.first()); + Q_EMIT accept(); - const QJNIObjectPrivate ACTION_OPEN_DOCUMENT = QJNIObjectPrivate::getStaticObjectField("android/content/Intent", "ACTION_OPEN_DOCUMENT", "Ljava/lang/String;"); - QJNIObjectPrivate intent("android/content/Intent", "(Ljava/lang/String;)V", ACTION_OPEN_DOCUMENT.object()); - const QJNIObjectPrivate CATEGORY_OPENABLE = QJNIObjectPrivate::getStaticObjectField("android/content/Intent", "CATEGORY_OPENABLE", "Ljava/lang/String;"); - intent.callObjectMethod("addCategory", "(Ljava/lang/String;)Landroid/content/Intent;", CATEGORY_OPENABLE.object()); - intent.callObjectMethod("setType", "(Ljava/lang/String;)Landroid/content/Intent;", QJNIObjectPrivate::fromString(QStringLiteral("*/*")).object()); + return true; + } - const QJNIObjectPrivate activity(QtAndroid::activity()); - activity.callMethod<void>("startActivityForResult", "(Landroid/content/Intent;I)V", intent.object(), REQUEST_CODE); + const QJNIObjectPrivate uriClipData = + intent.callObjectMethod("getClipData", "()Landroid/content/ClipData;"); + if (uriClipData.isValid()) { + const int size = uriClipData.callMethod<jint>("getItemCount"); + for (int i = 0; i < size; ++i) { + QJNIObjectPrivate item = uriClipData.callObjectMethod( + "getItemAt", "(I)Landroid/content/ClipData$Item;", i); + + QJNIObjectPrivate itemUri = item.callObjectMethod("getUri", "()Landroid/net/Uri;"); + takePersistableUriPermission(itemUri); + m_selectedFile.append(itemUri.toString()); + Q_EMIT filesSelected(m_selectedFile); + Q_EMIT accept(); + } + } return true; } -void QAndroidPlatformFileDialogHelper::exec() +void QAndroidPlatformFileDialogHelper::takePersistableUriPermission(const QJNIObjectPrivate &uri) { - m_eventLoop.exec(QEventLoop::DialogExec); + int modeFlags = QJNIObjectPrivate::getStaticField<jint>( + JniIntentClass, "FLAG_GRANT_READ_URI_PERMISSION"); + + if (options()->acceptMode() == QFileDialogOptions::AcceptSave) { + modeFlags |= QJNIObjectPrivate::getStaticField<jint>( + JniIntentClass, "FLAG_GRANT_WRITE_URI_PERMISSION"); + } + + QJNIObjectPrivate contentResolver = m_activity.callObjectMethod( + "getContentResolver", "()Landroid/content/ContentResolver;"); + contentResolver.callMethod<void>("takePersistableUriPermission", "(Landroid/net/Uri;I)V", + uri.object(), modeFlags); } -void QAndroidPlatformFileDialogHelper::hide() +void QAndroidPlatformFileDialogHelper::setLocalFilesOnly(bool localOnly) { - if (m_eventLoop.isRunning()) - m_eventLoop.exit(); - QtAndroidPrivate::unregisterActivityResultListener(this); + const QJNIObjectPrivate extraLocalOnly = QJNIObjectPrivate::getStaticObjectField( + JniIntentClass, "EXTRA_LOCAL_ONLY", "Ljava/lang/String;"); + m_intent.callObjectMethod("putExtra", "(Ljava/lang/String;Z)Landroid/content/Intent;", + extraLocalOnly.object(), localOnly); } -QString QAndroidPlatformFileDialogHelper::selectedNameFilter() const +void QAndroidPlatformFileDialogHelper::setIntentTitle(const QString &title) { - return QString(); + const QJNIObjectPrivate extraTitle = QJNIObjectPrivate::getStaticObjectField( + JniIntentClass, "EXTRA_TITLE", "Ljava/lang/String;"); + m_intent.callObjectMethod("putExtra", + "(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;", + extraTitle.object(), QJNIObjectPrivate::fromString(title).object()); } -void QAndroidPlatformFileDialogHelper::selectNameFilter(const QString &filter) +void QAndroidPlatformFileDialogHelper::setOpenableCategory() { - Q_UNUSED(filter) + const QJNIObjectPrivate CATEGORY_OPENABLE = QJNIObjectPrivate::getStaticObjectField( + JniIntentClass, "CATEGORY_OPENABLE", "Ljava/lang/String;"); + m_intent.callObjectMethod("addCategory", "(Ljava/lang/String;)Landroid/content/Intent;", + CATEGORY_OPENABLE.object()); } -void QAndroidPlatformFileDialogHelper::setFilter() +void QAndroidPlatformFileDialogHelper::setAllowMultipleSelections(bool allowMultiple) { + const QJNIObjectPrivate allowMultipleSelections = QJNIObjectPrivate::getStaticObjectField( + JniIntentClass, "EXTRA_ALLOW_MULTIPLE", "Ljava/lang/String;"); + m_intent.callObjectMethod("putExtra", "(Ljava/lang/String;Z)Landroid/content/Intent;", + allowMultipleSelections.object(), allowMultiple); } -QList<QUrl> QAndroidPlatformFileDialogHelper::selectedFiles() const +void QAndroidPlatformFileDialogHelper::setMimeTypes() { - return {m_selectedFile}; + m_intent.callObjectMethod("setType", "(Ljava/lang/String;)Landroid/content/Intent;", + QJNIObjectPrivate::fromString("*/*").object()); + + const QJNIObjectPrivate extraMimeType = QJNIObjectPrivate::getStaticObjectField( + JniIntentClass, "EXTRA_MIME_TYPES", "Ljava/lang/String;"); + for (const QString &type : options()->mimeTypeFilters()) { + m_intent.callObjectMethod( + "putExtra", "(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;", + extraMimeType.object(), QJNIObjectPrivate::fromString(type).object()); + } } -void QAndroidPlatformFileDialogHelper::selectFile(const QUrl &file) +QJNIObjectPrivate QAndroidPlatformFileDialogHelper::getFileDialogIntent(const QString &intentType) { - Q_UNUSED(file) + const QJNIObjectPrivate ACTION_OPEN_DOCUMENT = QJNIObjectPrivate::getStaticObjectField( + JniIntentClass, intentType.toLatin1(), "Ljava/lang/String;"); + return QJNIObjectPrivate(JniIntentClass, "(Ljava/lang/String;)V", + ACTION_OPEN_DOCUMENT.object()); } -QUrl QAndroidPlatformFileDialogHelper::directory() const +bool QAndroidPlatformFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) { - return QUrl(); + Q_UNUSED(windowFlags) + Q_UNUSED(windowModality) + Q_UNUSED(parent) + + bool isDirDialog = false; + + if (options()->acceptMode() == QFileDialogOptions::AcceptSave) { + m_intent = getFileDialogIntent("ACTION_CREATE_DOCUMENT"); + } else if (options()->acceptMode() == QFileDialogOptions::AcceptOpen) { + switch (options()->fileMode()) { + case QFileDialogOptions::FileMode::DirectoryOnly: + case QFileDialogOptions::FileMode::Directory: + m_intent = getFileDialogIntent("ACTION_OPEN_DOCUMENT_TREE"); + isDirDialog = true; + break; + case QFileDialogOptions::FileMode::ExistingFiles: + m_intent = getFileDialogIntent("ACTION_OPEN_DOCUMENT"); + setAllowMultipleSelections(true); + break; + case QFileDialogOptions::FileMode::AnyFile: + case QFileDialogOptions::FileMode::ExistingFile: + m_intent = getFileDialogIntent("ACTION_OPEN_DOCUMENT"); + break; + } + } + + if (!isDirDialog) { + setOpenableCategory(); + setMimeTypes(); + } + + setIntentTitle(options()->windowTitle()); + setLocalFilesOnly(true); + + QtAndroidPrivate::registerActivityResultListener(this); + m_activity.callMethod<void>("startActivityForResult", "(Landroid/content/Intent;I)V", + m_intent.object(), REQUEST_CODE); + return true; } -void QAndroidPlatformFileDialogHelper::setDirectory(const QUrl &directory) +void QAndroidPlatformFileDialogHelper::hide() { - Q_UNUSED(directory) + if (m_eventLoop.isRunning()) + m_eventLoop.exit(); + QtAndroidPrivate::unregisterActivityResultListener(this); } -bool QAndroidPlatformFileDialogHelper::defaultNameFilterDisables() const +void QAndroidPlatformFileDialogHelper::exec() { - return false; + m_eventLoop.exec(QEventLoop::DialogExec); } } diff --git a/src/plugins/platforms/android/qandroidplatformfiledialoghelper.h b/src/plugins/platforms/android/qandroidplatformfiledialoghelper.h index 5cd26af7c9..fa9c3f47b3 100644 --- a/src/plugins/platforms/android/qandroidplatformfiledialoghelper.h +++ b/src/plugins/platforms/android/qandroidplatformfiledialoghelper.h @@ -44,6 +44,8 @@ #include <QEventLoop> #include <qpa/qplatformdialoghelper.h> #include <QtCore/private/qjnihelpers_p.h> +#include <private/qjni_p.h> +#include <QEventLoop> QT_BEGIN_NAMESPACE @@ -55,26 +57,34 @@ class QAndroidPlatformFileDialogHelper: public QPlatformFileDialogHelper, public public: QAndroidPlatformFileDialogHelper(); - void exec() override; - bool show(Qt::WindowFlags windowFlags, - Qt::WindowModality windowModality, - QWindow *parent) override; + void exec() override; + bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) override; void hide() override; - QString selectedNameFilter() const override; - void selectNameFilter(const QString &filter) override; - void setFilter() override; - QList<QUrl> selectedFiles() const override; - void selectFile(const QUrl &file) override; - QUrl directory() const override; - void setDirectory(const QUrl &directory) override; - bool defaultNameFilterDisables() const override; + QString selectedNameFilter() const override { return QString(); }; + void selectNameFilter(const QString &filter) override { Q_UNUSED(filter) }; + void setFilter() override {}; + QList<QUrl> selectedFiles() const override { return m_selectedFile; }; + void selectFile(const QUrl &file) override { Q_UNUSED(file) }; + QUrl directory() const override { return QUrl(); }; + void setDirectory(const QUrl &directory) override { Q_UNUSED(directory) }; + bool defaultNameFilterDisables() const override { return false; }; bool handleActivityResult(jint requestCode, jint resultCode, jobject data) override; private: + QJNIObjectPrivate getFileDialogIntent(const QString &intentType); + void takePersistableUriPermission(const QJNIObjectPrivate &uri); + void setLocalFilesOnly(bool localOnly); + void setIntentTitle(const QString &title); + void setOpenableCategory(); + void setAllowMultipleSelections(bool allowMultiple); + void setMimeTypes(); + QEventLoop m_eventLoop; - QUrl m_selectedFile; + QList<QUrl> m_selectedFile; + QJNIObjectPrivate m_intent; + const QJNIObjectPrivate m_activity; }; } diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp index e0c437be27..c81cc66166 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp @@ -74,6 +74,8 @@ #include "qandroidplatformvulkaninstance.h" #endif +#include <QtGui/qpa/qplatforminputcontextfactory_p.h> + QT_BEGIN_NAMESPACE int QAndroidPlatformIntegration::m_defaultGeometryWidth = 320; @@ -255,6 +257,15 @@ static bool needsBasicRenderloopWorkaround() return needsWorkaround; } +void QAndroidPlatformIntegration::initialize() +{ + const QString icStr = QPlatformInputContextFactory::requested(); + if (icStr.isNull()) + m_inputContext.reset(new QAndroidInputContext); + else + m_inputContext.reset(QPlatformInputContextFactory::create(icStr)); +} + bool QAndroidPlatformIntegration::hasCapability(Capability cap) const { switch (cap) { @@ -366,7 +377,7 @@ QPlatformClipboard *QAndroidPlatformIntegration::clipboard() const QPlatformInputContext *QAndroidPlatformIntegration::inputContext() const { - return &m_platformInputContext; + return m_inputContext.data(); } QPlatformNativeInterface *QAndroidPlatformIntegration::nativeInterface() const diff --git a/src/plugins/platforms/android/qandroidplatformintegration.h b/src/plugins/platforms/android/qandroidplatformintegration.h index c795c499bc..ecbde4f951 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.h +++ b/src/plugins/platforms/android/qandroidplatformintegration.h @@ -81,6 +81,8 @@ public: QAndroidPlatformIntegration(const QStringList ¶mList); ~QAndroidPlatformIntegration(); + void initialize() override; + bool hasCapability(QPlatformIntegration::Capability cap) const override; QPlatformWindow *createPlatformWindow(QWindow *window) const override; @@ -167,7 +169,7 @@ private: mutable QPlatformAccessibility *m_accessibility; #endif - mutable QAndroidInputContext m_platformInputContext; + QScopedPointer<QPlatformInputContext> m_inputContext; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformservices.cpp b/src/plugins/platforms/android/qandroidplatformservices.cpp index 136637800b..c095613ce7 100644 --- a/src/plugins/platforms/android/qandroidplatformservices.cpp +++ b/src/plugins/platforms/android/qandroidplatformservices.cpp @@ -43,6 +43,7 @@ #include <QDebug> #include <QMimeDatabase> #include <QtCore/private/qjni_p.h> +#include <private/qjnihelpers_p.h> QT_BEGIN_NAMESPACE @@ -57,20 +58,20 @@ bool QAndroidPlatformServices::openUrl(const QUrl &theUrl) // if the file is local, we need to pass the MIME type, otherwise Android // does not start an Intent to view this file - if ((url.scheme().isEmpty() && QFile::exists(url.path())) || url.isLocalFile()) { + QLatin1String fileScheme("file"); + if ((url.scheme().isEmpty() || url.scheme() == fileScheme) && QFile::exists(url.path())) { // a real URL including the scheme is needed, else the Intent can not be started - url.setScheme(QLatin1String("file")); - + url.setScheme(fileScheme); QMimeDatabase mimeDb; mime = mimeDb.mimeTypeForUrl(url).name(); } QJNIObjectPrivate urlString = QJNIObjectPrivate::fromString(url.toString()); QJNIObjectPrivate mimeString = QJNIObjectPrivate::fromString(mime); - return QJNIObjectPrivate::callStaticMethod<jboolean>(QtAndroid::applicationClass(), - "openURL", - "(Ljava/lang/String;Ljava/lang/String;)Z", - urlString.object(), mimeString.object()); + return QJNIObjectPrivate::callStaticMethod<jboolean>( + QtAndroid::applicationClass(), "openURL", + "(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)Z", + QtAndroidPrivate::context(), urlString.object(), mimeString.object()); } bool QAndroidPlatformServices::openDocument(const QUrl &url) diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index 6645b6c90a..6b93b1acf0 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -31,8 +31,7 @@ SOURCES += main.mm \ qcocoaintrospection.mm \ qcocoakeymapper.mm \ qcocoamimetypes.mm \ - qiosurfacegraphicsbuffer.mm \ - messages.cpp + qiosurfacegraphicsbuffer.mm HEADERS += qcocoaintegration.h \ qcocoascreen.h \ @@ -63,7 +62,6 @@ HEADERS += qcocoaintegration.h \ qcocoasystemtrayicon.h \ qcocoaintrospection.h \ qcocoakeymapper.h \ - messages.h \ qiosurfacegraphicsbuffer.h \ qcocoamimetypes.h @@ -85,10 +83,17 @@ qtConfig(accessibility) { qcocoaaccessibility.h } +qtConfig(sessionmanager) { + SOURCES += qcocoasessionmanager.cpp + HEADERS += qcocoasessionmanager.h +} + RESOURCES += qcocoaresources.qrc LIBS += -framework AppKit -framework CoreServices -framework Carbon -framework IOKit -framework QuartzCore -framework CoreVideo -framework Metal -framework IOSurface -lcups +DEFINES += QT_NO_FOREACH + QT += \ core-private gui-private \ clipboard_support-private theme_support-private \ diff --git a/src/plugins/platforms/cocoa/messages.cpp b/src/plugins/platforms/cocoa/messages.cpp deleted file mode 100644 index 06e3dd454e..0000000000 --- a/src/plugins/platforms/cocoa/messages.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins 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 "messages.h" - -#include <QtCore/qcoreapplication.h> -#include <QtCore/qregularexpression.h> - -// Translatable messages should go into this .cpp file for them to be picked up by lupdate. - -QT_BEGIN_NAMESPACE - -QString msgAboutQt() -{ - return QCoreApplication::translate("QCocoaMenuItem", "About Qt"); -} - -static const char *application_menu_strings[] = -{ - QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","About %1"), - QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Preferences..."), - QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Services"), - QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Hide %1"), - QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Hide Others"), - QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Show All"), - QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Quit %1") -}; - -QString qt_mac_applicationmenu_string(int type) -{ - QString menuString = QString::fromLatin1(application_menu_strings[type]); - const QString translated = QCoreApplication::translate("QMenuBar", application_menu_strings[type]); - if (translated != menuString) { - return translated; - } else { - return QCoreApplication::translate("MAC_APPLICATION_MENU", application_menu_strings[type]); - } -} - -QPlatformMenuItem::MenuRole detectMenuRole(const QString &caption) -{ - QString captionNoAmpersand(caption); - captionNoAmpersand.remove(QLatin1Char('&')); - const QString aboutString = QCoreApplication::translate("QCocoaMenuItem", "About"); - if (captionNoAmpersand.startsWith(aboutString, Qt::CaseInsensitive) - || captionNoAmpersand.endsWith(aboutString, Qt::CaseInsensitive)) { - static const QRegularExpression qtRegExp(QLatin1String("qt$"), QRegularExpression::CaseInsensitiveOption); - if (captionNoAmpersand.contains(qtRegExp)) - return QPlatformMenuItem::AboutQtRole; - return QPlatformMenuItem::AboutRole; - } - if (captionNoAmpersand.startsWith(QCoreApplication::translate("QCocoaMenuItem", "Config"), Qt::CaseInsensitive) - || captionNoAmpersand.startsWith(QCoreApplication::translate("QCocoaMenuItem", "Preference"), Qt::CaseInsensitive) - || captionNoAmpersand.startsWith(QCoreApplication::translate("QCocoaMenuItem", "Options"), Qt::CaseInsensitive) - || captionNoAmpersand.startsWith(QCoreApplication::translate("QCocoaMenuItem", "Setting"), Qt::CaseInsensitive) - || captionNoAmpersand.startsWith(QCoreApplication::translate("QCocoaMenuItem", "Setup"), Qt::CaseInsensitive)) { - return QPlatformMenuItem::PreferencesRole; - } - if (captionNoAmpersand.startsWith(QCoreApplication::translate("QCocoaMenuItem", "Quit"), Qt::CaseInsensitive) - || captionNoAmpersand.startsWith(QCoreApplication::translate("QCocoaMenuItem", "Exit"), Qt::CaseInsensitive)) { - return QPlatformMenuItem::QuitRole; - } - if (!captionNoAmpersand.compare(QCoreApplication::translate("QCocoaMenuItem", "Cut"), Qt::CaseInsensitive)) - return QPlatformMenuItem::CutRole; - if (!captionNoAmpersand.compare(QCoreApplication::translate("QCocoaMenuItem", "Copy"), Qt::CaseInsensitive)) - return QPlatformMenuItem::CopyRole; - if (!captionNoAmpersand.compare(QCoreApplication::translate("QCocoaMenuItem", "Paste"), Qt::CaseInsensitive)) - return QPlatformMenuItem::PasteRole; - if (!captionNoAmpersand.compare(QCoreApplication::translate("QCocoaMenuItem", "Select All"), Qt::CaseInsensitive)) - return QPlatformMenuItem::SelectAllRole; - return QPlatformMenuItem::NoRole; -} - -QString msgDialogButtonDiscard() -{ - return QCoreApplication::translate("QCocoaTheme", "Don't Save"); -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h index 141ce6bf1a..f74afb8440 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h @@ -41,7 +41,7 @@ #include <QtCore/qglobal.h> -#include "qt_mac_p.h" +#include <QtCore/private/qcore_mac_p.h> #ifndef QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index 3560c9d9b5..ad40c6b0cb 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -41,7 +41,8 @@ #include "qcocoahelpers.h" #include "qcocoawindow.h" #include "qcocoascreen.h" -#include "private/qaccessiblecache_p.h" + +#include <QtGui/private/qaccessiblecache_p.h> #include <QtAccessibilitySupport/private/qaccessiblebridgeutils_p.h> #include <QtGui/qaccessible.h> @@ -547,7 +548,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of return nsActions; const QStringList &supportedActionNames = QAccessibleBridgeUtils::effectiveActionNames(iface); - foreach (const QString &qtAction, supportedActionNames) { + for (const QString &qtAction : supportedActionNames) { NSString *nsAction = QCocoaAccessible::getTranslatedAction(qtAction); if (nsAction) [nsActions addObject : nsAction]; diff --git a/src/plugins/platforms/cocoa/qcocoaapplication.h b/src/plugins/platforms/cocoa/qcocoaapplication.h index 15530d8281..4314a01ca1 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplication.h +++ b/src/plugins/platforms/cocoa/qcocoaapplication.h @@ -83,8 +83,8 @@ // We mean it. // -#include "qglobal.h" -#include "private/qcore_mac_p.h" +#include <qglobal.h> +#include <QtCore/private/qcore_mac_p.h> #import <AppKit/AppKit.h> diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm index 9b0a6b1b86..e8d789275c 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm @@ -79,12 +79,14 @@ #include "qcocoamenuitem.h" #include "qcocoansmenu.h" +#if QT_CONFIG(sessionmanager) +# include "qcocoasessionmanager.h" +#endif + #include <qevent.h> #include <qurl.h> #include <qdebug.h> #include <qguiapplication.h> -#include <private/qguiapplication_p.h> -#include "qt_mac_p.h" #include <qpa/qwindowsysteminterface.h> #include <qwindowdefs.h> @@ -149,7 +151,7 @@ QT_USE_NAMESPACE if ([reflectionDelegate respondsToSelector:_cmd]) return [reflectionDelegate applicationShouldTerminate:sender]; - if (QGuiApplicationPrivate::instance()->threadData->eventLoops.isEmpty()) { + if (QGuiApplicationPrivate::instance()->threadData.loadRelaxed()->eventLoops.isEmpty()) { // No event loop is executing. This probably means that Qt is used as a plugin, // or as a part of a native Cocoa application. In any case it should be fine to // terminate now. @@ -157,6 +159,17 @@ QT_USE_NAMESPACE return NSTerminateNow; } +#if QT_CONFIG(sessionmanager) + QCocoaSessionManager *cocoaSessionManager = QCocoaSessionManager::instance(); + cocoaSessionManager->resetCancellation(); + cocoaSessionManager->appCommitData(); + + if (cocoaSessionManager->wasCanceled()) { + qCDebug(lcQpaApplication) << "Session management canceled application termination"; + return NSTerminateCancel; + } +#endif + if (!QWindowSystemInterface::handleApplicationTermination<QWindowSystemInterface::SynchronousDelivery>()) { qCDebug(lcQpaApplication) << "Application termination canceled"; return NSTerminateCancel; @@ -359,7 +372,7 @@ QT_USE_NAMESPACE if (!platformItem || platformItem->menu()) return; - QScopedScopeLevelCounter scopeLevelCounter(QGuiApplicationPrivate::instance()->threadData); + QScopedScopeLevelCounter scopeLevelCounter(QGuiApplicationPrivate::instance()->threadData.loadRelaxed()); QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers:[NSEvent modifierFlags]]; static QMetaMethod activatedSignal = QMetaMethod::fromSignal(&QCocoaMenuItem::activated); diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index 2b4c71f279..3b9df8da3a 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -43,6 +43,7 @@ #include "qcocoahelpers.h" #include <QtCore/qmath.h> +#include <QtGui/qpainter.h> #include <QuartzCore/CATransaction.h> diff --git a/src/plugins/platforms/cocoa/qcocoaclipboard.mm b/src/plugins/platforms/cocoa/qcocoaclipboard.mm index a35c153084..141940cc50 100644 --- a/src/plugins/platforms/cocoa/qcocoaclipboard.mm +++ b/src/plugins/platforms/cocoa/qcocoaclipboard.mm @@ -67,7 +67,7 @@ void QCocoaClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) } pasteBoard->sync(); - pasteBoard->setMimeData(data); + pasteBoard->setMimeData(data, QMacPasteboard::LazyRequest); emitChanged(mode); } } diff --git a/src/plugins/platforms/cocoa/qcocoacursor.h b/src/plugins/platforms/cocoa/qcocoacursor.h index 5b008eff35..6589891ef2 100644 --- a/src/plugins/platforms/cocoa/qcocoacursor.h +++ b/src/plugins/platforms/cocoa/qcocoacursor.h @@ -63,8 +63,8 @@ private: QHash<Qt::CursorShape, NSCursor *> m_cursors; NSCursor *convertCursor(QCursor *cursor); NSCursor *createCursorData(QCursor * cursor); - NSCursor *createCursorFromBitmap(const QBitmap *bitmap, const QBitmap *mask, const QPoint hotspot = QPoint()); - NSCursor *createCursorFromPixmap(const QPixmap pixmap, const QPoint hotspot = QPoint()); + NSCursor *createCursorFromBitmap(const QBitmap &bitmap, const QBitmap &mask, const QPoint hotspot = QPoint()); + NSCursor *createCursorFromPixmap(const QPixmap &pixmap, const QPoint hotspot = QPoint()); }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm index e0d623fc4c..8ca72ec619 100644 --- a/src/plugins/platforms/cocoa/qcocoacursor.mm +++ b/src/plugins/platforms/cocoa/qcocoacursor.mm @@ -243,7 +243,7 @@ NSCursor *QCocoaCursor::createCursorData(QCursor *cursor) switch (cursor->shape()) { case Qt::BitmapCursor: { if (cursor->pixmap().isNull()) - return createCursorFromBitmap(cursor->bitmap(), cursor->mask(), hotspot); + return createCursorFromBitmap(cursor->bitmap(Qt::ReturnByValue), cursor->mask(Qt::ReturnByValue), hotspot); else return createCursorFromPixmap(cursor->pixmap(), hotspot); break; } @@ -301,17 +301,17 @@ NSCursor *QCocoaCursor::createCursorData(QCursor *cursor) if (cursorData) { QBitmap bitmap(QBitmap::fromData(QSize(16, 16), cursorData, QImage::Format_Mono)); QBitmap mask(QBitmap::fromData(QSize(16, 16), cursorMaskData, QImage::Format_Mono)); - return (createCursorFromBitmap(&bitmap, &mask, hotspot)); + return (createCursorFromBitmap(bitmap, mask, hotspot)); } return nil; // should not happen, all cases covered above } -NSCursor *QCocoaCursor::createCursorFromBitmap(const QBitmap *bitmap, const QBitmap *mask, const QPoint hotspot) +NSCursor *QCocoaCursor::createCursorFromBitmap(const QBitmap &bitmap, const QBitmap &mask, const QPoint hotspot) { - QImage finalCursor(bitmap->size(), QImage::Format_ARGB32); - QImage bmi = bitmap->toImage().convertToFormat(QImage::Format_RGB32); - QImage bmmi = mask->toImage().convertToFormat(QImage::Format_RGB32); + QImage finalCursor(bitmap.size(), QImage::Format_ARGB32); + QImage bmi = bitmap.toImage().convertToFormat(QImage::Format_RGB32); + QImage bmmi = mask.toImage().convertToFormat(QImage::Format_RGB32); for (int row = 0; row < finalCursor.height(); ++row) { QRgb *bmData = reinterpret_cast<QRgb *>(bmi.scanLine(row)); QRgb *bmmData = reinterpret_cast<QRgb *>(bmmi.scanLine(row)); @@ -332,27 +332,11 @@ NSCursor *QCocoaCursor::createCursorFromBitmap(const QBitmap *bitmap, const QBit return createCursorFromPixmap(QPixmap::fromImage(finalCursor), hotspot); } -NSCursor *QCocoaCursor::createCursorFromPixmap(const QPixmap pixmap, const QPoint hotspot) +NSCursor *QCocoaCursor::createCursorFromPixmap(const QPixmap &pixmap, const QPoint hotspot) { NSPoint hotSpot = NSMakePoint(hotspot.x(), hotspot.y()); - NSImage *nsimage; - if (pixmap.devicePixelRatio() > 1.0) { - QSize layoutSize = pixmap.size() / pixmap.devicePixelRatio(); - QPixmap scaledPixmap = pixmap.scaled(layoutSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - scaledPixmap.setDevicePixelRatio(1.0); - nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(scaledPixmap)); - CGImageRef cgImage = qt_mac_toCGImage(pixmap.toImage()); - NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage]; - [nsimage addRepresentation:imageRep]; - [imageRep release]; - CGImageRelease(cgImage); - } else { - nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(pixmap)); - } - - NSCursor *nsCursor = [[NSCursor alloc] initWithImage:nsimage hotSpot: hotSpot]; - [nsimage release]; - return nsCursor; + auto *image = [NSImage imageFromQImage:pixmap.toImage()]; + return [[NSCursor alloc] initWithImage:image hotSpot:hotSpot]; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm index 95808b8a11..b4a16ab912 100644 --- a/src/plugins/platforms/cocoa/qcocoadrag.mm +++ b/src/plugins/platforms/cocoa/qcocoadrag.mm @@ -130,9 +130,8 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o) QPoint hotSpot = m_drag->hotSpot(); QPixmap pm = dragPixmap(m_drag, hotSpot); - QSize pmDeviceIndependentSize = pm.size() / pm.devicePixelRatio(); - NSImage *nsimage = qt_mac_create_nsimage(pm); - [nsimage setSize:NSSizeFromCGSize(pmDeviceIndependentSize.toCGSize())]; + NSImage *dragImage = [NSImage imageFromQImage:pm.toImage()]; + Q_ASSERT(dragImage); QMacPasteboard dragBoard(CFStringRef(NSPasteboardNameDrag), QMacInternalPasteboardMime::MIME_DND); m_drag->mimeData()->setData(QLatin1String("application/x-qt-mime-type-name"), QByteArray("dummy")); @@ -142,12 +141,12 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o) NSWindow *theWindow = [m_lastEvent window]; Q_ASSERT(theWindow); event_location.x -= hotSpot.x(); - CGFloat flippedY = pmDeviceIndependentSize.height() - hotSpot.y(); + CGFloat flippedY = dragImage.size.height - hotSpot.y(); event_location.y -= flippedY; NSSize mouseOffset_unused = NSMakeSize(0.0, 0.0); NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSPasteboardNameDrag]; - [theWindow dragImage:nsimage + [theWindow dragImage:dragImage at:event_location offset:mouseOffset_unused event:m_lastEvent @@ -155,8 +154,6 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o) source:m_lastView slideBack:YES]; - [nsimage release]; - m_drag = nullptr; return m_executed_drop_action; } diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h index 69587a24be..b8d2532b8e 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h @@ -186,6 +186,7 @@ public: QAtomicInt serialNumber; int lastSerial; bool interrupt; + bool propagateInterrupt = false; static void postedEventsSourceCallback(void *info); static void waitingObserverCallback(CFRunLoopObserverRef observer, diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index e87fc39c42..338a5516d9 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -73,24 +73,26 @@ #include "qcocoaeventdispatcher.h" #include "qcocoawindow.h" - #include "qcocoahelpers.h" -#include "qguiapplication.h" -#include "qevent.h" -#include "qmutex.h" -#include "qsocketnotifier.h" + +#include <QtGui/qevent.h> +#include <QtGui/qguiapplication.h> +#include <QtGui/private/qguiapplication_p.h> + +#include <QtCore/qmutex.h> +#include <QtCore/qscopeguard.h> +#include <QtCore/qsocketnotifier.h> +#include <QtCore/private/qthread_p.h> + #include <qpa/qplatformwindow.h> #include <qpa/qplatformnativeinterface.h> -#include "private/qthread_p.h" -#include "private/qguiapplication_p.h" -#include <qdebug.h> + +#include <QtCore/qdebug.h> #include <AppKit/AppKit.h> QT_BEGIN_NAMESPACE -QT_USE_NAMESPACE - static inline CFRunLoopRef mainRunLoop() { return CFRunLoopGetMain(); @@ -293,46 +295,42 @@ bool QCocoaEventDispatcher::hasPendingEvents() return qGlobalPostedEventsCount() || (qt_is_gui_used && !CFRunLoopIsWaiting(CFRunLoopGetMain())); } -static bool IsMouseOrKeyEvent( NSEvent* event ) +static bool isUserInputEvent(NSEvent* event) { - bool result = false; - - switch( [event type] ) - { - case NSEventTypeLeftMouseDown: - case NSEventTypeLeftMouseUp: - case NSEventTypeRightMouseDown: - case NSEventTypeRightMouseUp: - case NSEventTypeMouseMoved: // ?? - case NSEventTypeLeftMouseDragged: - case NSEventTypeRightMouseDragged: - case NSEventTypeMouseEntered: - case NSEventTypeMouseExited: - case NSEventTypeKeyDown: - case NSEventTypeKeyUp: - case NSEventTypeFlagsChanged: // key modifiers changed? - case NSEventTypeCursorUpdate: // ?? - case NSEventTypeScrollWheel: - case NSEventTypeTabletPoint: - case NSEventTypeTabletProximity: - case NSEventTypeOtherMouseDown: - case NSEventTypeOtherMouseUp: - case NSEventTypeOtherMouseDragged: + switch ([event type]) { + case NSEventTypeLeftMouseDown: + case NSEventTypeLeftMouseUp: + case NSEventTypeRightMouseDown: + case NSEventTypeRightMouseUp: + case NSEventTypeMouseMoved: // ?? + case NSEventTypeLeftMouseDragged: + case NSEventTypeRightMouseDragged: + case NSEventTypeMouseEntered: + case NSEventTypeMouseExited: + case NSEventTypeKeyDown: + case NSEventTypeKeyUp: + case NSEventTypeFlagsChanged: // key modifiers changed? + case NSEventTypeCursorUpdate: // ?? + case NSEventTypeScrollWheel: + case NSEventTypeTabletPoint: + case NSEventTypeTabletProximity: + case NSEventTypeOtherMouseDown: + case NSEventTypeOtherMouseUp: + case NSEventTypeOtherMouseDragged: #ifndef QT_NO_GESTURES - case NSEventTypeGesture: // touch events - case NSEventTypeMagnify: - case NSEventTypeSwipe: - case NSEventTypeRotate: - case NSEventTypeBeginGesture: - case NSEventTypeEndGesture: + case NSEventTypeGesture: // touch events + case NSEventTypeMagnify: + case NSEventTypeSwipe: + case NSEventTypeRotate: + case NSEventTypeBeginGesture: + case NSEventTypeEndGesture: #endif // QT_NO_GESTURES - result = true; + return true; break; - - default: + default: break; } - return result; + return false; } static inline void qt_mac_waitForMoreEvents(NSString *runLoopMode = NSDefaultRunLoopMode) @@ -352,6 +350,16 @@ static inline void qt_mac_waitForMoreEvents(NSString *runLoopMode = NSDefaultRun bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) { Q_D(QCocoaEventDispatcher); + + // In rare rather corner cases a user's application messes with + // QEventLoop::exec()/exit() and QCoreApplication::processEvents(), + // we have to undo what bool blocker normally does. + d->propagateInterrupt = false; + const auto boolBlockerUndo = qScopeGuard([d](){ + if (d->propagateInterrupt) + d->interrupt = true; + d->propagateInterrupt = false; + }); QBoolBlocker interruptBlocker(d->interrupt, false); bool interruptLater = false; @@ -465,7 +473,7 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) dequeue: YES]; if (event) { - if (IsMouseOrKeyEvent(event)) { + if (isUserInputEvent(event)) { [event retain]; d->queuedUserInputEvents.append(event); continue; @@ -485,7 +493,7 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) if (event) { if (flags & QEventLoop::ExcludeUserInputEvents) { - if (IsMouseOrKeyEvent(event)) { + if (isUserInputEvent(event)) { [event retain]; d->queuedUserInputEvents.append(event); continue; @@ -500,7 +508,16 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) if ((d->processEventsFlags & QEventLoop::EventLoopExec) == 0) { // When called "manually", always process posted events and timers + bool oldInterrupt = d->interrupt; d->processPostedEvents(); + if (!oldInterrupt && d->interrupt && !d->currentModalSession()) { + // We had direct processEvent call, coming not from QEventLoop::exec(). + // One of the posted events triggered an application to interrupt the loop. + // But bool blocker will reset d->interrupt to false, so the real event + // loop will never notice it was interrupted. Now we'll have to fix it by + // enforcing the value of d->interrupt. + d->propagateInterrupt = true; + } retVal = d->processTimers() || retVal; } @@ -515,7 +532,7 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) if (hadModalSession && !d->currentModalSessionCached) interruptLater = true; } - bool canWait = (d->threadData->canWait + bool canWait = (d->threadData.loadRelaxed()->canWait && !retVal && !d->interrupt && (d->processEventsFlags & QEventLoop::WaitForMoreEvents)); @@ -882,7 +899,7 @@ void QCocoaEventDispatcherPrivate::processPostedEvents() } int serial = serialNumber.loadRelaxed(); - if (!threadData->canWait || (serial != lastSerial)) { + if (!threadData.loadRelaxed()->canWait || (serial != lastSerial)) { lastSerial = serial; QCoreApplication::sendPostedEvents(); QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::AllEvents); diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index 6aa21d78d1..15e83db48f 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -48,7 +48,6 @@ #include <qguiapplication.h> #include <private/qguiapplication_p.h> -#include "qt_mac_p.h" #include "qcocoahelpers.h" #include "qcocoaeventdispatcher.h" #include <qbuffer.h> @@ -419,8 +418,7 @@ static QString strippedText(QString s) [mPopUpButton setHidden:chooseDirsOnly]; // TODO hide the whole sunken pane instead? if (mOptions->acceptMode() == QFileDialogOptions::AcceptSave) { - const QStringList ext = [self acceptableExtensionsForSave]; - [mSavePanel setAllowedFileTypes:ext.isEmpty() ? nil : qt_mac_QStringListToNSMutableArray(ext)]; + [self recomputeAcceptableExtensionsForSave]; } else { [mOpenPanel setAllowedFileTypes:nil]; // delegate panel:shouldEnableURL: does the file filtering for NSOpenPanel } @@ -457,25 +455,49 @@ static QString strippedText(QString s) } /* - Returns a list of extensions (e.g. "png", "jpg", "gif") - for the current name filter. If a filter do not conform - to the format *.xyz or * or *.*, an empty list - is returned meaning accept everything. + Computes a list of extensions (e.g. "png", "jpg", "gif") + for the current name filter, and updates the save panel. + + If a filter do not conform to the format *.xyz or * or *.*, + all files types are allowed. + + Extensions with more than one part (e.g. "tar.gz") are + reduced to their final part, as NSSavePanel does not deal + well with multi-part extensions. */ -- (QStringList)acceptableExtensionsForSave -{ - QStringList result; - for (int i=0; i<mSelectedNameFilter->count(); ++i) { - const QString &filter = mSelectedNameFilter->at(i); - if (filter.startsWith(QLatin1String("*.")) - && !filter.contains(QLatin1Char('?')) - && filter.count(QLatin1Char('*')) == 1) { - result += filter.mid(2); - } else { - return QStringList(); // Accept everything - } +- (void)recomputeAcceptableExtensionsForSave +{ + QStringList fileTypes; + for (const QString &filter : *mSelectedNameFilter) { + if (!filter.startsWith(QLatin1String("*."))) + continue; + + if (filter.contains(QLatin1Char('?'))) + continue; + + if (filter.count(QLatin1Char('*')) != 1) + continue; + + auto extensions = filter.split('.', Qt::SkipEmptyParts); + fileTypes += extensions.last(); + + // Explicitly show extensions if we detect a filter + // that has a multi-part extension. This prevents + // confusing situations where the user clicks e.g. + // 'foo.tar.gz' and 'foo.tar' is populated in the + // file name box, but when then clicking save macOS + // will warn that the file needs to end in .gz, + // due to thinking the user tried to save the file + // as a 'tar' file instead. Unfortunately this + // property can only be set before the panel is + // shown, so it will not have any effect when + // swithcing filters in an already opened dialog. + if (extensions.size() > 2) + mSavePanel.extensionHidden = NO; } - return result; + + mSavePanel.allowedFileTypes = fileTypes.isEmpty() ? nil + : qt_mac_QStringListToNSMutableArray(fileTypes); } - (QString)removeExtensions:(const QString &)filter diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index 6db4bdb9fd..ccb6e20071 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -554,7 +554,7 @@ NSOpenGLContext *QCocoaGLContext::nativeContext() const QFunctionPointer QCocoaGLContext::getProcAddress(const char *procName) { - return (QFunctionPointer)dlsym(RTLD_DEFAULT, procName); + return (QFunctionPointer)dlsym(RTLD_NEXT, procName); } #ifndef QT_NO_DEBUG_STREAM diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index 69a1854598..71e72dca4f 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -45,14 +45,17 @@ // ------------- // // This file is not part of the Qt API. It provides helper functions -// for the Cocoa lighthouse plugin. This header file may +// for the Cocoa plugin. This header file may // change from version to version without notice, or even be removed. // // We mean it. // -#include "qt_mac_p.h" + +#include <AppKit/AppKit.h> + #include <private/qguiapplication_p.h> #include <QtCore/qoperatingsystemversion.h> +#include <QtCore/qloggingcategory.h> #include <QtGui/qpalette.h> #include <QtGui/qscreen.h> diff --git a/src/plugins/platforms/cocoa/qcocoainputcontext.mm b/src/plugins/platforms/cocoa/qcocoainputcontext.mm index d0baea5b36..000bcd708b 100644 --- a/src/plugins/platforms/cocoa/qcocoainputcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoainputcontext.mm @@ -74,8 +74,6 @@ QT_BEGIN_NAMESPACE Input method support in Cocoa uses NSTextInput protorol. Therefore almost all functionality is implemented in QNSView. - - \ingroup qt-lighthouse-cocoa */ diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index bfc3bfe9de..0c14e07551 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -92,6 +92,10 @@ public: QCocoaVulkanInstance *getCocoaVulkanInstance() const; #endif +#if QT_CONFIG(sessionmanager) + QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const override; +#endif + QCoreTextFontDatabase *fontDatabase() const override; QCocoaNativeInterface *nativeInterface() const override; QPlatformInputContext *inputContext() const override; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index b7f15a2bf1..245db429c5 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -52,6 +52,9 @@ #include "qcocoamimetypes.h" #include "qcocoaaccessibility.h" #include "qcocoascreen.h" +#if QT_CONFIG(sessionmanager) +# include "qcocoasessionmanager.h" +#endif #include <qpa/qplatforminputcontextfactory_p.h> #include <qpa/qplatformaccessibility.h> @@ -113,7 +116,7 @@ class QFontEngineFT; static QCocoaIntegration::Options parseOptions(const QStringList ¶mList) { QCocoaIntegration::Options options; - foreach (const QString ¶m, paramList) { + for (const QString ¶m : paramList) { #ifndef QT_NO_FREETYPE if (param == QLatin1String("fontengine=freetype")) options |= QCocoaIntegration::UseFreeTypeFontEngine; @@ -245,6 +248,13 @@ QCocoaIntegration::Options QCocoaIntegration::options() const return mOptions; } +#if QT_CONFIG(sessionmanager) +QPlatformSessionManager *QCocoaIntegration::createPlatformSessionManager(const QString &id, const QString &key) const +{ + return new QCocoaSessionManager(id, key); +} +#endif + bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) const { switch (cap) { @@ -462,14 +472,7 @@ QList<QCocoaWindow *> *QCocoaIntegration::popupWindowStack() void QCocoaIntegration::setApplicationIcon(const QIcon &icon) const { - NSImage *image = nil; - if (!icon.isNull()) { - NSSize size = [[[NSApplication sharedApplication] dockTile] size]; - QPixmap pixmap = icon.pixmap(size.width, size.height); - image = static_cast<NSImage *>(qt_mac_create_nsimage(pixmap)); - } - [[NSApplication sharedApplication] setApplicationIconImage:image]; - [image release]; + NSApp.applicationIconImage = [NSImage imageFromQIcon:icon]; } void QCocoaIntegration::beep() const diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 8c4fca0d29..90d5180fed 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -334,7 +334,7 @@ void QCocoaMenu::setEnabled(bool enabled) bool QCocoaMenu::isEnabled() const { - return m_attachedItem ? m_attachedItem.enabled : m_enabled && m_parentEnabled; + return m_enabled && m_parentEnabled; } void QCocoaMenu::setVisible(bool visible) diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm index 363defdd28..a2a8535547 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.mm +++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm @@ -191,7 +191,7 @@ void QCocoaMenuBar::syncMenu_helper(QPlatformMenu *menu, bool menubarUpdate) QMacAutoReleasePool pool; QCocoaMenu *cocoaMenu = static_cast<QCocoaMenu *>(menu); - Q_FOREACH (QCocoaMenuItem *item, cocoaMenu->items()) + for (QCocoaMenuItem *item : cocoaMenu->items()) cocoaMenu->syncMenuItem_helper(item, menubarUpdate); BOOL shouldHide = YES; diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.h b/src/plugins/platforms/cocoa/qcocoamenuitem.h index c842b08d52..029d29be9d 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.h +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.h @@ -53,6 +53,18 @@ Q_FORWARD_DECLARE_OBJC_CLASS(NSView); QT_BEGIN_NAMESPACE +enum { + AboutAppMenuItem = 0, + PreferencesAppMenuItem, + ServicesAppMenuItem, + HideAppMenuItem, + HideOthersAppMenuItem, + ShowAllAppMenuItem, + QuitAppMenuItem +}; + +QString qt_mac_applicationmenu_string(int type); + class QCocoaMenu; class QCocoaMenuObject diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index c35cf6d799..3b37e7c9c1 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -45,18 +45,39 @@ #include "qcocoansmenu.h" #include "qcocoamenu.h" #include "qcocoamenubar.h" -#include "messages.h" #include "qcocoahelpers.h" -#include "qt_mac_p.h" #include "qcocoaapplication.h" // for custom application category #include "qcocoamenuloader.h" #include <QtGui/private/qcoregraphics_p.h> +#include <QtCore/qregularexpression.h> #include <QtCore/QDebug> #include <QtCore/QRegExp> QT_BEGIN_NAMESPACE +static const char *application_menu_strings[] = +{ + QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","About %1"), + QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Preferences..."), + QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Services"), + QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Hide %1"), + QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Hide Others"), + QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Show All"), + QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Quit %1") +}; + +QString qt_mac_applicationmenu_string(int type) +{ + QString menuString = QString::fromLatin1(application_menu_strings[type]); + const QString translated = QCoreApplication::translate("QMenuBar", application_menu_strings[type]); + if (translated != menuString) { + return translated; + } else { + return QCoreApplication::translate("MAC_APPLICATION_MENU", application_menu_strings[type]); + } +} + static quint32 constructModifierMask(quint32 accel_key) { quint32 ret = 0; @@ -226,6 +247,40 @@ void QCocoaMenuItem::setNativeContents(WId item) m_itemView.needsDisplay = YES; } +static QPlatformMenuItem::MenuRole detectMenuRole(const QString &caption) +{ + QString captionNoAmpersand(caption); + captionNoAmpersand.remove(QLatin1Char('&')); + const QString aboutString = QCoreApplication::translate("QCocoaMenuItem", "About"); + if (captionNoAmpersand.startsWith(aboutString, Qt::CaseInsensitive) + || captionNoAmpersand.endsWith(aboutString, Qt::CaseInsensitive)) { + static const QRegularExpression qtRegExp(QLatin1String("qt$"), QRegularExpression::CaseInsensitiveOption); + if (captionNoAmpersand.contains(qtRegExp)) + return QPlatformMenuItem::AboutQtRole; + return QPlatformMenuItem::AboutRole; + } + if (captionNoAmpersand.startsWith(QCoreApplication::translate("QCocoaMenuItem", "Config"), Qt::CaseInsensitive) + || captionNoAmpersand.startsWith(QCoreApplication::translate("QCocoaMenuItem", "Preference"), Qt::CaseInsensitive) + || captionNoAmpersand.startsWith(QCoreApplication::translate("QCocoaMenuItem", "Options"), Qt::CaseInsensitive) + || captionNoAmpersand.startsWith(QCoreApplication::translate("QCocoaMenuItem", "Setting"), Qt::CaseInsensitive) + || captionNoAmpersand.startsWith(QCoreApplication::translate("QCocoaMenuItem", "Setup"), Qt::CaseInsensitive)) { + return QPlatformMenuItem::PreferencesRole; + } + if (captionNoAmpersand.startsWith(QCoreApplication::translate("QCocoaMenuItem", "Quit"), Qt::CaseInsensitive) + || captionNoAmpersand.startsWith(QCoreApplication::translate("QCocoaMenuItem", "Exit"), Qt::CaseInsensitive)) { + return QPlatformMenuItem::QuitRole; + } + if (!captionNoAmpersand.compare(QCoreApplication::translate("QCocoaMenuItem", "Cut"), Qt::CaseInsensitive)) + return QPlatformMenuItem::CutRole; + if (!captionNoAmpersand.compare(QCoreApplication::translate("QCocoaMenuItem", "Copy"), Qt::CaseInsensitive)) + return QPlatformMenuItem::CopyRole; + if (!captionNoAmpersand.compare(QCoreApplication::translate("QCocoaMenuItem", "Paste"), Qt::CaseInsensitive)) + return QPlatformMenuItem::PasteRole; + if (!captionNoAmpersand.compare(QCoreApplication::translate("QCocoaMenuItem", "Select All"), Qt::CaseInsensitive)) + return QPlatformMenuItem::SelectAllRole; + return QPlatformMenuItem::NoRole; +} + NSMenuItem *QCocoaMenuItem::sync() { if (m_isSeparator != m_native.separatorItem) { @@ -341,13 +396,7 @@ NSMenuItem *QCocoaMenuItem::sync() m_native.keyEquivalentModifierMask = NSEventModifierFlagCommand; } - NSImage *img = nil; - if (!m_icon.isNull()) { - img = qt_mac_create_nsimage(m_icon, m_iconSize); - img.size = CGSizeMake(m_iconSize, m_iconSize); - } - m_native.image = img; - [img release]; + m_native.image = [NSImage imageFromQIcon:m_icon withSize:m_iconSize]; m_native.state = m_checked ? NSOnState : NSOffState; return m_native; @@ -360,7 +409,7 @@ QString QCocoaMenuItem::mergeText() return qt_mac_applicationmenu_string(AboutAppMenuItem).arg(qt_mac_applicationName()); } else if (m_native== [loader aboutQtMenuItem]) { if (m_text == QString("About Qt")) - return msgAboutQt(); + return QCoreApplication::translate("QCocoaMenuItem", "About Qt"); else return m_text; } else if (m_native == [loader preferencesMenuItem]) { diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.mm b/src/plugins/platforms/cocoa/qcocoamenuloader.mm index d384078e91..a7c17fc177 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuloader.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuloader.mm @@ -39,7 +39,6 @@ #include "qcocoamenuloader.h" -#include "messages.h" #include "qcocoahelpers.h" #include "qcocoansmenu.h" #include "qcocoamenubar.h" diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index d0e69bdca5..90e124b790 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -50,13 +50,13 @@ #include <qwindow.h> #include <qpixmap.h> #include <qpa/qplatformwindow.h> -#include "qsurfaceformat.h" +#include <QtGui/qsurfaceformat.h> #ifndef QT_NO_OPENGL #include <qpa/qplatformopenglcontext.h> -#include "qopenglcontext.h" +#include <QtGui/qopenglcontext.h> #include "qcocoaglcontext.h" #endif -#include "qguiapplication.h" +#include <QtGui/qguiapplication.h> #include <qdebug.h> #if !defined(QT_NO_WIDGETS) && defined(QT_PRINTSUPPORT_LIB) @@ -107,7 +107,7 @@ void *QCocoaNativeInterface::nativeResourceForWindow(const QByteArray &resourceS #if QT_CONFIG(vulkan) } else if (resourceString == "vkSurface") { if (QVulkanInstance *instance = window->vulkanInstance()) - return static_cast<QCocoaVulkanInstance *>(instance->handle())->createSurface(window); + return static_cast<QCocoaVulkanInstance *>(instance->handle())->surface(window); #endif } return nullptr; diff --git a/src/plugins/platforms/cocoa/qcocoansmenu.h b/src/plugins/platforms/cocoa/qcocoansmenu.h index 0c77e2f1aa..bd0334e061 100644 --- a/src/plugins/platforms/cocoa/qcocoansmenu.h +++ b/src/plugins/platforms/cocoa/qcocoansmenu.h @@ -53,7 +53,7 @@ #import <AppKit/AppKit.h> -#include <qcocoahelpers.h> +#include "qcocoahelpers.h" QT_FORWARD_DECLARE_CLASS(QCocoaMenu); QT_FORWARD_DECLARE_CLASS(QCocoaMenuItem); diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.h b/src/plugins/platforms/cocoa/qcocoaprintdevice.h index d267343b0e..59a521e0b5 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintdevice.h +++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.h @@ -55,8 +55,6 @@ #ifndef QT_NO_PRINTER -#include "qt_mac_p.h" - #include <cups/ppd.h> QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm index 7605dc9d1a..ab304d9c04 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm +++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm @@ -37,6 +37,8 @@ ** ****************************************************************************/ +#include <ApplicationServices/ApplicationServices.h> + #include "qcocoaprintdevice.h" #if QT_CONFIG(mimetype) @@ -44,6 +46,8 @@ #endif #include <qdebug.h> +#include <QtCore/private/qcore_mac_p.h> + QT_BEGIN_NAMESPACE #ifndef QT_NO_PRINTER @@ -117,7 +121,7 @@ QCocoaPrintDevice::~QCocoaPrintDevice() { if (m_ppd) ppdClose(m_ppd); - foreach (PMPaper paper, m_macPapers) + for (PMPaper paper : m_macPapers) PMRelease(paper); // Releasing the session appears to also release the printer if (m_session) @@ -171,7 +175,7 @@ QPageSize QCocoaPrintDevice::createPageSize(const PMPaper &paper) const void QCocoaPrintDevice::loadPageSizes() const { m_pageSizes.clear(); - foreach (PMPaper paper, m_macPapers) + for (PMPaper paper : m_macPapers) PMRelease(paper); m_macPapers.clear(); m_printableMargins.clear(); diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.h b/src/plugins/platforms/cocoa/qcocoaprintersupport.h index 40a638207a..b1a9541c03 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintersupport.h +++ b/src/plugins/platforms/cocoa/qcocoaprintersupport.h @@ -43,8 +43,6 @@ #include <qpa/qplatformprintersupport.h> #ifndef QT_NO_PRINTER -#include "qt_mac_p.h" - QT_BEGIN_NAMESPACE class QCocoaPrinterSupport : public QPlatformPrinterSupport diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.mm b/src/plugins/platforms/cocoa/qcocoaprintersupport.mm index d7eaa469fb..4c5c7aef88 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintersupport.mm +++ b/src/plugins/platforms/cocoa/qcocoaprintersupport.mm @@ -41,6 +41,10 @@ #ifndef QT_NO_PRINTER +#include <AppKit/AppKit.h> + +#include <QtCore/private/qcore_mac_p.h> + #include "qcocoaprintdevice.h" #include "qprintengine_mac_p.h" diff --git a/src/plugins/platforms/cocoa/qcocoasessionmanager.cpp b/src/plugins/platforms/cocoa/qcocoasessionmanager.cpp new file mode 100644 index 0000000000..725fc5acc0 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoasessionmanager.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Samuel Gaist <samuel.gaist@idiap.ch> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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 QT_NO_SESSIONMANAGER +#include <private/qsessionmanager_p.h> +#include <private/qguiapplication_p.h> + +#include "qcocoasessionmanager.h" +#include <qstring.h> + +QT_BEGIN_NAMESPACE + +QCocoaSessionManager::QCocoaSessionManager(const QString &id, const QString &key) + : QPlatformSessionManager(id, key), + m_canceled(false) +{ +} + +QCocoaSessionManager::~QCocoaSessionManager() +{ +} + +bool QCocoaSessionManager::allowsInteraction() +{ + return false; +} + +void QCocoaSessionManager::resetCancellation() +{ + m_canceled = false; +} + +void QCocoaSessionManager::cancel() +{ + m_canceled = true; +} + +bool QCocoaSessionManager::wasCanceled() const +{ + return m_canceled; +} + +QCocoaSessionManager *QCocoaSessionManager::instance() +{ + auto *qGuiAppPriv = QGuiApplicationPrivate::instance(); + auto *managerPrivate = static_cast<QSessionManagerPrivate*>(QObjectPrivate::get(qGuiAppPriv->session_manager)); + return static_cast<QCocoaSessionManager *>(managerPrivate->platformSessionManager); +} + +QT_END_NAMESPACE + +#endif // QT_NO_SESSIONMANAGER diff --git a/src/plugins/platforms/cocoa/qcocoasessionmanager.h b/src/plugins/platforms/cocoa/qcocoasessionmanager.h new file mode 100644 index 0000000000..89ab7bd157 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoasessionmanager.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Samuel Gaist <samuel.gaist@idiap.ch> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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 QCOCOASESSIONMANAGER_H +#define QCOCOASESSIONMANAGER_H + +// +// W A R N I N G +// ------------- +// +// This file is part of the QPA API and is not meant to be used +// in applications. Usage of this API may make your code +// source and binary incompatible with future versions of Qt. +// + +#ifndef QT_NO_SESSIONMANAGER + +#include <qpa/qplatformsessionmanager.h> + +QT_BEGIN_NAMESPACE + +class QCocoaSessionManager : public QPlatformSessionManager +{ +public: + QCocoaSessionManager(const QString &id, const QString &key); + virtual ~QCocoaSessionManager(); + + bool allowsInteraction() override; + void cancel() override; + void resetCancellation(); + bool wasCanceled() const; + + static QCocoaSessionManager *instance(); + +private: + bool m_canceled; + + Q_DISABLE_COPY(QCocoaSessionManager) +}; + +QT_END_NAMESPACE + +#endif // QT_NO_SESSIONMANAGER + +#endif // QCOCOASESSIONMANAGER_H diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h index 6779bda491..141995d1b1 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h +++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h @@ -46,17 +46,26 @@ #if QT_CONFIG(systemtrayicon) -#include "QtCore/qstring.h" -#include "QtGui/qpa/qplatformsystemtrayicon.h" +#include <QtCore/qstring.h> +#include <QtGui/qpa/qplatformsystemtrayicon.h> -QT_BEGIN_NAMESPACE +#include "qcocoamenu.h" + +QT_FORWARD_DECLARE_CLASS(QCocoaSystemTrayIcon); + +@interface QT_MANGLE_NAMESPACE(QStatusItemDelegate) : NSObject <NSUserNotificationCenterDelegate> +- (instancetype)initWithSysTray:(QCocoaSystemTrayIcon *)platformSystemTray; +@property (nonatomic, assign) QCocoaSystemTrayIcon *platformSystemTray; +@end -class QSystemTrayIconSys; +QT_NAMESPACE_ALIAS_OBJC_CLASS(QStatusItemDelegate); + +QT_BEGIN_NAMESPACE class Q_GUI_EXPORT QCocoaSystemTrayIcon : public QPlatformSystemTrayIcon { public: - QCocoaSystemTrayIcon() : m_sys(nullptr) {} + QCocoaSystemTrayIcon() {} void init() override; void cleanup() override; @@ -65,13 +74,17 @@ public: void updateMenu(QPlatformMenu *menu) override; QRect geometry() const override; void showMessage(const QString &title, const QString &msg, - const QIcon& icon, MessageIcon iconType, int secs) override; + const QIcon& icon, MessageIcon iconType, int msecs) override; bool isSystemTrayAvailable() const override; bool supportsMessages() const override; + void statusItemClicked(); + private: - QSystemTrayIconSys *m_sys; + NSStatusItem *m_statusItem = nullptr; + QStatusItemDelegate *m_delegate = nullptr; + QCocoaMenu *m_menu = nullptr; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm index a5b42ac4e3..704498acb1 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm @@ -84,7 +84,6 @@ #include "qcocoamenu.h" -#include "qt_mac_p.h" #include "qcocoahelpers.h" #include "qcocoaintegration.h" #include "qcocoascreen.h" @@ -92,67 +91,46 @@ #import <AppKit/AppKit.h> -QT_USE_NAMESPACE - -@interface QT_MANGLE_NAMESPACE(QNSStatusItem) : NSObject <NSUserNotificationCenterDelegate> -@property (nonatomic, assign) QCocoaMenu *menu; -@property (nonatomic, assign) QIcon icon; -@property (nonatomic, readonly) NSStatusItem *item; -@property (nonatomic, readonly) QRectF geometry; -- (instancetype)initWithSysTray:(QCocoaSystemTrayIcon *)systray; -- (void)triggerSelector:(id)sender button:(Qt::MouseButton)mouseButton; -- (void)doubleClickSelector:(id)sender; -@end +QT_BEGIN_NAMESPACE -QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSStatusItem); +void QCocoaSystemTrayIcon::init() +{ + m_statusItem = [[NSStatusBar.systemStatusBar statusItemWithLength:NSSquareStatusItemLength] retain]; -@interface QT_MANGLE_NAMESPACE(QNSImageView) : NSImageView -@property (nonatomic, assign) BOOL down; -@property (nonatomic, assign) QNSStatusItem *parent; -@end + m_delegate = [[QStatusItemDelegate alloc] initWithSysTray:this]; -QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSImageView); + m_statusItem.button.target = m_delegate; + m_statusItem.button.action = @selector(statusItemClicked); + [m_statusItem.button sendActionOn:NSEventMaskLeftMouseUp | NSEventMaskRightMouseUp | NSEventMaskOtherMouseUp]; +} -QT_BEGIN_NAMESPACE -class QSystemTrayIconSys +void QCocoaSystemTrayIcon::cleanup() { -public: - QSystemTrayIconSys(QCocoaSystemTrayIcon *sys) { - item = [[QNSStatusItem alloc] initWithSysTray:sys]; - NSUserNotificationCenter.defaultUserNotificationCenter.delegate = item; - } - ~QSystemTrayIconSys() { - [[[item item] view] setHidden: YES]; - NSUserNotificationCenter *center = NSUserNotificationCenter.defaultUserNotificationCenter; - if (center.delegate == item) - center.delegate = nil; - [item release]; - } - QNSStatusItem *item; -}; + NSUserNotificationCenter *center = NSUserNotificationCenter.defaultUserNotificationCenter; + if (center.delegate == m_delegate) + center.delegate = nil; -void QCocoaSystemTrayIcon::init() -{ - if (!m_sys) - m_sys = new QSystemTrayIconSys(this); + [NSStatusBar.systemStatusBar removeStatusItem:m_statusItem]; + [m_statusItem release]; + m_statusItem = nil; + + [m_delegate release]; + m_delegate = nil; + + m_menu = nullptr; } QRect QCocoaSystemTrayIcon::geometry() const { - if (!m_sys) + if (!m_statusItem) return QRect(); - const QRectF geom = [m_sys->item geometry]; - if (!geom.isNull()) - return geom.toRect(); - else - return QRect(); -} + if (NSWindow *window = m_statusItem.button.window) { + if (QCocoaScreen *screen = QCocoaScreen::get(window.screen)) + return screen->mapFromNative(window.frame).toRect(); + } -void QCocoaSystemTrayIcon::cleanup() -{ - delete m_sys; - m_sys = nullptr; + return QRect(); } static bool heightCompareFunction (QSize a, QSize b) { return (a.height() < b.height()); } @@ -165,17 +143,15 @@ static QList<QSize> sortByHeight(const QList<QSize> &sizes) void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon) { - if (!m_sys) + if (!m_statusItem) return; - m_sys->item.icon = icon; - - // The reccomended maximum title bar icon height is 18 points + // The recommended maximum title bar icon height is 18 points // (device independent pixels). The menu height on past and // current OS X versions is 22 points. Provide some future-proofing // by deriving the icon height from the menu height. const int padding = 4; - const int menuHeight = [[NSStatusBar systemStatusBar] thickness]; + const int menuHeight = NSStatusBar.systemStatusBar.thickness; const int maxImageHeight = menuHeight - padding; // Select pixmap based on the device pixel height. Ideally we would use @@ -185,7 +161,7 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon) qreal devicePixelRatio = qApp->devicePixelRatio(); const int maxPixmapHeight = maxImageHeight * devicePixelRatio; QSize selectedSize; - Q_FOREACH (const QSize& size, sortByHeight(icon.availableSizes())) { + for (const QSize& size : sortByHeight(icon.availableSizes())) { // Select a pixmap based on the height. We want the largest pixmap // with a height smaller or equal to maxPixmapHeight. The pixmap // may rectangular; assume it has a reasonable size. If there is @@ -228,30 +204,28 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon) p.drawPixmap(r, pixmap); } - NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(fullHeightPixmap)); + auto *nsimage = [NSImage imageFromQImage:fullHeightPixmap.toImage()]; [nsimage setTemplate:icon.isMask()]; - [(NSImageView*)[[m_sys->item item] view] setImage: nsimage]; - [nsimage release]; + m_statusItem.button.image = nsimage; + m_statusItem.button.imageScaling = NSImageScaleProportionallyDown; } void QCocoaSystemTrayIcon::updateMenu(QPlatformMenu *menu) { - if (!m_sys) - return; - - m_sys->item.menu = static_cast<QCocoaMenu *>(menu); - if (menu && [m_sys->item.menu->nsMenu() numberOfItems] > 0) { - [[m_sys->item item] setHighlightMode:YES]; - } else { - [[m_sys->item item] setHighlightMode:NO]; - } + // We don't set the menu property of the NSStatusItem here, + // as that would prevent us from receiving the action for the + // click, and we wouldn't be able to emit the activated signal. + // Instead we show the menu manually when the status item is + // clicked. + m_menu = static_cast<QCocoaMenu *>(menu); } void QCocoaSystemTrayIcon::updateToolTip(const QString &toolTip) { - if (!m_sys) + if (!m_statusItem) return; - [[[m_sys->item item] view] setToolTip:toolTip.toNSString()]; + + m_statusItem.button.toolTip = toolTip.toNSString(); } bool QCocoaSystemTrayIcon::isSystemTrayAvailable() const @@ -265,179 +239,85 @@ bool QCocoaSystemTrayIcon::supportsMessages() const } void QCocoaSystemTrayIcon::showMessage(const QString &title, const QString &message, - const QIcon& icon, MessageIcon, int) + const QIcon& icon, MessageIcon, int msecs) { - if (!m_sys) + if (!m_statusItem) return; - NSUserNotification *notification = [[NSUserNotification alloc] init]; - notification.title = [NSString stringWithUTF8String:title.toUtf8().data()]; - notification.informativeText = [NSString stringWithUTF8String:message.toUtf8().data()]; - - if (!icon.isNull()) { - auto *nsimage = qt_mac_create_nsimage(icon); - [nsimage setTemplate:icon.isMask()]; - notification.contentImage = [nsimage autorelease]; - } + auto *notification = [[NSUserNotification alloc] init]; + notification.title = title.toNSString(); + notification.informativeText = message.toNSString(); + notification.contentImage = [NSImage imageFromQIcon:icon]; NSUserNotificationCenter *center = NSUserNotificationCenter.defaultUserNotificationCenter; - center.delegate = m_sys->item; - [center deliverNotification:notification]; - [notification release]; -} -QT_END_NAMESPACE + center.delegate = m_delegate; -@implementation NSStatusItem (Qt) -@end + [center deliverNotification:[notification autorelease]]; -@implementation QNSImageView -- (instancetype)initWithParent:(QNSStatusItem *)myParent { - self = [super init]; - self.parent = myParent; - self.down = NO; - return self; + if (msecs) { + NSTimeInterval timeout = msecs / 1000.0; + [center performSelector:@selector(removeDeliveredNotification:) withObject:notification afterDelay:timeout]; + } } -- (void)menuTrackingDone:(NSNotification *)__unused notification +void QCocoaSystemTrayIcon::statusItemClicked() { - self.down = NO; + auto *mouseEvent = NSApp.currentEvent; - [self setNeedsDisplay:YES]; -} - -- (void)mousePressed:(NSEvent *)mouseEvent -{ - self.down = YES; - int clickCount = [mouseEvent clickCount]; - [self setNeedsDisplay:YES]; + auto activationReason = QPlatformSystemTrayIcon::Unknown; - if (clickCount == 2) { - [self menuTrackingDone:nil]; - [self.parent doubleClickSelector:self]; + if (mouseEvent.clickCount == 2) { + activationReason = QPlatformSystemTrayIcon::DoubleClick; } else { - [self.parent triggerSelector:self button:cocoaButton2QtButton(mouseEvent)]; + auto mouseButton = cocoaButton2QtButton(mouseEvent); + if (mouseButton == Qt::MidButton) + activationReason = QPlatformSystemTrayIcon::MiddleClick; + else if (mouseButton == Qt::RightButton) + activationReason = QPlatformSystemTrayIcon::Context; + else + activationReason = QPlatformSystemTrayIcon::Trigger; } -} -- (void)mouseDown:(NSEvent *)mouseEvent -{ - [self mousePressed:mouseEvent]; -} + emit activated(activationReason); -- (void)mouseUp:(NSEvent *)mouseEvent -{ - Q_UNUSED(mouseEvent); - [self menuTrackingDone:nil]; + if (NSMenu *menu = m_menu ? m_menu->nsMenu() : nil) + [m_statusItem popUpStatusItemMenu:menu]; } -- (void)rightMouseDown:(NSEvent *)mouseEvent -{ - [self mousePressed:mouseEvent]; -} +QT_END_NAMESPACE -- (void)rightMouseUp:(NSEvent *)mouseEvent -{ - Q_UNUSED(mouseEvent); - [self menuTrackingDone:nil]; -} +@implementation QStatusItemDelegate -- (void)otherMouseDown:(NSEvent *)mouseEvent +- (instancetype)initWithSysTray:(QCocoaSystemTrayIcon *)platformSystemTray { - [self mousePressed:mouseEvent]; -} + if ((self = [super init])) + self.platformSystemTray = platformSystemTray; -- (void)otherMouseUp:(NSEvent *)mouseEvent -{ - Q_UNUSED(mouseEvent); - [self menuTrackingDone:nil]; -} - -- (void)drawRect:(NSRect)rect { - [[self.parent item] drawStatusBarBackgroundInRect:rect withHighlight:self.down]; - [super drawRect:rect]; -} -@end - -@implementation QNSStatusItem { - QCocoaSystemTrayIcon *systray; - NSStatusItem *item; - QNSImageView *imageCell; -} - -@synthesize menu = menu; -@synthesize icon = icon; - -- (instancetype)initWithSysTray:(QCocoaSystemTrayIcon *)sys -{ - self = [super init]; - if (self) { - item = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain]; - menu = nullptr; - systray = sys; - imageCell = [[QNSImageView alloc] initWithParent:self]; - [item setView: imageCell]; - } return self; } -- (void)dealloc { - [[NSStatusBar systemStatusBar] removeStatusItem:item]; - [[NSNotificationCenter defaultCenter] removeObserver:imageCell]; - imageCell.parent = nil; - [imageCell release]; - [item release]; +- (void)dealloc +{ + self.platformSystemTray = nullptr; [super dealloc]; } -- (NSStatusItem *)item { - return item; -} - -- (QRectF)geometry { - if (NSWindow *window = item.view.window) { - if (QCocoaScreen *screen = QCocoaScreen::get(window.screen)) - return screen->mapFromNative(window.frame); - } - return QRectF(); -} - -- (void)triggerSelector:(id)sender button:(Qt::MouseButton)mouseButton { - Q_UNUSED(sender); - if (!systray) - return; - - if (mouseButton == Qt::MidButton) - emit systray->activated(QPlatformSystemTrayIcon::MiddleClick); - else - emit systray->activated(QPlatformSystemTrayIcon::Trigger); - - if (menu) { - NSMenu *m = menu->nsMenu(); - [[NSNotificationCenter defaultCenter] addObserver:imageCell - selector:@selector(menuTrackingDone:) - name:NSMenuDidEndTrackingNotification - object:m]; - [item popUpStatusItemMenu: m]; - } -} - -- (void)doubleClickSelector:(id)sender { - Q_UNUSED(sender); - if (!systray) - return; - emit systray->activated(QPlatformSystemTrayIcon::DoubleClick); +- (void)statusItemClicked +{ + self.platformSystemTray->statusItemClicked(); } -- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification { +- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification +{ Q_UNUSED(center); Q_UNUSED(notification); return YES; } -- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification { - Q_UNUSED(center); - Q_UNUSED(notification); - emit systray->messageClicked(); +- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification +{ + [center removeDeliveredNotification:notification]; + emit self.platformSystemTray->messageClicked(); } @end diff --git a/src/plugins/platforms/cocoa/qcocoatheme.h b/src/plugins/platforms/cocoa/qcocoatheme.h index a00cbdfea3..50e56ef1bf 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.h +++ b/src/plugins/platforms/cocoa/qcocoatheme.h @@ -70,7 +70,7 @@ public: const QPalette *palette(Palette type = SystemPalette) const override; const QFont *font(Font type = SystemFont) const override; QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const override; - QIcon fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions options = 0) const override; + QIcon fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions options = {}) const override; QVariant themeHint(ThemeHint hint) const override; QString standardButtonText(int button) const override; diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm index a76ba300e9..d73b028afb 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.mm +++ b/src/plugins/platforms/cocoa/qcocoatheme.mm @@ -40,7 +40,6 @@ #import <AppKit/AppKit.h> #include "qcocoatheme.h" -#include "messages.h" #include <QtCore/QOperatingSystemVersion> #include <QtCore/QVariant> @@ -547,7 +546,9 @@ QVariant QCocoaTheme::themeHint(ThemeHint hint) const QString QCocoaTheme::standardButtonText(int button) const { - return button == QPlatformDialogHelper::Discard ? msgDialogButtonDiscard() : QPlatformTheme::standardButtonText(button); + return button == QPlatformDialogHelper::Discard ? + QCoreApplication::translate("QCocoaTheme", "Don't Save") + : QPlatformTheme::standardButtonText(button); } QKeySequence QCocoaTheme::standardButtonShortcut(int button) const diff --git a/src/plugins/platforms/cocoa/qcocoavulkaninstance.h b/src/plugins/platforms/cocoa/qcocoavulkaninstance.h index 5fe6a612af..2a8d04757e 100644 --- a/src/plugins/platforms/cocoa/qcocoavulkaninstance.h +++ b/src/plugins/platforms/cocoa/qcocoavulkaninstance.h @@ -61,9 +61,11 @@ public: void createOrAdoptInstance() override; - VkSurfaceKHR *createSurface(QWindow *window); - VkSurfaceKHR createSurface(NSView *view); + VkSurfaceKHR *surface(QWindow *window); + private: + VkSurfaceKHR createSurface(NSView *view); + QVulkanInstance *m_instance = nullptr; QLibrary m_lib; VkSurfaceKHR m_nullSurface = nullptr; diff --git a/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm b/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm index 7ce78ee738..9e714859f2 100644 --- a/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm +++ b/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm @@ -57,12 +57,11 @@ void QCocoaVulkanInstance::createOrAdoptInstance() initInstance(m_instance, QByteArrayList() << QByteArrayLiteral("VK_MVK_macos_surface")); } -VkSurfaceKHR *QCocoaVulkanInstance::createSurface(QWindow *window) +VkSurfaceKHR *QCocoaVulkanInstance::surface(QWindow *window) { QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle()); - if (cocoaWindow->m_vulkanSurface) - destroySurface(cocoaWindow->m_vulkanSurface); - cocoaWindow->m_vulkanSurface = createSurface(cocoaWindow->m_view); + if (!cocoaWindow->m_vulkanSurface) + cocoaWindow->m_vulkanSurface = createSurface(cocoaWindow->m_view); return &cocoaWindow->m_vulkanSurface; } @@ -81,7 +80,7 @@ VkSurfaceKHR QCocoaVulkanInstance::createSurface(NSView *view) surfaceInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK; surfaceInfo.pNext = nullptr; surfaceInfo.flags = 0; - surfaceInfo.pView = view; + surfaceInfo.pView = view.layer; VkSurfaceKHR surface = nullptr; VkResult err = m_createSurface(m_vkInst, &surfaceInfo, nullptr, &surface); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index fef72bc496..291a27b15e 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -51,7 +51,6 @@ #endif #include "qnsview.h" #include "qnswindow.h" -#include "qt_mac_p.h" #if QT_CONFIG(vulkan) #include <MoltenVK/mvk_vulkan.h> @@ -218,6 +217,8 @@ protected: void toggleFullScreen(); bool isTransitioningToFullScreen() const; + bool startSystemMove() override; + // private: public: // for QNSView friend class QCocoaBackingStore; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 69d192b4f5..79dfe58a4e 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -299,6 +299,22 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect) // will call QPlatformWindow::setGeometry(rect) during resize confirmation (see qnsview.mm) } +bool QCocoaWindow::startSystemMove() +{ + switch (NSApp.currentEvent.type) { + case NSEventTypeLeftMouseDown: + case NSEventTypeRightMouseDown: + case NSEventTypeOtherMouseDown: + case NSEventTypeMouseMoved: + // The documentation only describes starting a system move + // based on mouse down events, but move events also work. + [m_view.window performWindowDragWithEvent:NSApp.currentEvent]; + return true; + default: + return false; + } +} + void QCocoaWindow::setVisible(bool visible) { qCDebug(lcQpaWindow) << "QCocoaWindow::setVisible" << window() << visible; @@ -878,14 +894,10 @@ void QCocoaWindow::setWindowIcon(const QIcon &icon) QMacAutoReleasePool pool; - if (icon.isNull()) { - NSWorkspace *workspace = [NSWorkspace sharedWorkspace]; - [iconButton setImage:[workspace iconForFile:m_view.window.representedFilename]]; - } else { - QPixmap pixmap = icon.pixmap(QSize(22, 22)); - NSImage *image = static_cast<NSImage *>(qt_mac_create_nsimage(pixmap)); - [iconButton setImage:[image autorelease]]; - } + if (icon.isNull()) + iconButton.image = [NSWorkspace.sharedWorkspace iconForFile:m_view.window.representedFilename]; + else + iconButton.image = [NSImage imageFromQIcon:icon]; } void QCocoaWindow::setAlertState(bool enabled) @@ -1224,7 +1236,9 @@ void QCocoaWindow::windowDidOrderOffScreen() void QCocoaWindow::windowDidChangeOcclusionState() { - if (m_view.window.occlusionState & NSWindowOcclusionStateVisible) + bool visible = m_view.window.occlusionState & NSWindowOcclusionStateVisible; + qCDebug(lcQpaWindow) << "QCocoaWindow::windowDidChangeOcclusionState" << window() << "is now" << (visible ? "visible" : "occluded"); + if (visible) [m_view setNeedsDisplay:YES]; else handleExposeEvent(QRegion()); @@ -1619,6 +1633,7 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel) nsWindow.restorable = NO; nsWindow.level = windowLevel(flags); + nsWindow.tabbingMode = NSWindowTabbingModeDisallowed; if (shouldBePanel) { // Qt::Tool windows hide on app deactivation, unless Qt::WA_MacAlwaysShowToolWindow is set @@ -1818,7 +1833,7 @@ qreal QCocoaWindow::devicePixelRatio() const QWindow *QCocoaWindow::childWindowAt(QPoint windowPoint) { QWindow *targetWindow = window(); - foreach (QObject *child, targetWindow->children()) + for (QObject *child : targetWindow->children()) if (QWindow *childWindow = qobject_cast<QWindow *>(child)) if (QPlatformWindow *handle = childWindow->handle()) if (handle->isExposed() && childWindow->geometry().contains(windowPoint)) diff --git a/src/plugins/platforms/cocoa/qmacclipboard.mm b/src/plugins/platforms/cocoa/qmacclipboard.mm index 358a6b49fd..99b378be68 100644 --- a/src/plugins/platforms/cocoa/qmacclipboard.mm +++ b/src/plugins/platforms/cocoa/qmacclipboard.mm @@ -38,14 +38,14 @@ ****************************************************************************/ #include "qmacclipboard.h" -#include "qclipboard.h" -#include "qguiapplication.h" -#include "qbitmap.h" -#include "qdatetime.h" -#include "qdebug.h" -#include "qguiapplication.h" -#include "qevent.h" -#include "qurl.h" +#include <QtGui/qclipboard.h> +#include <QtGui/qguiapplication.h> +#include <QtGui/qbitmap.h> +#include <QtCore/qdatetime.h> +#include <QtCore/qdebug.h> +#include <QtGui/qguiapplication.h> +#include <QtGui/qevent.h> +#include <QtCore/qurl.h> #include <stdlib.h> #include <string.h> #include "qcocoahelpers.h" @@ -138,8 +138,12 @@ QMacPasteboard::QMacPasteboard(CFStringRef name, uchar mt) QMacPasteboard::~QMacPasteboard() { - // commit all promises for paste after exit close - resolvingBeforeDestruction = true; + /* + Commit all promises for paste when shutting down, + unless we are the stack-allocated clipboard used by QCocoaDrag. + */ + if (mime_type == QMacInternalPasteboardMime::MIME_DND) + resolvingBeforeDestruction = true; PasteboardResolvePromises(paste); if (paste) CFRelease(paste); diff --git a/src/plugins/platforms/cocoa/qmacdefines_mac.h b/src/plugins/platforms/cocoa/qmacdefines_mac.h deleted file mode 100644 index 9e229b8dcb..0000000000 --- a/src/plugins/platforms/cocoa/qmacdefines_mac.h +++ /dev/null @@ -1,129 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui 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$ -** -****************************************************************************/ - -/**************************************************************************** -** -** Copyright (c) 2007-2008, Apple, Inc. -** -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are met: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions in binary form must reproduce the above copyright notice, -** this list of conditions and the following disclaimer in the documentation -** and/or other materials provided with the distribution. -** -** * Neither the name of Apple, Inc. nor the names of its contributors -** may be used to endorse or promote products derived from this software -** without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -** -****************************************************************************/ - -/* - * qmacdefines_mac_p.h - * All the defines you'll ever need for Qt/Mac :-) - */ - -/* This is just many defines. Therefore it doesn't need things like: -QT_BEGIN_NAMESPACE - - -QT_END_NAMESPACE - -Yes, it is an informative comment ;-) -*/ - -#include <QtCore/qglobal.h> - -#ifdef __LP64__ -typedef signed int OSStatus; -#else -typedef signed long OSStatus; -#endif - -typedef struct OpaqueEventHandlerCallRef * EventHandlerCallRef; -typedef struct OpaqueEventRef * EventRef; -typedef struct OpaqueMenuRef * MenuRef; -typedef struct OpaquePasteboardRef* PasteboardRef; -typedef struct OpaqueRgnHandle * RgnHandle; -typedef const struct __HIShape *HIShapeRef; -typedef struct __HIShape *HIMutableShapeRef; -typedef struct CGRect CGRect; -typedef struct CGImage *CGImageRef; -typedef struct CGContext *CGContextRef; -typedef struct GDevice * GDPtr; -typedef GDPtr * GDHandle; -typedef struct OpaqueIconRef * IconRef; - -#ifdef __OBJC__ -typedef NSWindow* OSWindowRef; -typedef NSView *OSViewRef; -typedef NSMenu *OSMenuRef; -typedef NSEvent *OSEventRef; -#else -typedef void *OSWindowRef; -typedef void *OSViewRef; -typedef void *OSMenuRef; -typedef void *OSEventRef; -#endif - -typedef PasteboardRef OSPasteboardRef; -typedef struct AEDesc AEDescList; -typedef AEDescList AERecord; -typedef AERecord AppleEvent; - -#ifdef check -#undef check -#endif diff --git a/src/plugins/platforms/cocoa/qmultitouch_mac.mm b/src/plugins/platforms/cocoa/qmultitouch_mac.mm index 10652dc6a1..95256657fe 100644 --- a/src/plugins/platforms/cocoa/qmultitouch_mac.mm +++ b/src/plugins/platforms/cocoa/qmultitouch_mac.mm @@ -184,7 +184,7 @@ QCocoaTouch::getCurrentTouchPointList(NSEvent *event, bool acceptSingleTouch) if (_touchCount != _currentTouches.size()) { // Remove all instances, and basically start from scratch: touchPoints.clear(); - foreach (QCocoaTouch *qcocoaTouch, _currentTouches) { + for (QCocoaTouch *qcocoaTouch : _currentTouches) { if (!_updateInternalStateOnly) { qcocoaTouch->_touchPoint.state = Qt::TouchPointReleased; touchPoints.insert(qcocoaTouch->_touchPoint.id, qcocoaTouch->_touchPoint); diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index 74d0735b4c..0a18afe3a6 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -43,7 +43,7 @@ #include <AppKit/AppKit.h> #include <MetalKit/MetalKit.h> -#include "private/qcore_mac_p.h" +#include <QtCore/private/qcore_mac_p.h> QT_BEGIN_NAMESPACE class QCocoaWindow; diff --git a/src/plugins/platforms/cocoa/qnsview_dragging.mm b/src/plugins/platforms/cocoa/qnsview_dragging.mm index 650612e7ff..463e3c5579 100644 --- a/src/plugins/platforms/cocoa/qnsview_dragging.mm +++ b/src/plugins/platforms/cocoa/qnsview_dragging.mm @@ -150,10 +150,8 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin break; } } else { - NSImage *nsimage = qt_mac_create_nsimage(pixmapCursor); - nsimage.size = NSSizeFromCGSize((pixmapCursor.size() / pixmapCursor.devicePixelRatioF()).toCGSize()); + auto *nsimage = [NSImage imageFromQImage:pixmapCursor.toImage()]; nativeCursor = [[NSCursor alloc] initWithImage:nsimage hotSpot:NSZeroPoint]; - [nsimage release]; } // Change the cursor diff --git a/src/plugins/platforms/cocoa/qnsview_menus.mm b/src/plugins/platforms/cocoa/qnsview_menus.mm index a55fd97eb7..7ae274ab04 100644 --- a/src/plugins/platforms/cocoa/qnsview_menus.mm +++ b/src/plugins/platforms/cocoa/qnsview_menus.mm @@ -39,11 +39,11 @@ // This file is included from qnsview.mm, and only used to organize the code -#include <qcocoaapplicationdelegate.h> -#include <qcocoansmenu.h> -#include <qcocoamenuitem.h> -#include <qcocoamenu.h> -#include <qcocoamenubar.h> +#include "qcocoaapplicationdelegate.h" +#include "qcocoansmenu.h" +#include "qcocoamenuitem.h" +#include "qcocoamenu.h" +#include "qcocoamenubar.h" static bool selectorIsCutCopyPaste(SEL selector) { @@ -84,7 +84,8 @@ static bool selectorIsCutCopyPaste(SEL selector) menuParent = menuObject->menuParent(); } - if (menubar && menubar->cocoaWindow() != self.platformWindow) + // we have no menubar parent for the application menu items, e.g About and Preferences + if (!menubar || menubar->cocoaWindow() != self.platformWindow) return NO; } diff --git a/src/plugins/platforms/cocoa/qnswindow.h b/src/plugins/platforms/cocoa/qnswindow.h index 5fc48d826f..3263df3862 100644 --- a/src/plugins/platforms/cocoa/qnswindow.h +++ b/src/plugins/platforms/cocoa/qnswindow.h @@ -42,7 +42,7 @@ #include <qglobal.h> #include <QPointer> -#include "qt_mac_p.h" +#include <QtCore/private/qcore_mac_p.h> #include <AppKit/AppKit.h> diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm index 00b2267f0d..5ced962cb1 100644 --- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm @@ -37,6 +37,9 @@ ** ****************************************************************************/ +#include <AppKit/AppKit.h> +#include <CoreGraphics/CoreGraphics.h> + #include "qpaintengine_mac_p.h" #if defined(QT_PRINTSUPPORT_LIB) #include "qprintengine_mac_p.h" @@ -394,16 +397,19 @@ QCoreGraphicsPaintEngine::begin(QPaintDevice *pdev) d->cosmeticPenSize = 1; d->current.clipEnabled = false; d->pixelSize = QPoint(1,1); - QMacCGContext ctx(pdev); - d->hd = CGContextRetain(ctx); - if (d->hd) { - d->saveGraphicsState(); - d->orig_xform = CGContextGetCTM(d->hd); - if (d->shading) { - CGShadingRelease(d->shading); - d->shading = nullptr; + + if (pdev->devType() != QInternal::Printer) { + QMacCGContext ctx(pdev); + d->hd = CGContextRetain(ctx); + if (d->hd) { + d->saveGraphicsState(); + d->orig_xform = CGContextGetCTM(d->hd); + if (d->shading) { + CGShadingRelease(d->shading); + d->shading = nullptr; + } + d->setClip(nullptr); //clear the context's clipping } - d->setClip(nullptr); //clear the context's clipping } setActive(true); diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac_p.h b/src/plugins/platforms/cocoa/qpaintengine_mac_p.h index 1416386745..a52e9cbe1c 100644 --- a/src/plugins/platforms/cocoa/qpaintengine_mac_p.h +++ b/src/plugins/platforms/cocoa/qpaintengine_mac_p.h @@ -51,15 +51,15 @@ // We mean it. // -#include "QtGui/qpaintengine.h" -#include "private/qpaintengine_p.h" -#include "private/qpolygonclipper_p.h" -#include "private/qfont_p.h" -#include "QtCore/qhash.h" - -#include "qt_mac_p.h" +#include <QtGui/qpaintengine.h> +#include <QtGui/private/qpaintengine_p.h> +#include <QtGui/private/qpolygonclipper_p.h> +#include <QtGui/private/qfont_p.h> +#include <QtCore/qhash.h> typedef struct CGColorSpace *CGColorSpaceRef; +typedef struct CGContext *CGContextRef; + QT_BEGIN_NAMESPACE class QCoreGraphicsPaintEnginePrivate; diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index dcb9a85a3c..9391f921ec 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -37,6 +37,9 @@ ** ****************************************************************************/ +#include <AppKit/AppKit.h> +#include <ApplicationServices/ApplicationServices.h> + #include "qprintengine_mac_p.h" #include "qcocoaprintersupport.h" #include <quuid.h> @@ -44,6 +47,7 @@ #include <QtCore/qcoreapplication.h> #include <QtCore/qdebug.h> +#include <QtCore/private/qcore_mac_p.h> #ifndef QT_NO_PRINTER @@ -485,7 +489,7 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va int bestResolution = 0; int dpi = value.toInt(); int bestDistance = INT_MAX; - foreach (int resolution, d->m_printDevice->supportedResolutions()) { + for (int resolution : d->m_printDevice->supportedResolutions()) { if (dpi == resolution) { bestResolution = resolution; break; @@ -758,7 +762,7 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const } case PPK_SupportedResolutions: { QList<QVariant> list; - foreach (int resolution, d->m_printDevice->supportedResolutions()) + for (int resolution : d->m_printDevice->supportedResolutions()) list << resolution; ret = list; break; diff --git a/src/plugins/platforms/cocoa/qt_attribution.json b/src/plugins/platforms/cocoa/qt_attribution.json index 37c0937f29..1da0d7e370 100644 --- a/src/plugins/platforms/cocoa/qt_attribution.json +++ b/src/plugins/platforms/cocoa/qt_attribution.json @@ -3,7 +3,7 @@ "Name": "Cocoa Platform Plugin", "QDocModule": "qtgui", "QtUsage": "Code used in the Qt Platform Abstraction (QPA) for macOS.", - "Files": "qcocoaapplication.h qcocoaapplication.mm qcocoaapplicationdelegate.h qcocoaapplicationdelegate.mm qcocoaeventdispatcher.h qcocoaeventdispatcher.mm qcocoaintrospection.h qcocoaintrospection.mm qcocoasystemtrayicon.mm qmacdefines_mac.h", + "Files": "qcocoaapplication.h qcocoaapplication.mm qcocoaapplicationdelegate.h qcocoaapplicationdelegate.mm qcocoaeventdispatcher.h qcocoaeventdispatcher.mm qcocoaintrospection.h qcocoaintrospection.mm qcocoasystemtrayicon.mm", "Description": "Allows Qt to integrate into Apple's Cocoa API.", "LicenseId": "BSD-3-Clause", diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp index 9689d6a89b..95b30ec447 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp @@ -58,7 +58,6 @@ QT_BEGIN_NAMESPACE \class QWindowsDirect2DBackingStore \brief Backing store for windows. \internal - \ingroup qt-lighthouse-win */ static inline QWindowsDirect2DPlatformPixmap *platformPixmap(QPixmap *p) diff --git a/src/plugins/platforms/eglfs/api/api.pri b/src/plugins/platforms/eglfs/api/api.pri index a6d81016b6..68965b58d8 100644 --- a/src/plugins/platforms/eglfs/api/api.pri +++ b/src/plugins/platforms/eglfs/api/api.pri @@ -23,4 +23,13 @@ qtConfig(opengl) { $$PWD/qeglfscontext_p.h } +qtConfig(vulkan) { + SOURCES += \ + $$PWD/vulkan/qeglfsvulkaninstance.cpp \ + $$PWD/vulkan/qeglfsvulkanwindow.cpp + HEADERS += \ + $$PWD/vulkan/qeglfsvulkaninstance_p.h \ + $$PWD/vulkan/qeglfsvulkanwindow_p.h +} + INCLUDEPATH += $$PWD diff --git a/src/plugins/platforms/eglfs/api/qeglfscontext.cpp b/src/plugins/platforms/eglfs/api/qeglfscontext.cpp index c5cef34d8e..48fafbda8d 100644 --- a/src/plugins/platforms/eglfs/api/qeglfscontext.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfscontext.cpp @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE QEglFSContext::QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLConfig *config, const QVariant &nativeHandle) : QEGLPlatformContext(format, share, display, config, nativeHandle, - qt_egl_device_integration()->supportsSurfacelessContexts() ? Flags(0) : QEGLPlatformContext::NoSurfaceless), + qt_egl_device_integration()->supportsSurfacelessContexts() ? Flags() : QEGLPlatformContext::NoSurfaceless), m_tempWindow(0) { } @@ -78,7 +78,7 @@ EGLSurface QEglFSContext::createTemporaryOffscreenSurface() } } EGLConfig config = q_configFromGLFormat(eglDisplay(), format()); - return eglCreateWindowSurface(eglDisplay(), config, m_tempWindow, 0); + return eglCreateWindowSurface(eglDisplay(), config, m_tempWindow, nullptr); } void QEglFSContext::destroyTemporaryOffscreenSurface(EGLSurface surface) diff --git a/src/plugins/platforms/eglfs/api/qeglfscursor.cpp b/src/plugins/platforms/eglfs/api/qeglfscursor.cpp index 22319fcc66..98e05195ee 100644 --- a/src/plugins/platforms/eglfs/api/qeglfscursor.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfscursor.cpp @@ -62,7 +62,7 @@ QEglFSCursor::QEglFSCursor(QPlatformScreen *screen) : m_visible(true), m_screen(static_cast<QEglFSScreen *>(screen)), m_activeScreen(nullptr), - m_deviceListener(0), + m_deviceListener(nullptr), m_updateRequested(false) { QByteArray hideCursorVal = qgetenv("QT_QPA_EGLFS_HIDECURSOR"); diff --git a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp index 81bad45cd2..b985386a4e 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp @@ -52,6 +52,7 @@ #include <QScreen> #include <QDir> #if QT_CONFIG(regularexpression) +# include <QFileInfo> # include <QRegularExpression> #endif #include <QLoggingCategory> @@ -144,7 +145,12 @@ int QEglFSDeviceIntegration::framebufferIndex() const int fbIndex = 0; #if QT_CONFIG(regularexpression) QRegularExpression fbIndexRx(QLatin1String("fb(\\d+)")); - QRegularExpressionMatch match = fbIndexRx.match(QString::fromLocal8Bit(fbDeviceName())); + QFileInfo fbinfo(QString::fromLocal8Bit(fbDeviceName())); + QRegularExpressionMatch match; + if (fbinfo.isSymLink()) + match = fbIndexRx.match(fbinfo.symLinkTarget()); + else + match = fbIndexRx.match(fbinfo.fileName()); if (match.hasMatch()) fbIndex = match.captured(1).toInt(); #endif @@ -179,7 +185,9 @@ void QEglFSDeviceIntegration::platformDestroy() EGLNativeDisplayType QEglFSDeviceIntegration::platformDisplay() const { - return EGL_DEFAULT_DISPLAY; + bool displayOk; + const int defaultDisplay = qEnvironmentVariableIntValue("QT_QPA_EGLFS_DEFAULT_DISPLAY", &displayOk); + return displayOk ? EGLNativeDisplayType(quintptr(defaultDisplay)) : EGL_DEFAULT_DISPLAY; } EGLDisplay QEglFSDeviceIntegration::createDisplay(EGLNativeDisplayType nativeDisplay) @@ -375,6 +383,14 @@ void *QEglFSDeviceIntegration::wlDisplay() const return nullptr; } +#if QT_CONFIG(vulkan) +QPlatformVulkanInstance *QEglFSDeviceIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) +{ + Q_UNUSED(instance); + return nullptr; +} +#endif + EGLConfig QEglFSDeviceIntegration::chooseConfig(EGLDisplay display, const QSurfaceFormat &format) { class Chooser : public QEglConfigChooser { diff --git a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h index 71ffb4c69a..08447a40ea 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h +++ b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h @@ -108,6 +108,10 @@ public: virtual void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen); virtual void *wlDisplay() const; +#if QT_CONFIG(vulkan) + virtual QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance); +#endif + static EGLConfig chooseConfig(EGLDisplay display, const QSurfaceFormat &format); }; diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp index 674f579b4f..e26d984cc1 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp @@ -109,10 +109,10 @@ QT_BEGIN_NAMESPACE QEglFSIntegration::QEglFSIntegration() : m_display(EGL_NO_DISPLAY), - m_inputContext(0), + m_inputContext(nullptr), m_fontDb(new QGenericUnixFontDatabase), m_services(new QGenericUnixServices), - m_kbdMgr(0), + m_kbdMgr(nullptr), m_disableInputHandlers(false) { m_disableInputHandlers = qEnvironmentVariableIntValue("QT_QPA_EGLFS_DISABLE_INPUT"); @@ -223,7 +223,7 @@ QPlatformOpenGLContext *QEglFSIntegration::createPlatformOpenGLContext(QOpenGLCo EGLConfig config = QEglFSDeviceIntegration::chooseConfig(dpy, adjustedFormat); ctx = new QEglFSContext(adjustedFormat, share, dpy, &config, QVariant()); } else { - ctx = new QEglFSContext(adjustedFormat, share, dpy, 0, nativeHandle); + ctx = new QEglFSContext(adjustedFormat, share, dpy, nullptr, nativeHandle); } nativeHandle = QVariant::fromValue<QEGLNativeContext>(QEGLNativeContext(ctx->eglContext(), dpy)); @@ -236,7 +236,7 @@ QPlatformOffscreenSurface *QEglFSIntegration::createPlatformOffscreenSurface(QOf EGLDisplay dpy = surface->screen() ? static_cast<QEglFSScreen *>(surface->screen()->handle())->display() : display(); QSurfaceFormat fmt = qt_egl_device_integration()->surfaceFormatFor(surface->requestedFormat()); if (qt_egl_device_integration()->supportsPBuffers()) { - QEGLPlatformContext::Flags flags = 0; + QEGLPlatformContext::Flags flags; if (!qt_egl_device_integration()->supportsSurfacelessContexts()) flags |= QEGLPlatformContext::NoSurfaceless; return new QEGLPbuffer(dpy, fmt, surface, flags); @@ -247,6 +247,13 @@ QPlatformOffscreenSurface *QEglFSIntegration::createPlatformOffscreenSurface(QOf } #endif // QT_NO_OPENGL +#if QT_CONFIG(vulkan) +QPlatformVulkanInstance *QEglFSIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const +{ + return qt_egl_device_integration()->createPlatformVulkanInstance(instance); +} +#endif + bool QEglFSIntegration::hasCapability(QPlatformIntegration::Capability cap) const { // We assume that devices will have more and not less capabilities @@ -283,7 +290,8 @@ enum ResourceType { NativeDisplay, XlibDisplay, WaylandDisplay, - EglSurface + EglSurface, + VkSurface }; static int resourceType(const QByteArray &key) @@ -296,7 +304,8 @@ static int resourceType(const QByteArray &key) QByteArrayLiteral("nativedisplay"), QByteArrayLiteral("display"), QByteArrayLiteral("server_wl_display"), - QByteArrayLiteral("eglsurface") + QByteArrayLiteral("eglsurface"), + QByteArrayLiteral("vksurface") }; const QByteArray *end = names + sizeof(names) / sizeof(names[0]); const QByteArray *result = std::find(names, end, key); @@ -307,7 +316,7 @@ static int resourceType(const QByteArray &key) void *QEglFSIntegration::nativeResourceForIntegration(const QByteArray &resource) { - void *result = 0; + void *result = nullptr; switch (resourceType(resource)) { case EglDisplay: @@ -329,7 +338,7 @@ void *QEglFSIntegration::nativeResourceForIntegration(const QByteArray &resource void *QEglFSIntegration::nativeResourceForScreen(const QByteArray &resource, QScreen *screen) { - void *result = 0; + void *result = nullptr; switch (resourceType(resource)) { case XlibDisplay: @@ -347,7 +356,7 @@ void *QEglFSIntegration::nativeResourceForScreen(const QByteArray &resource, QSc void *QEglFSIntegration::nativeResourceForWindow(const QByteArray &resource, QWindow *window) { - void *result = 0; + void *result = nullptr; switch (resourceType(resource)) { case EglDisplay: @@ -364,6 +373,12 @@ void *QEglFSIntegration::nativeResourceForWindow(const QByteArray &resource, QWi if (window && window->handle()) result = reinterpret_cast<void*>(static_cast<QEglFSWindow *>(window->handle())->surface()); break; +#if QT_CONFIG(vulkan) + case VkSurface: + if (window && window->handle() && window->surfaceType() == QSurface::VulkanSurface) + result = static_cast<QEglFSWindow *>(window->handle())->vulkanSurfacePtr(); + break; +#endif default: break; } @@ -374,7 +389,7 @@ void *QEglFSIntegration::nativeResourceForWindow(const QByteArray &resource, QWi #ifndef QT_NO_OPENGL void *QEglFSIntegration::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) { - void *result = 0; + void *result = nullptr; switch (resourceType(resource)) { case EglContext: @@ -402,7 +417,7 @@ static void *eglContextForContext(QOpenGLContext *context) QEglFSContext *handle = static_cast<QEglFSContext *>(context->handle()); if (!handle) - return 0; + return nullptr; return handle->eglContext(); } @@ -416,7 +431,7 @@ QPlatformNativeInterface::NativeResourceForContextFunction QEglFSIntegration::na #else Q_UNUSED(resource); #endif - return 0; + return nullptr; } QFunctionPointer QEglFSIntegration::platformFunction(const QByteArray &function) const diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h b/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h index 898b322834..b293651ce7 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h +++ b/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h @@ -86,6 +86,9 @@ public: QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override; QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override; #endif +#if QT_CONFIG(vulkan) + QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const override; +#endif bool hasCapability(QPlatformIntegration::Capability cap) const override; QPlatformNativeInterface *nativeInterface() const override; diff --git a/src/plugins/platforms/eglfs/api/qeglfsoffscreenwindow.cpp b/src/plugins/platforms/eglfs/api/qeglfsoffscreenwindow.cpp index 864271cd3a..c96e329816 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsoffscreenwindow.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfsoffscreenwindow.cpp @@ -67,7 +67,7 @@ QEglFSOffscreenWindow::QEglFSOffscreenWindow(EGLDisplay display, const QSurfaceF return; } EGLConfig config = q_configFromGLFormat(m_display, m_format); - m_surface = eglCreateWindowSurface(m_display, config, m_window, 0); + m_surface = eglCreateWindowSurface(m_display, config, m_window, nullptr); if (m_surface != EGL_NO_SURFACE) m_format = q_glFormatFromConfig(m_display, config); } diff --git a/src/plugins/platforms/eglfs/api/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/api/qeglfsscreen.cpp index 11b68c0589..8a8e8cd563 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsscreen.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfsscreen.cpp @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE QEglFSScreen::QEglFSScreen(EGLDisplay dpy) : m_dpy(dpy), m_surface(EGL_NO_SURFACE), - m_cursor(0) + m_cursor(nullptr) { m_cursor = qt_egl_device_integration()->createCursor(this); } @@ -164,7 +164,7 @@ void QEglFSScreen::handleCursorMove(const QPoint &pos) return; } - QWindow *enter = 0, *leave = 0; + QWindow *enter = nullptr, *leave = nullptr; for (int i = windows.count() - 1; i >= 0; --i) { QWindow *window = windows[i]->sourceWindow(); const QRect geom = window->geometry(); diff --git a/src/plugins/platforms/eglfs/api/qeglfswindow.cpp b/src/plugins/platforms/eglfs/api/qeglfswindow.cpp index 1fed182882..f7e116eb88 100644 --- a/src/plugins/platforms/eglfs/api/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfswindow.cpp @@ -61,13 +61,12 @@ QT_BEGIN_NAMESPACE QEglFSWindow::QEglFSWindow(QWindow *w) : QPlatformWindow(w), #ifndef QT_NO_OPENGL - m_backingStore(0), - m_rasterCompositingContext(0), + m_backingStore(nullptr), + m_rasterCompositingContext(nullptr), #endif m_winId(0), m_surface(EGL_NO_SURFACE), - m_window(0), - m_flags(0) + m_window(0) { } @@ -186,7 +185,7 @@ void QEglFSWindow::destroy() #endif } - m_flags = 0; + m_flags = { }; } void QEglFSWindow::invalidateSurface() @@ -208,7 +207,7 @@ void QEglFSWindow::resetSurface() m_format = q_glFormatFromConfig(display, m_config, platformFormat); const QSize surfaceSize = screen()->rawGeometry().size(); m_window = qt_egl_device_integration()->createNativeWindow(this, surfaceSize, m_format); - m_surface = eglCreateWindowSurface(display, m_config, m_window, NULL); + m_surface = eglCreateWindowSurface(display, m_config, m_window, nullptr); } void QEglFSWindow::setVisible(bool visible) @@ -338,7 +337,7 @@ const QPlatformTextureList *QEglFSWindow::textures() const if (m_backingStore) return m_backingStore->textures(); - return 0; + return nullptr; } void QEglFSWindow::endCompositing() diff --git a/src/plugins/platforms/eglfs/api/qeglfswindow_p.h b/src/plugins/platforms/eglfs/api/qeglfswindow_p.h index be2a0630d3..7bf74c25ee 100644 --- a/src/plugins/platforms/eglfs/api/qeglfswindow_p.h +++ b/src/plugins/platforms/eglfs/api/qeglfswindow_p.h @@ -64,6 +64,7 @@ QT_BEGIN_NAMESPACE class QOpenGLCompositorBackingStore; class QPlatformTextureList; + #ifndef QT_NO_OPENGL class Q_EGLFS_EXPORT QEglFSWindow : public QPlatformWindow, public QOpenGLCompositorWindow #else @@ -96,6 +97,9 @@ public: EGLNativeWindowType eglWindow() const; EGLSurface surface() const; QEglFSScreen *screen() const override; +#if QT_CONFIG(vulkan) + virtual void *vulkanSurfacePtr() { return nullptr; } +#endif bool hasNativeWindow() const { return m_flags.testFlag(HasNativeWindow); } diff --git a/src/plugins/platforms/eglfs/api/vulkan/qeglfsvulkaninstance.cpp b/src/plugins/platforms/eglfs/api/vulkan/qeglfsvulkaninstance.cpp new file mode 100644 index 0000000000..a75251ca5f --- /dev/null +++ b/src/plugins/platforms/eglfs/api/vulkan/qeglfsvulkaninstance.cpp @@ -0,0 +1,280 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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 "qeglfsvulkaninstance_p.h" +#include "qeglfswindow_p.h" +#include "qeglfshooks_p.h" +#include <QLoggingCategory> + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(qLcEglDevDebug) + +QEglFSVulkanInstance::QEglFSVulkanInstance(QVulkanInstance *instance) + : m_instance(instance) +{ + loadVulkanLibrary(QStringLiteral("vulkan")); +} + +void QEglFSVulkanInstance::createOrAdoptInstance() +{ + qCDebug(qLcEglDevDebug, "Creating Vulkan instance for VK_KHR_display"); + + const QByteArray extName = QByteArrayLiteral("VK_KHR_display"); + initInstance(m_instance, { extName }); + if (!m_vkInst) + return; + if (!enabledExtensions().contains(extName)) { + qWarning("Failed to enable VK_KHR_display extension"); + return; + } + +#if VK_KHR_display + m_getPhysicalDeviceDisplayPropertiesKHR = (PFN_vkGetPhysicalDeviceDisplayPropertiesKHR) + m_vkGetInstanceProcAddr(m_vkInst, "vkGetPhysicalDeviceDisplayPropertiesKHR"); + m_getDisplayModePropertiesKHR = (PFN_vkGetDisplayModePropertiesKHR) + m_vkGetInstanceProcAddr(m_vkInst, "vkGetDisplayModePropertiesKHR"); + m_getPhysicalDeviceDisplayPlanePropertiesKHR = (PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR) + m_vkGetInstanceProcAddr(m_vkInst, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR"); + + m_getDisplayPlaneSupportedDisplaysKHR = (PFN_vkGetDisplayPlaneSupportedDisplaysKHR) + m_vkGetInstanceProcAddr(m_vkInst, "vkGetDisplayPlaneSupportedDisplaysKHR"); + m_getDisplayPlaneCapabilitiesKHR = (PFN_vkGetDisplayPlaneCapabilitiesKHR) + m_vkGetInstanceProcAddr(m_vkInst, "vkGetDisplayPlaneCapabilitiesKHR"); + + m_createDisplayPlaneSurfaceKHR = (PFN_vkCreateDisplayPlaneSurfaceKHR) + m_vkGetInstanceProcAddr(m_vkInst, "vkCreateDisplayPlaneSurfaceKHR"); +#endif + + m_enumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices) + m_vkGetInstanceProcAddr(m_vkInst, "vkEnumeratePhysicalDevices"); + + // Use for first physical device, unless overridden by QT_VK_PHYSICAL_DEVICE_INDEX. + // This behavior matches what the Vulkan backend of QRhi would do. + + uint32_t physDevCount = 0; + m_enumeratePhysicalDevices(m_vkInst, &physDevCount, nullptr); + if (!physDevCount) { + qWarning("No physical devices"); + return; + } + QVarLengthArray<VkPhysicalDevice, 4> physDevs(physDevCount); + VkResult err = m_enumeratePhysicalDevices(m_vkInst, &physDevCount, physDevs.data()); + if (err != VK_SUCCESS || !physDevCount) { + qWarning("Failed to enumerate physical devices: %d", err); + return; + } + + if (qEnvironmentVariableIsSet("QT_VK_PHYSICAL_DEVICE_INDEX")) { + int requestedPhysDevIndex = qEnvironmentVariableIntValue("QT_VK_PHYSICAL_DEVICE_INDEX"); + if (requestedPhysDevIndex >= 0 && uint32_t(requestedPhysDevIndex) < physDevCount) + m_physDev = physDevs[requestedPhysDevIndex]; + } + + if (m_physDev == VK_NULL_HANDLE) + m_physDev = physDevs[0]; +} + +bool QEglFSVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + QWindow *window) +{ + Q_UNUSED(physicalDevice); + Q_UNUSED(queueFamilyIndex); + Q_UNUSED(window); + return true; +} + +VkSurfaceKHR QEglFSVulkanInstance::createSurface(QEglFSWindow *window) +{ +#if VK_KHR_display + qCDebug(qLcEglDevDebug, "Creating VkSurfaceKHR via VK_KHR_display for window %p", (void *) window); + + if (!m_physDev) { + qWarning("No physical device, cannot create surface"); + return VK_NULL_HANDLE; + } + + uint32_t displayCount = 0; + VkResult err = m_getPhysicalDeviceDisplayPropertiesKHR(m_physDev, &displayCount, nullptr); + if (err != VK_SUCCESS) { + qWarning("Failed to get display properties: %d", err); + return VK_NULL_HANDLE; + } + + qCDebug(qLcEglDevDebug, "Display count: %u", displayCount); + + QVarLengthArray<VkDisplayPropertiesKHR, 4> displayProps(displayCount); + m_getPhysicalDeviceDisplayPropertiesKHR(m_physDev, &displayCount, displayProps.data()); + + VkDisplayKHR display = VK_NULL_HANDLE; + VkDisplayModeKHR displayMode = VK_NULL_HANDLE; + uint32_t width = 0; + uint32_t height = 0; + + for (uint32_t i = 0; i < displayCount; ++i) { + const VkDisplayPropertiesKHR &disp(displayProps[i]); + qCDebug(qLcEglDevDebug, "Display #%u:\n display: %p\n name: %s\n dimensions: %ux%u\n resolution: %ux%u", + i, (void *) disp.display, disp.displayName, + disp.physicalDimensions.width, disp.physicalDimensions.height, + disp.physicalResolution.width, disp.physicalResolution.height); + + // Just pick the first display and the first mode. + if (i == 0) + display = disp.display; + + uint32_t modeCount = 0; + if (m_getDisplayModePropertiesKHR(m_physDev, disp.display, &modeCount, nullptr) != VK_SUCCESS) { + qWarning("Failed to get modes for display"); + continue; + } + QVarLengthArray<VkDisplayModePropertiesKHR, 16> modeProps(modeCount); + m_getDisplayModePropertiesKHR(m_physDev, disp.display, &modeCount, modeProps.data()); + for (uint32_t j = 0; j < modeCount; ++j) { + const VkDisplayModePropertiesKHR &mode(modeProps[j]); + qCDebug(qLcEglDevDebug, " Mode #%u:\n mode: %p\n visibleRegion: %ux%u\n refreshRate: %u", + j, (void *) mode.displayMode, + mode.parameters.visibleRegion.width, mode.parameters.visibleRegion.height, + mode.parameters.refreshRate); + if (j == 0) { + displayMode = mode.displayMode; + width = mode.parameters.visibleRegion.width; + height = mode.parameters.visibleRegion.height; + } + } + } + + if (display == VK_NULL_HANDLE || displayMode == VK_NULL_HANDLE) { + qWarning("Failed to choose display and mode"); + return VK_NULL_HANDLE; + } + uint32_t planeCount = 0; + err = m_getPhysicalDeviceDisplayPlanePropertiesKHR(m_physDev, &planeCount, nullptr); + if (err != VK_SUCCESS) { + qWarning("Failed to get plane properties: %d", err); + return VK_NULL_HANDLE; + } + + qCDebug(qLcEglDevDebug, "Plane count: %u", planeCount); + + QVarLengthArray<VkDisplayPlanePropertiesKHR, 4> planeProps(planeCount); + m_getPhysicalDeviceDisplayPlanePropertiesKHR(m_physDev, &planeCount, planeProps.data()); + + uint32_t planeIndex = UINT_MAX; + for (uint32_t i = 0; i < planeCount; ++i) { + uint32_t supportedDisplayCount = 0; + err = m_getDisplayPlaneSupportedDisplaysKHR(m_physDev, i, &supportedDisplayCount, nullptr); + if (err != VK_SUCCESS) { + qWarning("Failed to query supported displays for plane: %d", err); + return VK_NULL_HANDLE; + } + + QVarLengthArray<VkDisplayKHR, 4> supportedDisplays(supportedDisplayCount); + m_getDisplayPlaneSupportedDisplaysKHR(m_physDev, i, &supportedDisplayCount, supportedDisplays.data()); + qCDebug(qLcEglDevDebug, "Plane #%u supports %u displays, currently bound to display %p", + i, supportedDisplayCount, (void *) planeProps[i].currentDisplay); + + VkDisplayPlaneCapabilitiesKHR caps; + err = m_getDisplayPlaneCapabilitiesKHR(m_physDev, displayMode, i, &caps); + if (err != VK_SUCCESS) { + qWarning("Failed to query plane capabilities: %d", err); + return VK_NULL_HANDLE; + } + + qCDebug(qLcEglDevDebug, " supportedAlpha: %d (1=no, 2=global, 4=per pixel, 8=per pixel premul)\n" + " minSrc=%d, %d %ux%u\n" + " maxSrc=%d, %d %ux%u\n" + " minDst=%d, %d %ux%u\n" + " maxDst=%d, %d %ux%u", + int(caps.supportedAlpha), + caps.minSrcPosition.x, caps.minSrcPosition.y, caps.minSrcExtent.width, caps.minSrcExtent.height, + caps.maxSrcPosition.x, caps.maxSrcPosition.y, caps.maxSrcExtent.width, caps.maxSrcExtent.height, + caps.minDstPosition.x, caps.minDstPosition.y, caps.minDstExtent.width, caps.minDstExtent.height, + caps.maxDstPosition.x, caps.maxDstPosition.y, caps.maxDstExtent.width, caps.maxDstExtent.height); + + // if the plane is not in use and supports our chosen display, use that plane + if (supportedDisplays.contains(display) + && (planeProps[i].currentDisplay == VK_NULL_HANDLE || planeProps[i].currentDisplay == display)) + { + planeIndex = i; + } + } + + if (planeIndex == UINT_MAX) { + qWarning("Failed to find a suitable plane"); + return VK_NULL_HANDLE; + } + + qCDebug(qLcEglDevDebug, "Using plane #%u", planeIndex); + + VkDisplaySurfaceCreateInfoKHR surfaceCreateInfo = {}; + surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR; + surfaceCreateInfo.displayMode = displayMode; + surfaceCreateInfo.planeIndex = planeIndex; + surfaceCreateInfo.planeStackIndex = planeProps[planeIndex].currentStackIndex; + surfaceCreateInfo.transform = VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR; + surfaceCreateInfo.globalAlpha = 1.0f; + surfaceCreateInfo.alphaMode = VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR; + surfaceCreateInfo.imageExtent = { width, height }; + + VkSurfaceKHR surface = VK_NULL_HANDLE; + err = m_createDisplayPlaneSurfaceKHR(m_vkInst, &surfaceCreateInfo, nullptr, &surface); + if (err != VK_SUCCESS || surface == VK_NULL_HANDLE) { + qWarning("Failed to create surface: %d", err); + return VK_NULL_HANDLE; + } + + qCDebug(qLcEglDevDebug, "Created surface %p", (void *) surface); + + return surface; + +#else + Q_UNUSED(window); + qWarning("VK_KHR_display support was not compiled in, cannot create surface"); + return VK_NULL_HANDLE; +#endif +} + +void QEglFSVulkanInstance::presentAboutToBeQueued(QWindow *window) +{ + // support QT_QPA_EGLFS_FORCEVSYNC (i.MX8 with eglfs_viv) + qt_egl_device_integration()->waitForVSync(window->handle()); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qt_mac_p.h b/src/plugins/platforms/eglfs/api/vulkan/qeglfsvulkaninstance_p.h index fdcf3bcdd3..9d6d47f439 100644 --- a/src/plugins/platforms/cocoa/qt_mac_p.h +++ b/src/plugins/platforms/eglfs/api/vulkan/qeglfsvulkaninstance_p.h @@ -1,9 +1,9 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** -** This file is part of the QtGui module of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#ifndef QT_MAC_P_H -#define QT_MAC_P_H +#ifndef QEGLFSVULKANINSTANCE_H +#define QEGLFSVULKANINSTANCE_H // // W A R N I N G @@ -51,77 +51,38 @@ // We mean it. // -#ifdef __OBJC__ -#include <AppKit/AppKit.h> -#include <objc/runtime.h> -#endif - -#include "qmacdefines_mac.h" - -#include <CoreServices/CoreServices.h> - -#include "QtCore/qglobal.h" -#include "QtCore/qvariant.h" -#include "QtCore/qmimedata.h" -#include "QtCore/qpointer.h" -#include "QtCore/qloggingcategory.h" -#include "private/qcore_mac_p.h" - - -#include "QtGui/qpainter.h" +#include "qeglfsglobal_p.h" +#include <QtVulkanSupport/private/qbasicvulkanplatforminstance_p.h> QT_BEGIN_NAMESPACE -class QWidget; -class QDragMoveEvent; -// Simple class to manage short-lived regions -class QMacSmartQuickDrawRegion +class QEglFSWindow; + +class Q_EGLFS_EXPORT QEglFSVulkanInstance : public QBasicPlatformVulkanInstance { - RgnHandle qdRgn; - Q_DISABLE_COPY(QMacSmartQuickDrawRegion) public: - explicit QMacSmartQuickDrawRegion(RgnHandle rgn) : qdRgn(rgn) {} - ~QMacSmartQuickDrawRegion() { - extern void qt_mac_dispose_rgn(RgnHandle); // qregion_mac.cpp - qt_mac_dispose_rgn(qdRgn); - } - operator RgnHandle() { - return qdRgn; - } -}; - -class QMacInternalPasteboardMime; -class QMimeData; - - -extern QPaintDevice *qt_mac_safe_pdev; //qapplication_mac.cpp - -extern OSWindowRef qt_mac_window_for(const QWidget*); //qwidget_mac.mm -extern OSViewRef qt_mac_nativeview_for(const QWidget *); //qwidget_mac.mm -extern QPoint qt_mac_nativeMapFromParent(const QWidget *child, const QPoint &pt); //qwidget_mac.mm - -#ifdef check -# undef check + QEglFSVulkanInstance(QVulkanInstance *instance); + + void createOrAdoptInstance() override; + bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) override; + void presentAboutToBeQueued(QWindow *window) override; + + VkSurfaceKHR createSurface(QEglFSWindow *window); + +private: + QVulkanInstance *m_instance; + VkPhysicalDevice m_physDev = VK_NULL_HANDLE; + PFN_vkEnumeratePhysicalDevices m_enumeratePhysicalDevices = nullptr; +#if VK_KHR_display + PFN_vkGetPhysicalDeviceDisplayPropertiesKHR m_getPhysicalDeviceDisplayPropertiesKHR = nullptr; + PFN_vkGetDisplayModePropertiesKHR m_getDisplayModePropertiesKHR = nullptr; + PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR m_getPhysicalDeviceDisplayPlanePropertiesKHR = nullptr; + PFN_vkGetDisplayPlaneSupportedDisplaysKHR m_getDisplayPlaneSupportedDisplaysKHR = nullptr; + PFN_vkGetDisplayPlaneCapabilitiesKHR m_getDisplayPlaneCapabilitiesKHR = nullptr; + PFN_vkCreateDisplayPlaneSurfaceKHR m_createDisplayPlaneSurfaceKHR = nullptr; #endif - -struct QMacDndAnswerRecord { - QRect rect; - Qt::KeyboardModifiers modifiers; - Qt::MouseButtons buttons; - Qt::DropAction lastAction; - unsigned int lastOperation; - void clear() { - rect = QRect(); - modifiers = Qt::NoModifier; - buttons = Qt::NoButton; - lastAction = Qt::IgnoreAction; - lastOperation = 0; - } }; -extern QMacDndAnswerRecord qt_mac_dnd_answer_rec; -void qt_mac_copy_answer_rect(const QDragMoveEvent &event); -bool qt_mac_mouse_inside_answer_rect(QPoint mouse); QT_END_NAMESPACE -#endif // QT_MAC_P_H +#endif diff --git a/src/plugins/platforms/eglfs/api/vulkan/qeglfsvulkanwindow.cpp b/src/plugins/platforms/eglfs/api/vulkan/qeglfsvulkanwindow.cpp new file mode 100644 index 0000000000..ae41ca00b6 --- /dev/null +++ b/src/plugins/platforms/eglfs/api/vulkan/qeglfsvulkanwindow.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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 "qeglfsvulkanwindow_p.h" + +QT_BEGIN_NAMESPACE + +QEglFSVulkanWindow::QEglFSVulkanWindow(QWindow *window) + : QEglFSWindow(window), + m_surface(VK_NULL_HANDLE) +{ +} + +QEglFSVulkanWindow::~QEglFSVulkanWindow() +{ + if (m_surface) { + QVulkanInstance *inst = window()->vulkanInstance(); + if (inst) + static_cast<QEglFSVulkanInstance *>(inst->handle())->destroySurface(m_surface); + } +} + +void *QEglFSVulkanWindow::vulkanSurfacePtr() +{ + if (m_surface) + return &m_surface; + + QVulkanInstance *inst = window()->vulkanInstance(); + if (!inst) { + qWarning("Attempted to create Vulkan surface without an instance; was QWindow::setVulkanInstance() called?"); + return nullptr; + } + QEglFSVulkanInstance *eglfsInst = static_cast<QEglFSVulkanInstance *>(inst->handle()); + m_surface = eglfsInst->createSurface(this); + + return &m_surface; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/api/vulkan/qeglfsvulkanwindow_p.h b/src/plugins/platforms/eglfs/api/vulkan/qeglfsvulkanwindow_p.h new file mode 100644 index 0000000000..492fb41ca4 --- /dev/null +++ b/src/plugins/platforms/eglfs/api/vulkan/qeglfsvulkanwindow_p.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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 QEGLFSVULKANWINDOW_H +#define QEGLFSVULKANWINDOW_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 "qeglfsglobal_p.h" +#include "qeglfswindow_p.h" +#include "qeglfsvulkaninstance_p.h" + +QT_BEGIN_NAMESPACE + +class Q_EGLFS_EXPORT QEglFSVulkanWindow : public QEglFSWindow +{ +public: + QEglFSVulkanWindow(QWindow *window); + ~QEglFSVulkanWindow(); + + void *vulkanSurfacePtr() override; + +private: + VkSurfaceKHR m_surface; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp index 4d0cf0c47e..dc98cdce4b 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp @@ -69,7 +69,7 @@ QEglFSKmsGbmCursor::QEglFSKmsGbmCursor(QEglFSKmsGbmScreen *screen) : m_screen(screen) , m_cursorSize(64, 64) // 64x64 is the old standard size, we now try to query the real size below , m_bo(nullptr) - , m_cursorImage(0, 0, 0, 0, 0, 0) + , m_cursorImage(nullptr, nullptr, 0, 0, 0, 0) , m_state(CursorPendingVisible) , m_deviceListener(nullptr) { @@ -102,7 +102,7 @@ QEglFSKmsGbmCursor::QEglFSKmsGbmCursor(QEglFSKmsGbmScreen *screen) #ifndef QT_NO_CURSOR QCursor cursor(Qt::ArrowCursor); - changeCursor(&cursor, 0); + changeCursor(&cursor, nullptr); #endif setPos(QPoint(0, 0)); } @@ -214,7 +214,8 @@ void QEglFSKmsGbmCursor::changeCursor(QCursor *windowCursor, QWindow *window) Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) { QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen); - + if (kmsScreen->isCursorOutOfRange()) + continue; int status = drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, handle, m_cursorSize.width(), m_cursorSize.height()); if (status != 0) @@ -232,17 +233,36 @@ void QEglFSKmsGbmCursor::setPos(const QPoint &pos) { Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) { QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen); - QPoint origin = kmsScreen->geometry().topLeft(); - QPoint localPos = pos - origin; - QPoint adjustedPos = localPos - m_cursorImage.hotspot(); - - int ret = drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, adjustedPos.x(), adjustedPos.y()); - if (ret == 0) - m_pos = pos; - else - qWarning("Failed to move cursor on screen %s: %d", kmsScreen->name().toLatin1().constData(), ret); - - kmsScreen->handleCursorMove(pos); + const QRect screenGeom = kmsScreen->geometry(); + const QPoint origin = screenGeom.topLeft(); + const QPoint localPos = pos - origin; + const QPoint adjustedLocalPos = localPos - m_cursorImage.hotspot(); + + if (localPos.x() < 0 || localPos.y() < 0 + || localPos.x() >= screenGeom.width() || localPos.y() >= screenGeom.height()) + { + if (!kmsScreen->isCursorOutOfRange()) { + kmsScreen->setCursorOutOfRange(true); + drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0); + } + } else { + int ret; + if (kmsScreen->isCursorOutOfRange()) { + kmsScreen->setCursorOutOfRange(false); + uint32_t handle = gbm_bo_get_handle(m_bo).u32; + ret = drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, + handle, m_cursorSize.width(), m_cursorSize.height()); + } else { + ret = drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, + adjustedLocalPos.x(), adjustedLocalPos.y()); + } + if (ret == 0) + m_pos = pos; + else + qWarning("Failed to move cursor on screen %s: %d", kmsScreen->name().toLatin1().constData(), ret); + + kmsScreen->handleCursorMove(pos); + } } } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.h index d47b579238..5d2dfedba2 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.h @@ -85,6 +85,8 @@ public: void updateMouseStatus(); + void reevaluateVisibilityForScreens() { setPos(pos()); } + private: void initCursorAtlas(); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp index 20127ae7f7..503419cf91 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp @@ -83,6 +83,8 @@ bool QEglFSKmsGbmDevice::open() setFd(fd); + m_eventReader.create(this); + return true; } @@ -90,6 +92,8 @@ void QEglFSKmsGbmDevice::close() { // Note: screens are gone at this stage. + m_eventReader.destroy(); + if (m_gbm_device) { gbm_device_destroy(m_gbm_device); m_gbm_device = nullptr; @@ -155,4 +159,14 @@ void QEglFSKmsGbmDevice::registerScreenCloning(QPlatformScreen *screen, gbmScreen->initCloning(screenThisScreenClones, screensCloningThisScreen); } +void QEglFSKmsGbmDevice::registerScreen(QPlatformScreen *screen, + bool isPrimary, + const QPoint &virtualPos, + const QList<QPlatformScreen *> &virtualSiblings) +{ + QEglFSKmsDevice::registerScreen(screen, isPrimary, virtualPos, virtualSiblings); + if (screenConfig()->hwCursor() && m_globalCursor) + m_globalCursor->reevaluateVisibilityForScreens(); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h index 518e2ce58b..f1476f8ffa 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h @@ -70,6 +70,10 @@ public: void registerScreenCloning(QPlatformScreen *screen, QPlatformScreen *screenThisScreenClones, const QVector<QPlatformScreen *> &screensCloningThisScreen) override; + void registerScreen(QPlatformScreen *screen, + bool isPrimary, + const QPoint &virtualPos, + const QList<QPlatformScreen *> &virtualSiblings) override; private: Q_DISABLE_COPY(QEglFSKmsGbmDevice) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp index f154520669..caa1187b40 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp @@ -54,8 +54,6 @@ QT_BEGIN_NAMESPACE -QMutex QEglFSKmsGbmScreen::m_waitForFlipMutex; - QEglFSKmsGbmIntegration::QEglFSKmsGbmIntegration() { qCDebug(qLcEglfsKmsDebug, "New DRM/KMS via GBM integration created"); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp index 16dbfe1522..6f5c3b6953 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp @@ -110,7 +110,7 @@ QEglFSKmsGbmScreen::FrameBuffer *QEglFSKmsGbmScreen::framebufferForBufferObject( return fb.take(); } -QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QKmsDevice *device, const QKmsOutput &output, bool headless) +QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QEglFSKmsDevice *device, const QKmsOutput &output, bool headless) : QEglFSKmsScreen(device, output, headless) , m_gbm_surface(nullptr) , m_gbm_bo_current(nullptr) @@ -243,7 +243,7 @@ void QEglFSKmsGbmScreen::ensureModeSet(uint32_t fb) if (device()->hasAtomicSupport()) { #if QT_CONFIG(drm_atomic) - drmModeAtomicReq *request = device()->atomic_request(); + drmModeAtomicReq *request = device()->threadLocalAtomicRequest(); if (request) { drmModeAtomicAddProperty(request, op.connector_id, op.crtcIdPropertyId, op.crtc_id); drmModeAtomicAddProperty(request, op.crtc_id, op.modeIdPropertyId, op.mode_blob_id); @@ -276,19 +276,15 @@ void QEglFSKmsGbmScreen::waitForFlip() if (!m_gbm_bo_next) return; - QMutexLocker lock(&m_waitForFlipMutex); - while (m_gbm_bo_next) { - drmEventContext drmEvent; - memset(&drmEvent, 0, sizeof(drmEvent)); - drmEvent.version = 2; - drmEvent.vblank_handler = nullptr; - drmEvent.page_flip_handler = pageFlipHandler; - drmHandleEvent(device()->fd(), &drmEvent); - } + m_flipMutex.lock(); + device()->eventReader()->startWaitFlip(this, &m_flipMutex, &m_flipCond); + m_flipCond.wait(&m_flipMutex); + m_flipMutex.unlock(); + + flipFinished(); #if QT_CONFIG(drm_atomic) - if (device()->hasAtomicSupport()) - device()->atomicReset(); + device()->threadLocalAtomicReset(); #endif } @@ -324,16 +320,16 @@ void QEglFSKmsGbmScreen::flip() if (device()->hasAtomicSupport()) { #if QT_CONFIG(drm_atomic) - drmModeAtomicReq *request = device()->atomic_request(); + drmModeAtomicReq *request = device()->threadLocalAtomicRequest(); if (request) { drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->framebufferPropertyId, fb->fb); drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcPropertyId, op.crtc_id); drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->srcwidthPropertyId, - output().size.width() << 16); + op.size.width() << 16); drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->srcXPropertyId, 0); drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->srcYPropertyId, 0); drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->srcheightPropertyId, - output().size.height() << 16); + op.size.height() << 16); drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcXPropertyId, 0); drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcYPropertyId, 0); drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcwidthPropertyId, @@ -371,7 +367,7 @@ void QEglFSKmsGbmScreen::flip() if (device()->hasAtomicSupport()) { #if QT_CONFIG(drm_atomic) - drmModeAtomicReq *request = device()->atomic_request(); + drmModeAtomicReq *request = device()->threadLocalAtomicRequest(); if (request) { drmModeAtomicAddProperty(request, d.screen->output().eglfs_plane->id, d.screen->output().eglfs_plane->framebufferPropertyId, fb->fb); @@ -394,22 +390,10 @@ void QEglFSKmsGbmScreen::flip() } #if QT_CONFIG(drm_atomic) - if (device()->hasAtomicSupport()) - device()->atomicCommit(this); + device()->threadLocalAtomicCommit(this); #endif } -void QEglFSKmsGbmScreen::pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) -{ - Q_UNUSED(fd); - Q_UNUSED(sequence); - Q_UNUSED(tv_sec); - Q_UNUSED(tv_usec); - - QEglFSKmsGbmScreen *screen = static_cast<QEglFSKmsGbmScreen *>(user_data); - screen->flipFinished(); -} - void QEglFSKmsGbmScreen::flipFinished() { if (m_cloneSource) { diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h index b94f44b7b1..69feeee703 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h @@ -43,7 +43,8 @@ #define QEGLFSKMSGBMSCREEN_H #include "qeglfskmsscreen.h" -#include <QtCore/QMutex> +#include <QMutex> +#include <QWaitCondition> #include <gbm.h> @@ -54,7 +55,7 @@ class QEglFSKmsGbmCursor; class QEglFSKmsGbmScreen : public QEglFSKmsScreen { public: - QEglFSKmsGbmScreen(QKmsDevice *device, const QKmsOutput &output, bool headless); + QEglFSKmsGbmScreen(QEglFSKmsDevice *device, const QKmsOutput &output, bool headless); ~QEglFSKmsGbmScreen(); QPlatformCursor *cursor() const override; @@ -75,18 +76,15 @@ private: void cloneDestFlipFinished(QEglFSKmsGbmScreen *cloneDestScreen); void updateFlipStatus(); - static void pageFlipHandler(int fd, - unsigned int sequence, - unsigned int tv_sec, - unsigned int tv_usec, - void *user_data); - gbm_surface *m_gbm_surface; gbm_bo *m_gbm_bo_current; gbm_bo *m_gbm_bo_next; bool m_flipPending; + QMutex m_flipMutex; + QWaitCondition m_flipCond; + QScopedPointer<QEglFSKmsGbmCursor> m_cursor; struct FrameBuffer { @@ -101,8 +99,6 @@ private: bool cloneFlipPending = false; }; QVector<CloneDestination> m_cloneDests; - - static QMutex m_waitForFlipMutex; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp index 1626c86239..5a62e437c4 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp @@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) -QEglFSKmsEglDeviceScreen::QEglFSKmsEglDeviceScreen(QKmsDevice *device, const QKmsOutput &output) +QEglFSKmsEglDeviceScreen::QEglFSKmsEglDeviceScreen(QEglFSKmsDevice *device, const QKmsOutput &output) : QEglFSKmsScreen(device, output) { } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h index 5efe35f8b3..961398ba3e 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h @@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE class QEglFSKmsEglDeviceScreen : public QEglFSKmsScreen { public: - QEglFSKmsEglDeviceScreen(QKmsDevice *device, const QKmsOutput &output); + QEglFSKmsEglDeviceScreen(QEglFSKmsDevice *device, const QKmsOutput &output); ~QEglFSKmsEglDeviceScreen(); QPlatformCursor *cursor() const override; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro index 40806b6a9b..e51903ed96 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro @@ -14,9 +14,11 @@ CONFIG += egl SOURCES += $$PWD/qeglfskmsintegration.cpp \ $$PWD/qeglfskmsdevice.cpp \ - $$PWD/qeglfskmsscreen.cpp + $$PWD/qeglfskmsscreen.cpp \ + $$PWD/qeglfskmseventreader.cpp HEADERS += $$PWD/qeglfskmsintegration.h \ $$PWD/qeglfskmsdevice.h \ $$PWD/qeglfskmsscreen.h \ - $$PWD/qeglfskmshelpers.h + $$PWD/qeglfskmshelpers.h \ + $$PWD/qeglfskmseventreader.h diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h index fc83a620d9..34908aa60f 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h @@ -42,6 +42,7 @@ #define QEGLFSKMSDEVICE_H #include "private/qeglfsglobal_p.h" +#include "qeglfskmseventreader.h" #include <QtKmsSupport/private/qkmsdevice_p.h> QT_BEGIN_NAMESPACE @@ -55,6 +56,11 @@ public: bool isPrimary, const QPoint &virtualPos, const QList<QPlatformScreen *> &virtualSiblings) override; + + QEglFSKmsEventReader *eventReader() { return &m_eventReader; } + +protected: + QEglFSKmsEventReader m_eventReader; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp new file mode 100644 index 0000000000..645a0ae2e9 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp @@ -0,0 +1,218 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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 "qeglfskmseventreader.h" +#include "qeglfskmsdevice.h" +#include <QSocketNotifier> +#include <QCoreApplication> +#include <QLoggingCategory> + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) + +static void pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) +{ + Q_UNUSED(fd); + Q_UNUSED(sequence); + Q_UNUSED(tv_sec); + Q_UNUSED(tv_usec); + + QEglFSKmsEventReaderThread *t = static_cast<QEglFSKmsEventReaderThread *>(QThread::currentThread()); + t->eventHost()->handlePageFlipCompleted(user_data); +} + +class RegisterWaitFlipEvent : public QEvent +{ +public: + static const QEvent::Type TYPE = QEvent::Type(QEvent::User + 1); + RegisterWaitFlipEvent(void *key, QMutex *mutex, QWaitCondition *cond) + : QEvent(TYPE), key(key), mutex(mutex), cond(cond) + { } + void *key; + QMutex *mutex; + QWaitCondition *cond; +}; + +bool QEglFSKmsEventHost::event(QEvent *event) +{ + if (event->type() == RegisterWaitFlipEvent::TYPE) { + RegisterWaitFlipEvent *e = static_cast<RegisterWaitFlipEvent *>(event); + PendingFlipWait *p = &pendingFlipWaits[0]; + PendingFlipWait *end = p + MAX_FLIPS; + while (p < end) { + if (!p->key) { + p->key = e->key; + p->mutex = e->mutex; + p->cond = e->cond; + updateStatus(); + return true; + } + ++p; + } + qWarning("Cannot queue page flip wait (more than %d screens?)", MAX_FLIPS); + e->mutex->lock(); + e->cond->wakeOne(); + e->mutex->unlock(); + return true; + } + return QObject::event(event); +} + +void QEglFSKmsEventHost::updateStatus() +{ + void **begin = &completedFlips[0]; + void **end = begin + MAX_FLIPS; + + for (int i = 0; i < MAX_FLIPS; ++i) { + PendingFlipWait *w = pendingFlipWaits + i; + if (!w->key) + continue; + + void **p = begin; + while (p < end) { + if (*p == w->key) { + *p = nullptr; + w->key = nullptr; + w->mutex->lock(); + w->cond->wakeOne(); + w->mutex->unlock(); + return; + } + ++p; + } + } +} + +void QEglFSKmsEventHost::handlePageFlipCompleted(void *key) +{ + void **begin = &completedFlips[0]; + void **end = begin + MAX_FLIPS; + void **p = begin; + while (p < end) { + if (*p == key) { + updateStatus(); + return; + } + ++p; + } + p = begin; + while (p < end) { + if (!*p) { + *p = key; + updateStatus(); + return; + } + ++p; + } + qWarning("Cannot store page flip status (more than %d screens?)", MAX_FLIPS); +} + +void QEglFSKmsEventReaderThread::run() +{ + qCDebug(qLcEglfsKmsDebug, "Event reader thread: entering event loop"); + + QSocketNotifier notifier(m_fd, QSocketNotifier::Read); + QObject::connect(¬ifier, &QSocketNotifier::activated, ¬ifier, [this] { + drmEventContext drmEvent; + memset(&drmEvent, 0, sizeof(drmEvent)); + drmEvent.version = 2; + drmEvent.vblank_handler = nullptr; + drmEvent.page_flip_handler = pageFlipHandler; + drmHandleEvent(m_fd, &drmEvent); + }); + + exec(); + + m_ev.moveToThread(thread()); // move back to the thread where m_ev was created + + qCDebug(qLcEglfsKmsDebug, "Event reader thread: event loop stopped"); +} + +QEglFSKmsEventReader::~QEglFSKmsEventReader() +{ + destroy(); +} + +void QEglFSKmsEventReader::create(QEglFSKmsDevice *device) +{ + destroy(); + + if (!device) + return; + + m_device = device; + + qCDebug(qLcEglfsKmsDebug, "Initalizing event reader for device %p fd %d", + m_device, m_device->fd()); + + m_thread = new QEglFSKmsEventReaderThread(m_device->fd()); + m_thread->start(); + + // Change thread affinity for the event host, so that postEvent() + // goes through the event reader thread's event loop for that object. + m_thread->eventHost()->moveToThread(m_thread); +} + +void QEglFSKmsEventReader::destroy() +{ + if (!m_device) + return; + + qCDebug(qLcEglfsKmsDebug, "Stopping event reader for device %p", m_device); + + if (m_thread) { + m_thread->quit(); + m_thread->wait(); + delete m_thread; + m_thread = nullptr; + } + + m_device = nullptr; +} + +void QEglFSKmsEventReader::startWaitFlip(void *key, QMutex *mutex, QWaitCondition *cond) +{ + if (m_thread) { + QCoreApplication::postEvent(m_thread->eventHost(), + new RegisterWaitFlipEvent(key, mutex, cond)); + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.h new file mode 100644 index 0000000000..4aa285b0fe --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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 QEGLFSKKMSEVENTREADER_H +#define QEGLFSKKMSEVENTREADER_H + +#include "private/qeglfsglobal_p.h" +#include <QObject> +#include <QThread> +#include <QMutex> +#include <QWaitCondition> + +QT_BEGIN_NAMESPACE + +class QEglFSKmsDevice; + +struct QEglFSKmsEventHost : public QObject +{ + struct PendingFlipWait { + void *key; + QMutex *mutex; + QWaitCondition *cond; + }; + + static const int MAX_FLIPS = 32; + void *completedFlips[MAX_FLIPS] = {}; + QEglFSKmsEventHost::PendingFlipWait pendingFlipWaits[MAX_FLIPS] = {}; + + bool event(QEvent *event) override; + void updateStatus(); + void handlePageFlipCompleted(void *key); +}; + +class QEglFSKmsEventReaderThread : public QThread +{ +public: + QEglFSKmsEventReaderThread(int fd) : m_fd(fd) { } + void run() override; + QEglFSKmsEventHost *eventHost() { return &m_ev; } + +private: + int m_fd; + QEglFSKmsEventHost m_ev; +}; + +class Q_EGLFS_EXPORT QEglFSKmsEventReader +{ +public: + ~QEglFSKmsEventReader(); + + void create(QEglFSKmsDevice *device); + void destroy(); + + void startWaitFlip(void *key, QMutex *mutex, QWaitCondition *cond); + +private: + QEglFSKmsDevice *m_device = nullptr; + QEglFSKmsEventReaderThread *m_thread = nullptr; +}; + +QT_END_NAMESPACE + +#endif // QEGLFSKKMSEVENTREADER_H diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp index a6aac61506..28b6b7df63 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp @@ -140,7 +140,7 @@ void *QEglFSKmsIntegration::nativeResourceForIntegration(const QByteArray &name) #if QT_CONFIG(drm_atomic) if (name == QByteArrayLiteral("dri_atomic_request") && m_device) - return (void *) (qintptr) m_device->atomic_request(); + return (void *) (qintptr) m_device->threadLocalAtomicRequest(); #endif return nullptr; } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp index e5354d97bd..959f17eba3 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qeglfskmsscreen.h" +#include "qeglfskmsdevice.h" #include "qeglfsintegration_p.h" #include <QtCore/QLoggingCategory> @@ -68,10 +69,11 @@ private: QEglFSKmsScreen *m_screen; }; -QEglFSKmsScreen::QEglFSKmsScreen(QKmsDevice *device, const QKmsOutput &output, bool headless) +QEglFSKmsScreen::QEglFSKmsScreen(QEglFSKmsDevice *device, const QKmsOutput &output, bool headless) : QEglFSScreen(static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration())->display()) , m_device(device) , m_output(output) + , m_cursorOutOfRange(false) , m_powerState(PowerStateOn) , m_interruptHandler(new QEglFSKmsInterruptHandler(this)) , m_headless(headless) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h index 7f395aacb7..a5c8f5b4e8 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h @@ -51,12 +51,13 @@ QT_BEGIN_NAMESPACE +class QEglFSKmsDevice; class QEglFSKmsInterruptHandler; class Q_EGLFS_EXPORT QEglFSKmsScreen : public QEglFSScreen { public: - QEglFSKmsScreen(QKmsDevice *device, const QKmsOutput &output, bool headless = false); + QEglFSKmsScreen(QEglFSKmsDevice *device, const QKmsOutput &output, bool headless = false); ~QEglFSKmsScreen(); void setVirtualPosition(const QPoint &pos); @@ -87,7 +88,7 @@ public: int currentMode() const override; int preferredMode() const override; - QKmsDevice *device() const { return m_device; } + QEglFSKmsDevice *device() const { return m_device; } virtual void waitForFlip(); @@ -99,12 +100,16 @@ public: QPlatformScreen::PowerState powerState() const override; void setPowerState(QPlatformScreen::PowerState state) override; + bool isCursorOutOfRange() const { return m_cursorOutOfRange; } + void setCursorOutOfRange(bool b) { m_cursorOutOfRange = b; } + protected: - QKmsDevice *m_device; + QEglFSKmsDevice *m_device; QKmsOutput m_output; QEdidParser m_edid; QPoint m_pos; + bool m_cursorOutOfRange; QList<QPlatformScreen *> m_siblings; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.cpp index 475d9d55dd..c255bc84b7 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.cpp @@ -99,7 +99,7 @@ QEglFSKmsVsp2Screen::DmaBuffer *QEglFSKmsVsp2Screen::dmaBufferForGbmBuffer(gbm_b return fb.take(); } -QEglFSKmsVsp2Screen::QEglFSKmsVsp2Screen(QKmsDevice *device, const QKmsOutput &output) +QEglFSKmsVsp2Screen::QEglFSKmsVsp2Screen(QEglFSKmsDevice *device, const QKmsOutput &output) : QEglFSKmsScreen(device, output) , m_blender(new Blender(this)) { diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.h index 7618510333..378786643d 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.h @@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE class QEglFSKmsVsp2Screen : public QEglFSKmsScreen { public: - QEglFSKmsVsp2Screen(QKmsDevice *device, const QKmsOutput &output); + QEglFSKmsVsp2Screen(QEglFSKmsDevice *device, const QKmsOutput &output); gbm_surface *createSurface(); void resetSurface(); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp index 2fc076ad0c..5e1d28a353 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp @@ -41,6 +41,11 @@ #include <EGL/eglvivante.h> #include <QDebug> +#if QT_CONFIG(vulkan) +#include "private/qeglfsvulkaninstance_p.h" +#include "private/qeglfsvulkanwindow_p.h" +#endif + #ifdef Q_OS_INTEGRITY extern "C" void VivanteInit(void); #endif @@ -97,4 +102,20 @@ void QEglFSVivIntegration::destroyNativeWindow(EGLNativeWindowType window) fbDestroyWindow(window); } +#if QT_CONFIG(vulkan) + +QEglFSWindow *QEglFSVivIntegration::createWindow(QWindow *window) const +{ + if (window->surfaceType() == QSurface::VulkanSurface) + return new QEglFSVulkanWindow(window); + return QEglFSDeviceIntegration::createWindow(window); +} + +QPlatformVulkanInstance *QEglFSVivIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) +{ + return new QEglFSVulkanInstance(instance); +} + +#endif // vulkan + QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.h index 4d1718afcf..02b59c16b5 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.h @@ -53,6 +53,12 @@ public: void destroyNativeWindow(EGLNativeWindowType window) override; EGLNativeDisplayType platformDisplay() const override; + // Vulkan support with VK_KHR_display +#if QT_CONFIG(vulkan) + QEglFSWindow *createWindow(QWindow *window) const override; + QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) override; +#endif + private: QSize mScreenSize; EGLNativeDisplayType mNativeDisplay; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp index 07b2de7c58..ce5a721906 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp @@ -75,7 +75,7 @@ void EventReader::run() if (client->format == 32 && client->type == atoms[Atoms::WM_PROTOCOLS] && client->data.data32[0] == atoms[Atoms::WM_DELETE_WINDOW]) { - QWindow *window = m_integration->platformWindow() ? m_integration->platformWindow()->window() : 0; + QWindow *window = m_integration->platformWindow() ? m_integration->platformWindow()->window() : nullptr; if (window) QWindowSystemInterface::handleCloseEvent(window); } @@ -106,7 +106,7 @@ void QEglFSX11Integration::sendConnectionEvent(xcb_atom_t a) void QEglFSX11Integration::platformInit() { - m_display = XOpenDisplay(0); + m_display = XOpenDisplay(nullptr); if (Q_UNLIKELY(!m_display)) qFatal("Could not open display"); @@ -121,7 +121,7 @@ void QEglFSX11Integration::platformInit() xcb_create_window(m_connection, XCB_COPY_FROM_PARENT, m_connectionEventListener, it.data->root, 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY, - it.data->root_visual, 0, 0); + it.data->root_visual, 0, nullptr); m_eventReader = new EventReader(this); m_eventReader->start(); @@ -135,11 +135,11 @@ void QEglFSX11Integration::platformDestroy() m_eventReader->wait(); delete m_eventReader; - m_eventReader = 0; + m_eventReader = nullptr; XCloseDisplay(DISPLAY); - m_display = 0; - m_connection = 0; + m_display = nullptr; + m_connection = nullptr; } EGLNativeDisplayType QEglFSX11Integration::platformDisplay() const @@ -175,7 +175,7 @@ EGLNativeWindowType QEglFSX11Integration::createNativeWindow(QPlatformWindow *pl xcb_create_window(m_connection, XCB_COPY_FROM_PARENT, m_window, it.data->root, 0, 0, size.width(), size.height(), 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, it.data->root_visual, - 0, 0); + 0, nullptr); xcb_intern_atom_cookie_t cookies[Atoms::N_ATOMS]; static const char *atomNames[Atoms::N_ATOMS] = { @@ -189,7 +189,7 @@ EGLNativeWindowType QEglFSX11Integration::createNativeWindow(QPlatformWindow *pl for (int i = 0; i < Atoms::N_ATOMS; ++i) { cookies[i] = xcb_intern_atom(m_connection, false, strlen(atomNames[i]), atomNames[i]); - xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(m_connection, cookies[i], 0); + xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(m_connection, cookies[i], nullptr); m_atoms[i] = reply->atom; free(reply); } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.h index bf431caaac..ebcc19b682 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.h @@ -67,7 +67,7 @@ class EventReader; class QEglFSX11Integration : public QEglFSDeviceIntegration { public: - QEglFSX11Integration() : m_connection(0), m_window(0), m_eventReader(0) {} + QEglFSX11Integration() : m_connection(nullptr), m_window(0), m_eventReader(nullptr) {} void platformInit() override; void platformDestroy() override; diff --git a/src/plugins/platforms/eglfs/eglfsdeviceintegration.pro b/src/plugins/platforms/eglfs/eglfsdeviceintegration.pro index 8bb7b614f1..bd02aea4d3 100644 --- a/src/plugins/platforms/eglfs/eglfsdeviceintegration.pro +++ b/src/plugins/platforms/eglfs/eglfsdeviceintegration.pro @@ -20,6 +20,9 @@ qtHaveModule(input_support-private): \ qtHaveModule(platformcompositor_support-private): \ QT += platformcompositor_support-private +qtConfig(vulkan): \ + QT += vulkan_support-private + # Avoid X11 header collision, use generic EGL native types DEFINES += QT_EGL_NO_X11 diff --git a/src/plugins/platforms/eglfs/qeglfsmain.cpp b/src/plugins/platforms/eglfs/qeglfsmain.cpp index 4f77b7cd17..b41bbec27d 100644 --- a/src/plugins/platforms/eglfs/qeglfsmain.cpp +++ b/src/plugins/platforms/eglfs/qeglfsmain.cpp @@ -56,7 +56,7 @@ QPlatformIntegration* QEglFSIntegrationPlugin::create(const QString& system, con if (!system.compare(QLatin1String("eglfs"), Qt::CaseInsensitive)) return new QEglFSIntegration; - return 0; + return nullptr; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/kernel.pro b/src/plugins/platforms/ios/kernel.pro index 71257d09f7..54069bee06 100644 --- a/src/plugins/platforms/ios/kernel.pro +++ b/src/plugins/platforms/ios/kernel.pro @@ -57,13 +57,15 @@ HEADERS = \ qiosmenu.mm \ qiosfiledialog.mm \ qiosmessagedialog.mm \ - qiostextinputoverlay.mm + qiostextinputoverlay.mm \ + qiosdocumentpickercontroller.mm HEADERS += \ qiosclipboard.h \ qiosmenu.h \ qiosfiledialog.h \ qiosmessagedialog.h \ - qiostextinputoverlay.h + qiostextinputoverlay.h \ + qiosdocumentpickercontroller.h } OTHER_FILES = \ diff --git a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm index 54152aebf7..c5244a51ad 100644 --- a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm +++ b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm @@ -373,7 +373,7 @@ bool QIOSFileEngineAssetsLibrary::close() QAbstractFileEngine::FileFlags QIOSFileEngineAssetsLibrary::fileFlags(QAbstractFileEngine::FileFlags type) const { - QAbstractFileEngine::FileFlags flags = 0; + QAbstractFileEngine::FileFlags flags; const bool isDir = (m_assetUrl == QLatin1String("assets-library://")); const bool exists = isDir || m_assetUrl == g_iteratorCurrentUrl.localData() || loadAsset(); diff --git a/src/plugins/platforms/cocoa/messages.h b/src/plugins/platforms/ios/qiosdocumentpickercontroller.h index 3a9eaf604e..dba6f24fc5 100644 --- a/src/plugins/platforms/cocoa/messages.h +++ b/src/plugins/platforms/ios/qiosdocumentpickercontroller.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2020 Harald Meyer. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -37,33 +37,10 @@ ** ****************************************************************************/ -#ifndef MESSAGES_H -#define MESSAGES_H +#import <UIKit/UIKit.h> -#include <QString> -#include <qpa/qplatformmenu.h> +#include "qiosfiledialog.h" -QT_BEGIN_NAMESPACE - -enum { - AboutAppMenuItem = 0, - PreferencesAppMenuItem, - ServicesAppMenuItem, - HideAppMenuItem, - HideOthersAppMenuItem, - ShowAllAppMenuItem, - QuitAppMenuItem -}; - - -QString msgAboutQt(); - -QString qt_mac_applicationmenu_string(int type); - -QPlatformMenuItem::MenuRole detectMenuRole(const QString &caption); - -QString msgDialogButtonDiscard(); - -QT_END_NAMESPACE - -#endif // MESSAGES_H +@interface QIOSDocumentPickerController : UIDocumentPickerViewController <UIDocumentPickerDelegate, UINavigationControllerDelegate> +- (instancetype)initWithQIOSFileDialog:(QIOSFileDialog *)fileDialog; +@end diff --git a/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm b/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm new file mode 100644 index 0000000000..c1b641e839 --- /dev/null +++ b/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2020 Harald Meyer. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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$ +** +****************************************************************************/ + +#import <UIKit/UIKit.h> +#import <MobileCoreServices/MobileCoreServices.h> + +#include "qiosdocumentpickercontroller.h" + +@implementation QIOSDocumentPickerController { + QIOSFileDialog *m_fileDialog; +} + +- (instancetype)initWithQIOSFileDialog:(QIOSFileDialog *)fileDialog +{ + NSMutableArray <NSString *> *docTypes = [[[NSMutableArray alloc] init] autorelease]; + UIDocumentPickerMode importMode; + switch (fileDialog->options()->fileMode()) { + case QFileDialogOptions::AnyFile: + case QFileDialogOptions::ExistingFile: + case QFileDialogOptions::ExistingFiles: + [docTypes addObject:(__bridge NSString *)kUTTypeContent]; + [docTypes addObject:(__bridge NSString *)kUTTypeItem]; + [docTypes addObject:(__bridge NSString *)kUTTypeData]; + importMode = UIDocumentPickerModeImport; + break; + case QFileDialogOptions::Directory: + case QFileDialogOptions::DirectoryOnly: + // Directory picking is not supported because it requires + // special handling not possible with the current QFilePicker + // implementation. + + Q_UNREACHABLE(); + } + + if (self = [super initWithDocumentTypes:docTypes inMode:importMode]) { + m_fileDialog = fileDialog; + self.modalPresentationStyle = UIModalPresentationFormSheet; + self.delegate = self; + + if (m_fileDialog->options()->fileMode() == QFileDialogOptions::ExistingFiles) + self.allowsMultipleSelection = YES; + + if (@available(ios 13.0, *)) + self.directoryURL = m_fileDialog->options()->initialDirectory().toNSURL(); + } + return self; +} + +- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray <NSURL *>*)urls +{ + Q_UNUSED(controller); + + QList<QUrl> files; + for (NSURL* url in urls) + files.append(QUrl::fromNSURL(url)); + + m_fileDialog->selectedFilesChanged(files); + emit m_fileDialog->accept(); +} + +- (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller +{ + Q_UNUSED(controller) + emit m_fileDialog->reject(); +} + +@end diff --git a/src/plugins/platforms/ios/qiosfiledialog.h b/src/plugins/platforms/ios/qiosfiledialog.h index 5cb1b45e20..eab05091ef 100644 --- a/src/plugins/platforms/ios/qiosfiledialog.h +++ b/src/plugins/platforms/ios/qiosfiledialog.h @@ -65,7 +65,7 @@ public: void selectNameFilter(const QString &) override {} QString selectedNameFilter() const override { return QString(); } - void selectedFilesChanged(QList<QUrl> selection); + void selectedFilesChanged(const QList<QUrl> &selection); private: QUrl m_directory; @@ -74,6 +74,7 @@ private: UIViewController *m_viewController; bool showImagePickerDialog(QWindow *parent); + bool showNativeDocumentPickerDialog(QWindow *parent); }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qiosfiledialog.mm b/src/plugins/platforms/ios/qiosfiledialog.mm index e8a3f5b30e..edf04016fd 100644 --- a/src/plugins/platforms/ios/qiosfiledialog.mm +++ b/src/plugins/platforms/ios/qiosfiledialog.mm @@ -48,6 +48,7 @@ #include "qiosfiledialog.h" #include "qiosintegration.h" #include "qiosoptionalplugininterface.h" +#include "qiosdocumentpickercontroller.h" QIOSFileDialog::QIOSFileDialog() : m_viewController(nullptr) @@ -72,8 +73,12 @@ bool QIOSFileDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality window bool acceptOpen = options()->acceptMode() == QFileDialogOptions::AcceptOpen; QString directory = options()->initialDirectory().toLocalFile(); - if (acceptOpen && directory.startsWith(QLatin1String("assets-library:"))) - return showImagePickerDialog(parent); + if (acceptOpen) { + if (directory.startsWith(QLatin1String("assets-library:"))) + return showImagePickerDialog(parent); + else + return showNativeDocumentPickerDialog(parent); + } return false; } @@ -102,6 +107,25 @@ bool QIOSFileDialog::showImagePickerDialog(QWindow *parent) return true; } +bool QIOSFileDialog::showNativeDocumentPickerDialog(QWindow *parent) +{ +#ifndef Q_OS_TVOS + if (options()->fileMode() == QFileDialogOptions::Directory || + options()->fileMode() == QFileDialogOptions::DirectoryOnly) + return false; + + m_viewController = [[QIOSDocumentPickerController alloc] initWithQIOSFileDialog:this]; + + UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window + : qt_apple_sharedApplication().keyWindow; + [window.rootViewController presentViewController:m_viewController animated:YES completion:nil]; + + return true; +#else + return false; +#endif +} + void QIOSFileDialog::hide() { // QFileDialog will remember the last directory set, and open subsequent dialogs in the same @@ -123,7 +147,7 @@ QList<QUrl> QIOSFileDialog::selectedFiles() const return m_selection; } -void QIOSFileDialog::selectedFilesChanged(QList<QUrl> selection) +void QIOSFileDialog::selectedFilesChanged(const QList<QUrl> &selection) { m_selection = selection; emit filesSelected(m_selection); diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index cdec57de71..1b6a802ca2 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -51,6 +51,9 @@ #include <qpa/qplatformintegration.h> #import <QuartzCore/CAEAGLLayer.h> +#ifdef Q_OS_IOS +#import <QuartzCore/CAMetalLayer.h> +#endif #include <QtDebug> @@ -58,9 +61,15 @@ QT_BEGIN_NAMESPACE QIOSWindow::QIOSWindow(QWindow *window) : QPlatformWindow(window) - , m_view([[QUIView alloc] initWithQIOSWindow:this]) , m_windowLevel(0) { +#ifdef Q_OS_IOS + if (window->surfaceType() == QSurface::MetalSurface) + m_view = [[QUIMetalView alloc] initWithQIOSWindow:this]; + else +#endif + m_view = [[QUIView alloc] initWithQIOSWindow:this]; + connect(qGuiApp, &QGuiApplication::applicationStateChanged, this, &QIOSWindow::applicationStateChanged); setParent(QPlatformWindow::parent()); diff --git a/src/plugins/platforms/ios/quiview.h b/src/plugins/platforms/ios/quiview.h index e1d5d5af0c..1ab9481dd6 100644 --- a/src/plugins/platforms/ios/quiview.h +++ b/src/plugins/platforms/ios/quiview.h @@ -70,3 +70,7 @@ QT_END_NAMESPACE @property (nonatomic, readonly) UIEdgeInsets qt_safeAreaInsets; @end +#ifdef Q_OS_IOS +@interface QUIMetalView : QUIView +@end +#endif diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index 91a186bace..59eae07388 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -100,13 +100,15 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") - (instancetype)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { - // Set up EAGL layer - CAEAGLLayer *eaglLayer = static_cast<CAEAGLLayer *>(self.layer); - eaglLayer.opaque = TRUE; - eaglLayer.drawableProperties = @{ - kEAGLDrawablePropertyRetainedBacking: @(YES), - kEAGLDrawablePropertyColorFormat: kEAGLColorFormatRGBA8 - }; + if ([self.layer isKindOfClass:[CAEAGLLayer class]]) { + // Set up EAGL layer + CAEAGLLayer *eaglLayer = static_cast<CAEAGLLayer *>(self.layer); + eaglLayer.opaque = TRUE; + eaglLayer.drawableProperties = @{ + kEAGLDrawablePropertyRetainedBacking: @(YES), + kEAGLDrawablePropertyColorFormat: kEAGLColorFormatRGBA8 + }; + } if (isQtApplication()) self.hidden = YES; @@ -675,6 +677,25 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") @end +#ifdef Q_OS_IOS +@implementation QUIMetalView + ++ (Class)layerClass +{ +#ifdef TARGET_IPHONE_SIMULATOR + if (@available(ios 13.0, *)) +#endif + + return [CAMetalLayer class]; + +#ifdef TARGET_IPHONE_SIMULATOR + return nil; +#endif +} + +@end +#endif + #ifndef QT_NO_ACCESSIBILITY // Include category as an alternative to using -ObjC (Apple QA1490) #include "quiview_accessibility.mm" diff --git a/src/plugins/platforms/minimal/qminimalintegration.cpp b/src/plugins/platforms/minimal/qminimalintegration.cpp index f457f69f11..0c2c0d0b68 100644 --- a/src/plugins/platforms/minimal/qminimalintegration.cpp +++ b/src/plugins/platforms/minimal/qminimalintegration.cpp @@ -103,17 +103,18 @@ QMinimalIntegration::QMinimalIntegration(const QStringList ¶meters) m_options |= DebugBackingStore | EnableFonts; } - QMinimalScreen *mPrimaryScreen = new QMinimalScreen(); + m_primaryScreen = new QMinimalScreen(); - mPrimaryScreen->mGeometry = QRect(0, 0, 240, 320); - mPrimaryScreen->mDepth = 32; - mPrimaryScreen->mFormat = QImage::Format_ARGB32_Premultiplied; + m_primaryScreen->mGeometry = QRect(0, 0, 240, 320); + m_primaryScreen->mDepth = 32; + m_primaryScreen->mFormat = QImage::Format_ARGB32_Premultiplied; - QWindowSystemInterface::handleScreenAdded(mPrimaryScreen); + QWindowSystemInterface::handleScreenAdded(m_primaryScreen); } QMinimalIntegration::~QMinimalIntegration() { + QWindowSystemInterface::handleScreenRemoved(m_primaryScreen); delete m_fontDatabase; } diff --git a/src/plugins/platforms/minimal/qminimalintegration.h b/src/plugins/platforms/minimal/qminimalintegration.h index ad1bec2112..f9c66e0c3e 100644 --- a/src/plugins/platforms/minimal/qminimalintegration.h +++ b/src/plugins/platforms/minimal/qminimalintegration.h @@ -88,6 +88,7 @@ public: private: mutable QPlatformFontDatabase *m_fontDatabase; + QMinimalScreen *m_primaryScreen; unsigned m_options; }; diff --git a/src/plugins/platforms/offscreen/main.cpp b/src/plugins/platforms/offscreen/main.cpp index 207db60f3a..f364d9f004 100644 --- a/src/plugins/platforms/offscreen/main.cpp +++ b/src/plugins/platforms/offscreen/main.cpp @@ -57,7 +57,7 @@ QPlatformIntegration *QOffscreenIntegrationPlugin::create(const QString& system, if (!system.compare(QLatin1String("offscreen"), Qt::CaseInsensitive)) return QOffscreenIntegration::createOffscreenIntegration(); - return 0; + return nullptr; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/offscreen/qoffscreencommon.cpp b/src/plugins/platforms/offscreen/qoffscreencommon.cpp index eae25012c1..de75a3e012 100644 --- a/src/plugins/platforms/offscreen/qoffscreencommon.cpp +++ b/src/plugins/platforms/offscreen/qoffscreencommon.cpp @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE -QPlatformWindow *QOffscreenScreen::windowContainingCursor = 0; +QPlatformWindow *QOffscreenScreen::windowContainingCursor = nullptr; class QOffscreenCursor : public QPlatformCursor { @@ -60,7 +60,7 @@ public: { m_pos = pos; const QWindowList wl = QGuiApplication::topLevelWindows(); - QWindow *containing = 0; + QWindow *containing = nullptr; for (QWindow *w : wl) { if (w->type() != Qt::Desktop && w->isExposed() && w->geometry().contains(pos)) { containing = w; @@ -72,7 +72,7 @@ public: if (containing) local -= containing->position(); - QWindow *previous = QOffscreenScreen::windowContainingCursor ? QOffscreenScreen::windowContainingCursor->window() : 0; + QWindow *previous = QOffscreenScreen::windowContainingCursor ? QOffscreenScreen::windowContainingCursor->window() : nullptr; if (containing != previous) QWindowSystemInterface::handleEnterLeaveEvent(containing, previous, local, pos); @@ -80,7 +80,7 @@ public: QWindowSystemInterface::handleMouseEvent(containing, local, pos, QGuiApplication::mouseButtons(), Qt::NoButton, QEvent::MouseMove, QGuiApplication::keyboardModifiers(), Qt::MouseEventSynthesizedByQt); - QOffscreenScreen::windowContainingCursor = containing ? containing->handle() : 0; + QOffscreenScreen::windowContainingCursor = containing ? containing->handle() : nullptr; } #ifndef QT_NO_CURSOR void changeCursor(QCursor *windowCursor, QWindow *window) override @@ -106,7 +106,7 @@ QPixmap QOffscreenScreen::grabWindow(WId id, int x, int y, int width, int height QOffscreenWindow *window = QOffscreenWindow::windowForWinId(id); if (!window || window->window()->type() == Qt::Desktop) { const QWindowList wl = QGuiApplication::topLevelWindows(); - QWindow *containing = 0; + QWindow *containing = nullptr; for (QWindow *w : wl) { if (w->type() != Qt::Desktop && w->isExposed() && w->geometry().contains(rect)) { containing = w; diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp index 869e9228cd..3a4494fc2e 100644 --- a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp +++ b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp @@ -79,7 +79,7 @@ template <typename BaseEventDispatcher> class QOffscreenEventDispatcher : public BaseEventDispatcher { public: - explicit QOffscreenEventDispatcher(QObject *parent = 0) + explicit QOffscreenEventDispatcher(QObject *parent = nullptr) : BaseEventDispatcher(parent) { } diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp index 92fc8aa57a..84991d751f 100644 --- a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp +++ b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp @@ -206,7 +206,7 @@ QOffscreenX11GLXContext::QOffscreenX11GLXContext(QOffscreenX11Info *x11, QOpenGL if (d->format.renderableType() != QSurfaceFormat::OpenGL) return; - d->shareContext = 0; + d->shareContext = nullptr; if (context->shareHandle()) d->shareContext = static_cast<QOffscreenX11GLXContext *>(context->shareHandle())->d->context; @@ -216,9 +216,9 @@ QOffscreenX11GLXContext::QOffscreenX11GLXContext(QOffscreenX11Info *x11, QOpenGL if (config) { d->context = glXCreateNewContext(x11->display(), config, GLX_RGBA_TYPE, d->shareContext, true); if (!d->context && d->shareContext) { - d->shareContext = 0; + d->shareContext = nullptr; // re-try without a shared glx context - d->context = glXCreateNewContext(x11->display(), config, GLX_RGBA_TYPE, 0, true); + d->context = glXCreateNewContext(x11->display(), config, GLX_RGBA_TYPE, nullptr, true); } // Get the basic surface format details @@ -234,8 +234,8 @@ QOffscreenX11GLXContext::QOffscreenX11GLXContext(QOffscreenX11Info *x11, QOpenGL d->context = glXCreateContext(x11->display(), visualInfo, d->shareContext, true); if (!d->context && d->shareContext) { // re-try without a shared glx context - d->shareContext = 0; - d->context = glXCreateContext(x11->display(), visualInfo, 0, true); + d->shareContext = nullptr; + d->context = glXCreateContext(x11->display(), visualInfo, nullptr, true); } d->window = createDummyWindow(x11, visualInfo); @@ -269,7 +269,7 @@ bool QOffscreenX11GLXContext::makeCurrent(QPlatformSurface *surface) void QOffscreenX11GLXContext::doneCurrent() { - glXMakeCurrent(d->x11->display(), 0, 0); + glXMakeCurrent(d->x11->display(), 0, nullptr); } void QOffscreenX11GLXContext::swapBuffers(QPlatformSurface *) diff --git a/src/plugins/platforms/offscreen/qoffscreenwindow.cpp b/src/plugins/platforms/offscreen/qoffscreenwindow.cpp index 832e94034d..53880c877e 100644 --- a/src/plugins/platforms/offscreen/qoffscreenwindow.cpp +++ b/src/plugins/platforms/offscreen/qoffscreenwindow.cpp @@ -69,7 +69,7 @@ QOffscreenWindow::QOffscreenWindow(QWindow *window) QOffscreenWindow::~QOffscreenWindow() { if (QOffscreenScreen::windowContainingCursor == this) - QOffscreenScreen::windowContainingCursor = 0; + QOffscreenScreen::windowContainingCursor = nullptr; m_windowForWinIdHash.remove(m_winId); } diff --git a/src/plugins/platforms/openwfd/qopenwfddevice.cpp b/src/plugins/platforms/openwfd/qopenwfddevice.cpp index 7a9d22e74d..99896151b2 100644 --- a/src/plugins/platforms/openwfd/qopenwfddevice.cpp +++ b/src/plugins/platforms/openwfd/qopenwfddevice.cpp @@ -83,7 +83,7 @@ QOpenWFDDevice::QOpenWFDDevice(QOpenWFDIntegration *integration, WFDint device_e int fd = wfdDeviceEventGetFD(mDevice,mEvent); mEventSocketNotifier = new QSocketNotifier(fd,QSocketNotifier::Read,this); - connect(mEventSocketNotifier,SIGNAL(activated(int)),SLOT(readEvents())); + connect(mEventSocketNotifier,SIGNAL(activated(QSocketDescriptor)),SLOT(readEvents())); mCommitedDevice = true; commit(WFD_COMMIT_ENTIRE_DEVICE, handle()); diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro index c4f2b30965..23f838a7fe 100644 --- a/src/plugins/platforms/platforms.pro +++ b/src/plugins/platforms/platforms.pro @@ -3,9 +3,9 @@ QT_FOR_CONFIG += gui-private android:!android-embedded: SUBDIRS += android -!android: SUBDIRS += minimal +!wasm:!android: SUBDIRS += minimal -!android:qtConfig(freetype): SUBDIRS += offscreen +!wasm:!android:qtConfig(freetype): SUBDIRS += offscreen qtConfig(xcb) { SUBDIRS += xcb diff --git a/src/plugins/platforms/qnx/qqnxbuttoneventnotifier.cpp b/src/plugins/platforms/qnx/qqnxbuttoneventnotifier.cpp index a6236f2376..f0c4c385ef 100644 --- a/src/plugins/platforms/qnx/qqnxbuttoneventnotifier.cpp +++ b/src/plugins/platforms/qnx/qqnxbuttoneventnotifier.cpp @@ -96,7 +96,7 @@ void QQnxButtonEventNotifier::start() } m_readNotifier = new QSocketNotifier(m_fd, QSocketNotifier::Read); - QObject::connect(m_readNotifier, SIGNAL(activated(int)), this, SLOT(updateButtonStates())); + QObject::connect(m_readNotifier, SIGNAL(activated(QSocketDescriptor)), this, SLOT(updateButtonStates())); qButtonDebug("successfully connected to Navigator. fd = %d", m_fd); } diff --git a/src/plugins/platforms/qnx/qqnxglcontext.cpp b/src/plugins/platforms/qnx/qqnxglcontext.cpp index 1d030ba1aa..69391c4fec 100644 --- a/src/plugins/platforms/qnx/qqnxglcontext.cpp +++ b/src/plugins/platforms/qnx/qqnxglcontext.cpp @@ -58,8 +58,6 @@ QT_BEGIN_NAMESPACE -EGLDisplay QQnxGLContext::ms_eglDisplay = EGL_NO_DISPLAY; - static QEGLPlatformContext::Flags makeFlags() { QEGLPlatformContext::Flags result = 0; @@ -71,7 +69,8 @@ static QEGLPlatformContext::Flags makeFlags() } QQnxGLContext::QQnxGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share) - : QEGLPlatformContext(format, share, ms_eglDisplay, 0, QVariant(), makeFlags()) + : QEGLPlatformContext(format, share, QQnxIntegration::instance()->eglDisplay(), 0, QVariant(), + makeFlags()) { } @@ -79,28 +78,6 @@ QQnxGLContext::~QQnxGLContext() { } -void QQnxGLContext::initializeContext() -{ - qGLContextDebug(); - - // Initialize connection to EGL - ms_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); - if (Q_UNLIKELY(ms_eglDisplay == EGL_NO_DISPLAY)) - qFatal("QQnxGLContext: failed to obtain EGL display: %x", eglGetError()); - - EGLBoolean eglResult = eglInitialize(ms_eglDisplay, 0, 0); - if (Q_UNLIKELY(eglResult != EGL_TRUE)) - qFatal("QQnxGLContext: failed to initialize EGL display, err=%d", eglGetError()); -} - -void QQnxGLContext::shutdownContext() -{ - qGLContextDebug(); - - // Close connection to EGL - eglTerminate(ms_eglDisplay); -} - EGLSurface QQnxGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface) { QQnxEglWindow *window = static_cast<QQnxEglWindow *>(surface); diff --git a/src/plugins/platforms/qnx/qqnxglcontext.h b/src/plugins/platforms/qnx/qqnxglcontext.h index 19179a80e2..5d807ee9e4 100644 --- a/src/plugins/platforms/qnx/qqnxglcontext.h +++ b/src/plugins/platforms/qnx/qqnxglcontext.h @@ -58,19 +58,12 @@ public: QQnxGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share); virtual ~QQnxGLContext(); - static void initializeContext(); - static void shutdownContext(); - bool makeCurrent(QPlatformSurface *surface) override; void swapBuffers(QPlatformSurface *surface) override; void doneCurrent() override; protected: EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) override; - -private: - //Can be static because different displays returne the same handle - static EGLDisplay ms_eglDisplay; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp index f479e94988..84baa6ec44 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.cpp +++ b/src/plugins/platforms/qnx/qqnxintegration.cpp @@ -170,6 +170,9 @@ QQnxIntegration::QQnxIntegration(const QStringList ¶mList) #if QT_CONFIG(draganddrop) , m_drag(new QSimpleDrag()) #endif +#if QT_CONFIG(opengl) + , m_eglDisplay(EGL_NO_DISPLAY) +#endif { ms_instance = this; m_options = parseOptions(paramList); @@ -195,9 +198,8 @@ QQnxIntegration::QQnxIntegration(const QStringList ¶mList) QMetaObject::invokeMethod(m_navigatorEventNotifier, "start", Qt::QueuedConnection); #endif -#if !defined(QT_NO_OPENGL) - // Initialize global OpenGL resources - QQnxGLContext::initializeContext(); +#if QT_CONFIG(opengl) + createEglDisplay(); #endif // Create/start event thread @@ -284,9 +286,8 @@ QQnxIntegration::~QQnxIntegration() // Close connection to QNX composition manager screen_destroy_context(m_screenContext); -#if !defined(QT_NO_OPENGL) - // Cleanup global OpenGL resources - QQnxGLContext::shutdownContext(); +#if QT_CONFIG(opengl) + destroyEglDisplay(); #endif #if QT_CONFIG(qqnx_pps) @@ -741,4 +742,28 @@ bool QQnxIntegration::supportsNavigatorEvents() const return m_navigator != 0; } +#if QT_CONFIG(opengl) +void QQnxIntegration::createEglDisplay() +{ + qIntegrationDebug(); + + // Initialize connection to EGL + m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (Q_UNLIKELY(m_eglDisplay == EGL_NO_DISPLAY)) + qFatal("QQnxiIntegration: failed to obtain EGL display: %x", eglGetError()); + + EGLBoolean eglResult = eglInitialize(m_eglDisplay, 0, 0); + if (Q_UNLIKELY(eglResult != EGL_TRUE)) + qFatal("QQnxIntegration: failed to initialize EGL display, err=%d", eglGetError()); +} + +void QQnxIntegration::destroyEglDisplay() +{ + qIntegrationDebug(); + + // Close connection to EGL + eglTerminate(m_eglDisplay); +} +#endif + QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxintegration.h b/src/plugins/platforms/qnx/qqnxintegration.h index 0bf37880d1..2596af3c45 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.h +++ b/src/plugins/platforms/qnx/qqnxintegration.h @@ -46,6 +46,10 @@ #include <screen/screen.h> +#if QT_CONFIG(opengl) +#include <EGL/egl.h> +#endif + QT_BEGIN_NAMESPACE class QQnxScreenEventThread; @@ -96,7 +100,8 @@ public: QPlatformWindow *createPlatformWindow(QWindow *window) const override; QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override; -#if !defined(QT_NO_OPENGL) +#if QT_CONFIG(opengl) + EGLDisplay eglDisplay() const { return m_eglDisplay; } QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override; #endif @@ -175,6 +180,12 @@ private: Options m_options; +#if QT_CONFIG(opengl) + EGLDisplay m_eglDisplay; + void createEglDisplay(); + void destroyEglDisplay(); +#endif + static QQnxIntegration *ms_instance; friend class QQnxWindow; diff --git a/src/plugins/platforms/qnx/qqnxnativeinterface.cpp b/src/plugins/platforms/qnx/qqnxnativeinterface.cpp index 3bd6a86b59..25f7b09a60 100644 --- a/src/plugins/platforms/qnx/qqnxnativeinterface.cpp +++ b/src/plugins/platforms/qnx/qqnxnativeinterface.cpp @@ -94,6 +94,11 @@ void *QQnxNativeInterface::nativeResourceForIntegration(const QByteArray &resour if (resource == "screenContext") return m_integration->screenContext(); +#if QT_CONFIG(opengl) + if (resource.toLower() == "egldisplay") + return m_integration->eglDisplay(); +#endif + return 0; } diff --git a/src/plugins/platforms/qnx/qqnxnavigatoreventnotifier.cpp b/src/plugins/platforms/qnx/qqnxnavigatoreventnotifier.cpp index 1f630863b7..f7e8e7966c 100644 --- a/src/plugins/platforms/qnx/qqnxnavigatoreventnotifier.cpp +++ b/src/plugins/platforms/qnx/qqnxnavigatoreventnotifier.cpp @@ -96,7 +96,7 @@ void QQnxNavigatorEventNotifier::start() } m_readNotifier = new QSocketNotifier(m_fd, QSocketNotifier::Read); - connect(m_readNotifier, SIGNAL(activated(int)), this, SLOT(readData())); + connect(m_readNotifier, SIGNAL(activated(QSocketDescriptor)), this, SLOT(readData())); } void QQnxNavigatorEventNotifier::parsePPS(const QByteArray &ppsData, QByteArray &msg, QByteArray &dat, QByteArray &id) diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp index a9b5860187..e3a6aea99f 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp +++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp @@ -257,7 +257,7 @@ void QQnxScreenEventHandler::injectKeyboardEvent(int flags, int sym, int modifie capKeyString(cap, modifiers, key); QWindowSystemInterface::handleExtendedKeyEvent(QGuiApplication::focusWindow(), type, key, qtMod, - scan, virtualKey, modifiers, keyStr); + scan, virtualKey, modifiers, keyStr, flags & KEY_REPEAT); qScreenEventDebug() << "Qt key t=" << type << ", k=" << key << ", s=" << keyStr; } diff --git a/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp b/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp index 025c03c058..6f496571fa 100644 --- a/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp +++ b/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp @@ -143,7 +143,7 @@ bool QQnxVirtualKeyboardPps::connect() return false; m_readNotifier = new QSocketNotifier(m_fd, QSocketNotifier::Read); - QObject::connect(m_readNotifier, SIGNAL(activated(int)), this, SLOT(ppsDataReady())); + QObject::connect(m_readNotifier, SIGNAL(activated(QSocketDescriptor)), this, SLOT(ppsDataReady())); return true; } diff --git a/src/plugins/platforms/vnc/main.cpp b/src/plugins/platforms/vnc/main.cpp index 3ec0f0b78d..ac7e18e03f 100644 --- a/src/plugins/platforms/vnc/main.cpp +++ b/src/plugins/platforms/vnc/main.cpp @@ -56,7 +56,7 @@ QPlatformIntegration* QVncIntegrationPlugin::create(const QString& system, const if (!system.compare(QLatin1String("vnc"), Qt::CaseInsensitive)) return new QVncIntegration(paramList); - return 0; + return nullptr; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/vnc/qvnc.cpp b/src/plugins/platforms/vnc/qvnc.cpp index 32114c6443..8390fa19cd 100644 --- a/src/plugins/platforms/vnc/qvnc.cpp +++ b/src/plugins/platforms/vnc/qvnc.cpp @@ -537,7 +537,7 @@ QVncClientCursor::QVncClientCursor() { QWindow *w = QGuiApplication::focusWindow(); QCursor c = w ? w->cursor() : QCursor(Qt::ArrowCursor); - changeCursor(&c, 0); + changeCursor(&c, nullptr); } QVncClientCursor::~QVncClientCursor() @@ -595,7 +595,7 @@ void QVncClientCursor::changeCursor(QCursor *widgetCursor, QWindow *window) cursor = widgetCursor->pixmap().toImage(); } else { // system cursor - QPlatformCursorImage platformImage(0, 0, 0, 0, 0, 0); + QPlatformCursorImage platformImage(nullptr, nullptr, 0, 0, 0, 0); platformImage.set(shape); cursor = *platformImage.image(); hotspot = platformImage.hotspot(); diff --git a/src/plugins/platforms/vnc/qvncclient.cpp b/src/plugins/platforms/vnc/qvncclient.cpp index 3a373a5e4b..c5caddc58d 100644 --- a/src/plugins/platforms/vnc/qvncclient.cpp +++ b/src/plugins/platforms/vnc/qvncclient.cpp @@ -65,7 +65,6 @@ QVncClient::QVncClient(QTcpSocket *clientSocket, QVncServer *server) , m_cutTextPending(0) , m_supportHextile(false) , m_wantUpdate(false) - , m_keymod(0) , m_dirtyCursor(false) , m_updatePending(false) , m_protocolVersion(V3_3) @@ -618,7 +617,7 @@ void QVncClient::keyEvent() m_keymod = ev.down ? m_keymod | Qt::AltModifier : m_keymod & ~Qt::AltModifier; if (ev.unicode || ev.keycode) - QWindowSystemInterface::handleKeyEvent(0, ev.down ? QEvent::KeyPress : QEvent::KeyRelease, ev.keycode, m_keymod, QString(ev.unicode)); + QWindowSystemInterface::handleKeyEvent(nullptr, ev.down ? QEvent::KeyPress : QEvent::KeyRelease, ev.keycode, m_keymod, QString(ev.unicode)); m_handleMsg = false; } } diff --git a/src/plugins/platforms/vnc/qvncscreen.cpp b/src/plugins/platforms/vnc/qvncscreen.cpp index 2eca18fb4d..5dc3919ff5 100644 --- a/src/plugins/platforms/vnc/qvncscreen.cpp +++ b/src/plugins/platforms/vnc/qvncscreen.cpp @@ -101,7 +101,7 @@ bool QVncScreen::initialize() default: qWarning("QVNCScreen::initDevice: No support for screen depth %d", depth()); - dirty = 0; + dirty = nullptr; return false; } diff --git a/src/plugins/platforms/wasm/qwasmclipboard.cpp b/src/plugins/platforms/wasm/qwasmclipboard.cpp index f02c2c6ccb..890b01fa3c 100644 --- a/src/plugins/platforms/wasm/qwasmclipboard.cpp +++ b/src/plugins/platforms/wasm/qwasmclipboard.cpp @@ -192,15 +192,12 @@ void QWasmClipboard::initClipboardEvents() permissions.call<val>("query", writePermissionsMap); } -void QWasmClipboard::installEventHandlers(const QString &canvasId) +void QWasmClipboard::installEventHandlers(const emscripten::val &canvas) { if (hasClipboardApi) return; // Fallback path for browsers which do not support direct clipboard access - val document = val::global("document"); - val canvas = document.call<val>("getElementById", QWasmString::fromQString(canvasId)); - canvas.call<void>("addEventListener", val("cut"), val::module_property("qtClipboardCutTo")); canvas.call<void>("addEventListener", val("copy"), diff --git a/src/plugins/platforms/wasm/qwasmclipboard.h b/src/plugins/platforms/wasm/qwasmclipboard.h index 00aae8fead..3b28e2c381 100644 --- a/src/plugins/platforms/wasm/qwasmclipboard.h +++ b/src/plugins/platforms/wasm/qwasmclipboard.h @@ -36,6 +36,7 @@ #include <QMimeData> #include <emscripten/bind.h> +#include <emscripten/val.h> class QWasmClipboard : public QObject, public QPlatformClipboard { @@ -51,7 +52,7 @@ public: static void qWasmClipboardPaste(QMimeData *mData); void initClipboardEvents(); - void installEventHandlers(const QString &canvasId); + void installEventHandlers(const emscripten::val &canvas); bool hasClipboardApi; void readTextFromClipboard(); void writeTextToClipboard(); diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp index 2f0b0414d9..0ece812972 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.cpp +++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp @@ -328,11 +328,12 @@ QRect QWasmCompositor::titlebarRect(QWasmTitleBarOptions tb, QWasmCompositor::Su } break; case SC_TitleBarNormalButton: - if (isMinimized && (tb.flags & Qt::WindowMinimizeButtonHint)) + if (isMinimized && (tb.flags & Qt::WindowMinimizeButtonHint)) { offset += delta; - else if (isMaximized && (tb.flags & Qt::WindowMaximizeButtonHint)) + } else if (isMaximized && (tb.flags & Qt::WindowMaximizeButtonHint)) { ret.adjust(0, 0, -delta*2, 0); offset += (delta +delta); + } break; case SC_TitleBarSysMenu: if (tb.flags & Qt::WindowSystemMenuHint) { diff --git a/src/plugins/platforms/wasm/qwasmcursor.cpp b/src/plugins/platforms/wasm/qwasmcursor.cpp index 616456b2fa..61204517ce 100644 --- a/src/plugins/platforms/wasm/qwasmcursor.cpp +++ b/src/plugins/platforms/wasm/qwasmcursor.cpp @@ -57,9 +57,7 @@ void QWasmCursor::changeCursor(QCursor *windowCursor, QWindow *window) htmlCursorName = "auto"; // Set cursor on the canvas - val jsCanvasId = QWasmString::fromQString(QWasmScreen::get(screen)->canvasId()); - val document = val::global("document"); - val canvas = document.call<val>("getElementById", jsCanvasId); + val canvas = QWasmScreen::get(screen)->canvas(); val canvasStyle = canvas["style"]; canvasStyle.set("cursor", val(htmlCursorName.constData())); } diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp index 62ada796db..3e6043b083 100644 --- a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp +++ b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp @@ -354,9 +354,7 @@ void QWasmEventTranslator::initEventHandlers() g_useNaturalScrolling = false; // make this !default on macOS if (emscripten::val::global("window")["safari"].isUndefined()) { - val document = val::global("document"); - val jsCanvasId = QWasmString::fromQString(screen()->canvasId()); - val canvas = document.call<val>("getElementById", jsCanvasId); + val canvas = screen()->canvas(); canvas.call<void>("addEventListener", val("wheel"), val::module_property("qtMouseWheelEvent")); diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp index f8eaa39f76..4b42b5788f 100644 --- a/src/plugins/platforms/wasm/qwasmintegration.cpp +++ b/src/plugins/platforms/wasm/qwasmintegration.cpp @@ -68,20 +68,17 @@ static void browserBeforeUnload(emscripten::val) static void addCanvasElement(emscripten::val canvas) { - QString canvasId = QWasmString::toQString(canvas["id"]); - QWasmIntegration::get()->addScreen(canvasId); + QWasmIntegration::get()->addScreen(canvas); } static void removeCanvasElement(emscripten::val canvas) { - QString canvasId = QWasmString::toQString(canvas["id"]); - QWasmIntegration::get()->removeScreen(canvasId); + QWasmIntegration::get()->removeScreen(canvas); } static void resizeCanvasElement(emscripten::val canvas) { - QString canvasId = QWasmString::toQString(canvas["id"]); - QWasmIntegration::get()->resizeScreen(canvasId); + QWasmIntegration::get()->resizeScreen(canvas); } static void qtUpdateDpi() @@ -114,15 +111,12 @@ QWasmIntegration::QWasmIntegration() if (!qtCanvaseElements.isUndefined()) { int screenCount = qtCanvaseElements["length"].as<int>(); for (int i = 0; i < screenCount; ++i) { - emscripten::val canvas = qtCanvaseElements[i].as<emscripten::val>(); - QString canvasId = QWasmString::toQString(canvas["id"]); - addScreen(canvasId); + addScreen(qtCanvaseElements[i].as<emscripten::val>()); } } else if (!canvas.isUndefined()) { qWarning() << "Module.canvas is deprecated. A future version of Qt will stop reading this property. " << "Instead, set Module.qtCanvasElements to be an array of canvas elements, or use qtloader.js."; - QString canvasId = QWasmString::toQString(canvas["id"]); - addScreen(canvasId); + addScreen(canvas); } emscripten::val::global("window").set("onbeforeunload", val::module_property("qtBrowserBeforeUnload")); @@ -148,8 +142,8 @@ QWasmIntegration::~QWasmIntegration() delete m_fontDb; delete m_desktopServices; - for (auto it = m_screens.constBegin(); it != m_screens.constEnd(); ++it) - QWindowSystemInterface::handleScreenRemoved(*it); + for (const auto &canvasAndScreen : m_screens) + QWindowSystemInterface::handleScreenRemoved(canvasAndScreen.second); m_screens.clear(); s_instance = nullptr; @@ -276,24 +270,37 @@ QPlatformClipboard* QWasmIntegration::clipboard() const return m_clipboard; } -void QWasmIntegration::addScreen(const QString &canvasId) +void QWasmIntegration::addScreen(const emscripten::val &canvas) { - QWasmScreen *screen = new QWasmScreen(canvasId); - m_clipboard->installEventHandlers(canvasId); - m_screens.insert(canvasId, screen); + QWasmScreen *screen = new QWasmScreen(canvas); + m_screens.append(qMakePair(canvas, screen)); + m_clipboard->installEventHandlers(canvas); QWindowSystemInterface::handleScreenAdded(screen); } -void QWasmIntegration::removeScreen(const QString &canvasId) +void QWasmIntegration::removeScreen(const emscripten::val &canvas) { - QWasmScreen *exScreen = m_screens.take(canvasId); + auto it = std::find_if(m_screens.begin(), m_screens.end(), + [&] (const QPair<emscripten::val, QWasmScreen *> &candidate) { return candidate.first.equals(canvas); }); + if (it == m_screens.end()) { + qWarning() << "Attempting to remove non-existing screen for canvas" << QWasmString::toQString(canvas["id"]);; + return; + } + QWasmScreen *exScreen = it->second; + m_screens.erase(it); exScreen->destroy(); // clean up before deleting the screen QWindowSystemInterface::handleScreenRemoved(exScreen); } -void QWasmIntegration::resizeScreen(const QString &canvasId) +void QWasmIntegration::resizeScreen(const emscripten::val &canvas) { - m_screens.value(canvasId)->updateQScreenAndCanvasRenderSize(); + auto it = std::find_if(m_screens.begin(), m_screens.end(), + [&] (const QPair<emscripten::val, QWasmScreen *> &candidate) { return candidate.first.equals(canvas); }); + if (it == m_screens.end()) { + qWarning() << "Attempting to resize non-existing screen for canvas" << QWasmString::toQString(canvas["id"]);; + return; + } + it->second->updateQScreenAndCanvasRenderSize(); } void QWasmIntegration::updateDpi() @@ -302,15 +309,14 @@ void QWasmIntegration::updateDpi() if (dpi.isUndefined()) return; qreal dpiValue = dpi.as<qreal>(); - for (QWasmScreen *screen : m_screens) - QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen->screen(), dpiValue, dpiValue); + for (const auto &canvasAndScreen : m_screens) + QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(canvasAndScreen.second->screen(), dpiValue, dpiValue); } void QWasmIntegration::resizeAllScreens() { - qDebug() << "resizeAllScreens"; - for (QWasmScreen *screen : m_screens) - screen->updateQScreenAndCanvasRenderSize(); + for (const auto &canvasAndScreen : m_screens) + canvasAndScreen.second->updateQScreenAndCanvasRenderSize(); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/wasm/qwasmintegration.h b/src/plugins/platforms/wasm/qwasmintegration.h index 2eb64ed366..cb8639086a 100644 --- a/src/plugins/platforms/wasm/qwasmintegration.h +++ b/src/plugins/platforms/wasm/qwasmintegration.h @@ -40,6 +40,7 @@ #include <emscripten.h> #include <emscripten/html5.h> +#include <emscripten/val.h> QT_BEGIN_NAMESPACE @@ -83,9 +84,9 @@ public: static QWasmIntegration *get() { return s_instance; } static void QWasmBrowserExit(); - void addScreen(const QString &canvasId); - void removeScreen(const QString &canvasId); - void resizeScreen(const QString &canvasId); + void addScreen(const emscripten::val &canvas); + void removeScreen(const emscripten::val &canvas); + void resizeScreen(const emscripten::val &canvas); void resizeAllScreens(); void updateDpi(); void removeBackingStore(QWindow* window); @@ -94,8 +95,7 @@ private: mutable QWasmFontDatabase *m_fontDb; mutable QWasmServices *m_desktopServices; mutable QHash<QWindow *, QWasmBackingStore *> m_backingStores; - - QHash<QString, QWasmScreen *> m_screens; + QVector<QPair<emscripten::val, QWasmScreen *>> m_screens; mutable QWasmClipboard *m_clipboard; qreal m_fontDpi = -1; mutable QScopedPointer<QPlatformInputContext> m_inputContext; diff --git a/src/plugins/platforms/wasm/qwasmopenglcontext.cpp b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp index 4ddd56fd8c..c122335a57 100644 --- a/src/plugins/platforms/wasm/qwasmopenglcontext.cpp +++ b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp @@ -62,6 +62,16 @@ QWasmOpenGLContext::~QWasmOpenGLContext() } } +bool QWasmOpenGLContext::isOpenGLVersionSupported(QSurfaceFormat format) +{ + // Version check: support WebGL 1 and 2: + // (ES) 2.0 -> WebGL 1.0 + // (ES) 3.0 -> WebGL 2.0 + // [we don't expect that new WebGL versions will be created] + return ((format.majorVersion() == 2 && format.minorVersion() == 0) || + (format.majorVersion() == 3 && format.minorVersion() == 0)); +} + bool QWasmOpenGLContext::maybeCreateEmscriptenContext(QPlatformSurface *surface) { // Native emscripten/WebGL contexts are tied to a single screen/canvas. The first @@ -88,14 +98,12 @@ EMSCRIPTEN_WEBGL_CONTEXT_HANDLE QWasmOpenGLContext::createEmscriptenContext(cons EmscriptenWebGLContextAttributes attributes; emscripten_webgl_init_context_attributes(&attributes); // Populate with default attributes - attributes.preferLowPowerToHighPerformance = false; + attributes.powerPreference = EM_WEBGL_POWER_PREFERENCE_HIGH_PERFORMANCE; attributes.failIfMajorPerformanceCaveat = false; attributes.antialias = true; attributes.enableExtensionsByDefault = true; - - if (format.majorVersion() == 3) { - attributes.majorVersion = 2; - } + attributes.majorVersion = format.majorVersion() - 1; + attributes.minorVersion = format.minorVersion(); // WebGL doesn't allow separate attach buffers to STENCIL_ATTACHMENT and DEPTH_ATTACHMENT // we need both or none @@ -149,6 +157,9 @@ bool QWasmOpenGLContext::isSharing() const bool QWasmOpenGLContext::isValid() const { + if (!(isOpenGLVersionSupported(m_requestedFormat))) + return false; + // Note: we get isValid() calls before we see the surface and can // create a native context, so no context is also a valid state. return !m_context || !emscripten_is_webgl_context_lost(m_context); diff --git a/src/plugins/platforms/wasm/qwasmopenglcontext.h b/src/plugins/platforms/wasm/qwasmopenglcontext.h index d27007e8ea..cf84379c36 100644 --- a/src/plugins/platforms/wasm/qwasmopenglcontext.h +++ b/src/plugins/platforms/wasm/qwasmopenglcontext.h @@ -51,6 +51,7 @@ public: QFunctionPointer getProcAddress(const char *procName) override; private: + static bool isOpenGLVersionSupported(QSurfaceFormat format); bool maybeCreateEmscriptenContext(QPlatformSurface *surface); static EMSCRIPTEN_WEBGL_CONTEXT_HANDLE createEmscriptenContext(const QString &canvasId, QSurfaceFormat format); diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp index 2788f1ac19..a2bcd4fcb4 100644 --- a/src/plugins/platforms/wasm/qwasmscreen.cpp +++ b/src/plugins/platforms/wasm/qwasmscreen.cpp @@ -50,13 +50,13 @@ using namespace emscripten; QT_BEGIN_NAMESPACE -QWasmScreen::QWasmScreen(const QString &canvasId) - : m_canvasId(canvasId) - +QWasmScreen::QWasmScreen(const emscripten::val &canvas) + : m_canvas(canvas) { m_compositor = new QWasmCompositor(this); m_eventTranslator = new QWasmEventTranslator(this); updateQScreenAndCanvasRenderSize(); + m_canvas.call<void>("focus"); } QWasmScreen::~QWasmScreen() @@ -89,9 +89,14 @@ QWasmEventTranslator *QWasmScreen::eventTranslator() return m_eventTranslator; } +emscripten::val QWasmScreen::canvas() const +{ + return m_canvas; +} + QString QWasmScreen::canvasId() const { - return m_canvasId; + return QWasmString::toQString(m_canvas["id"]); } QRect QWasmScreen::geometry() const @@ -132,7 +137,7 @@ qreal QWasmScreen::devicePixelRatio() const QString QWasmScreen::name() const { - return m_canvasId; + return canvasId(); } QPlatformCursor *QWasmScreen::cursor() const @@ -178,24 +183,22 @@ void QWasmScreen::updateQScreenAndCanvasRenderSize() // Setting the render size to a value larger than the CSS size enables high-dpi // rendering. - QByteArray canvasSelector = "#" + m_canvasId.toUtf8(); + QByteArray canvasSelector = "#" + canvasId().toUtf8(); double css_width; double css_height; emscripten_get_element_css_size(canvasSelector.constData(), &css_width, &css_height); QSizeF cssSize(css_width, css_height); QSizeF canvasSize = cssSize * devicePixelRatio(); - val document = val::global("document"); - val canvas = document.call<val>("getElementById", QWasmString::fromQString(m_canvasId)); - canvas.set("width", canvasSize.width()); - canvas.set("height", canvasSize.height()); + m_canvas.set("width", canvasSize.width()); + m_canvas.set("height", canvasSize.height()); QPoint offset; - offset.setX(canvas["offsetTop"].as<int>()); - offset.setY(canvas["offsetLeft"].as<int>()); + offset.setX(m_canvas["offsetTop"].as<int>()); + offset.setY(m_canvas["offsetLeft"].as<int>()); - emscripten::val rect = canvas.call<emscripten::val>("getBoundingClientRect"); + emscripten::val rect = m_canvas.call<emscripten::val>("getBoundingClientRect"); QPoint position(rect["left"].as<int>() - offset.x(), rect["top"].as<int>() - offset.y()); setGeometry(QRect(position, cssSize.toSize())); diff --git a/src/plugins/platforms/wasm/qwasmscreen.h b/src/plugins/platforms/wasm/qwasmscreen.h index fcf693681c..ea7ffc4193 100644 --- a/src/plugins/platforms/wasm/qwasmscreen.h +++ b/src/plugins/platforms/wasm/qwasmscreen.h @@ -37,6 +37,8 @@ #include <QtCore/qscopedpointer.h> #include <QtCore/qtextstream.h> +#include <emscripten/val.h> + QT_BEGIN_NAMESPACE class QPlatformOpenGLContext; @@ -50,12 +52,13 @@ class QWasmScreen : public QObject, public QPlatformScreen { Q_OBJECT public: - QWasmScreen(const QString &canvasId); + QWasmScreen(const emscripten::val &canvas); ~QWasmScreen(); void destroy(); static QWasmScreen *get(QPlatformScreen *screen); static QWasmScreen *get(QScreen *screen); + emscripten::val canvas() const; QString canvasId() const; QWasmCompositor *compositor(); @@ -80,7 +83,7 @@ public slots: void setGeometry(const QRect &rect); private: - QString m_canvasId; + emscripten::val m_canvas; QWasmCompositor *m_compositor = nullptr; QWasmEventTranslator *m_eventTranslator = nullptr; QRect m_geometry = QRect(0, 0, 100, 100); diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp index 594db65cfd..f95335f891 100644 --- a/src/plugins/platforms/wasm/qwasmwindow.cpp +++ b/src/plugins/platforms/wasm/qwasmwindow.cpp @@ -265,6 +265,8 @@ bool QWasmWindow::isPointOnTitle(QPoint point) const bool QWasmWindow::isPointOnResizeRegion(QPoint point) const { + if (window()->flags().testFlag(Qt::Popup)) + return false; return resizeRegion().contains(point); } @@ -402,7 +404,8 @@ void QWasmWindow::requestUpdate() bool QWasmWindow::hasTitleBar() const { - return !(m_windowState & Qt::WindowFullScreen) && (window()->flags().testFlag(Qt::WindowTitleHint) && m_needsCompositor); + return !(m_windowState & Qt::WindowFullScreen) && (window()->flags().testFlag(Qt::WindowTitleHint) && m_needsCompositor) + && !window()->flags().testFlag(Qt::Popup); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/main.cpp b/src/plugins/platforms/windows/main.cpp index 1929f800a4..94d8470ab1 100644 --- a/src/plugins/platforms/windows/main.cpp +++ b/src/plugins/platforms/windows/main.cpp @@ -46,10 +46,9 @@ QT_BEGIN_NAMESPACE /*! - \group qt-lighthouse-win - \title Qt Lighthouse plugin for Windows + \title Qt platform plugin for Windows - \brief Class documentation of the Qt Lighthouse plugin for Windows. + \brief Class documentation of the Qt platform plugin for Windows. \section1 Supported Parameters @@ -78,7 +77,6 @@ QT_BEGIN_NAMESPACE \class QWindowsIntegrationPlugin \brief Plugin. \internal - \ingroup qt-lighthouse-win */ /*! @@ -86,7 +84,6 @@ QT_BEGIN_NAMESPACE \brief Namespace for enumerations, etc. \internal - \ingroup qt-lighthouse-win */ /*! @@ -97,7 +94,6 @@ QT_BEGIN_NAMESPACE With flags that should help to structure the code. \internal - \ingroup qt-lighthouse-win */ class QWindowsIntegrationPlugin : public QPlatformIntegrationPlugin diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp index bd7bdc55d1..e3939ca2d7 100644 --- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp +++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp @@ -55,7 +55,6 @@ QT_BEGIN_NAMESPACE \class QWindowsBackingStore \brief Backing store for windows. \internal - \ingroup qt-lighthouse-win */ QWindowsBackingStore::QWindowsBackingStore(QWindow *window) : diff --git a/src/plugins/platforms/windows/qwindowsclipboard.cpp b/src/plugins/platforms/windows/qwindowsclipboard.cpp index 4e6d3306e1..b23904e978 100644 --- a/src/plugins/platforms/windows/qwindowsclipboard.cpp +++ b/src/plugins/platforms/windows/qwindowsclipboard.cpp @@ -71,7 +71,6 @@ QT_BEGIN_NAMESPACE \note The OLE-functions used in this class require OleInitialize(). \internal - \ingroup qt-lighthouse-win */ #ifndef QT_NO_DEBUG_STREAM @@ -82,7 +81,7 @@ static QDebug operator<<(QDebug d, const QMimeData *mimeData) d << "QMimeData("; if (mimeData) { const QStringList formats = mimeData->formats(); - d << "formats=" << formats.join(QLatin1String(", ")); + d << "formats=" << formats.join(u", "); if (mimeData->hasText()) d << ", text=" << mimeData->text(); if (mimeData->hasHtml()) @@ -110,7 +109,6 @@ static QDebug operator<<(QDebug d, const QMimeData *mimeData) \sa QWindowsInternalMimeDataBase, QWindowsClipboard \internal - \ingroup qt-lighthouse-win */ IDataObject *QWindowsClipboardRetrievalMimeData::retrieveDataObject() const @@ -190,7 +188,7 @@ void QWindowsClipboard::releaseIData() void QWindowsClipboard::registerViewer() { m_clipboardViewer = QWindowsContext::instance()-> - createDummyWindow(QStringLiteral("Qt5ClipboardView"), L"Qt5ClipboardView", + createDummyWindow(QStringLiteral("ClipboardView"), L"QtClipboardView", qClipboardViewerWndProc, WS_OVERLAPPED); // Try format listener API (Vista onwards) first. @@ -339,7 +337,7 @@ void QWindowsClipboard::setMimeData(QMimeData *mimeData, QClipboard::Mode mode) if (src != S_OK) { QString mimeDataFormats = mimeData ? - mimeData->formats().join(QLatin1String(", ")) : QString(QStringLiteral("NULL")); + mimeData->formats().join(u", ") : QString(QStringLiteral("NULL")); qErrnoWarning("OleSetClipboard: Failed to set mime data (%s) on clipboard: %s", qPrintable(mimeDataFormats), QWindowsContext::comErrorString(src).constData()); diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 293faf8a53..0d357b1605 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -42,6 +42,7 @@ #include "qwindowsintegration.h" #include "qwindowswindow.h" #include "qwindowskeymapper.h" +#include "qwindowsnativeinterface.h" #include "qwindowsmousehandler.h" #include "qwindowspointerhandler.h" #include "qtwindowsglobal.h" @@ -72,6 +73,7 @@ #include <QtCore/qset.h> #include <QtCore/qhash.h> +#include <QtCore/qlibraryinfo.h> #include <QtCore/qstringlist.h> #include <QtCore/qdebug.h> #include <QtCore/qoperatingsystemversion.h> @@ -183,7 +185,6 @@ static bool enableNonClientDpiScaling(HWND hwnd) \sa QWindowsShell32DLL \internal - \ingroup qt-lighthouse-win */ void QWindowsUser32DLL::init() @@ -249,7 +250,6 @@ QWindowsContext *QWindowsContext::m_instance = nullptr; Holds state information formerly stored in \c qapplication_win.cpp. \internal - \ingroup qt-lighthouse-win */ typedef QHash<HWND, QWindowsWindow *> HandleBaseWindowHash; @@ -276,8 +276,11 @@ struct QWindowsContextPrivate { bool m_asyncExpose = false; HPOWERNOTIFY m_powerNotification = nullptr; HWND m_powerDummyWindow = nullptr; + static bool m_darkMode; }; +bool QWindowsContextPrivate::m_darkMode = false; + QWindowsContextPrivate::QWindowsContextPrivate() : m_oleInitializeResult(OleInitialize(nullptr)) { @@ -292,6 +295,7 @@ QWindowsContextPrivate::QWindowsContextPrivate() m_systemInfo |= QWindowsContext::SI_RTL_Extensions; m_keyMapper.setUseRTLExtensions(true); } + m_darkMode = QWindowsTheme::queryDarkMode(); if (FAILED(m_oleInitializeResult)) { qWarning() << "QWindowsContext: OleInitialize() failed: " << QWindowsContext::comErrorString(m_oleInitializeResult); @@ -426,7 +430,7 @@ bool QWindowsContext::initPowerNotificationHandler() if (d->m_powerNotification) return false; - d->m_powerDummyWindow = createDummyWindow(QStringLiteral("QtPowerDummyWindow"), L"QtPowerDummyWindow", qWindowsPowerWindowProc); + d->m_powerDummyWindow = createDummyWindow(QStringLiteral("PowerDummyWindow"), L"QtPowerDummyWindow", qWindowsPowerWindowProc); if (!d->m_powerDummyWindow) return false; @@ -484,6 +488,11 @@ void QWindowsContext::setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiA } } +bool QWindowsContext::isDarkMode() +{ + return QWindowsContextPrivate::m_darkMode; +} + QWindowsContext *QWindowsContext::instance() { return m_instance; @@ -536,6 +545,23 @@ void QWindowsContext::setKeyGrabber(QWindow *w) d->m_keyMapper.setKeyGrabber(w); } +QString QWindowsContext::classNamePrefix() +{ + static QString result; + if (result.isEmpty()) { + QTextStream str(&result); + str << "Qt" << QT_VERSION_MAJOR << QT_VERSION_MINOR << QT_VERSION_PATCH; + if (QLibraryInfo::isDebugBuild()) + str << 'd'; +#ifdef QT_NAMESPACE +# define xstr(s) str(s) +# define str(s) #s + str << xstr(QT_NAMESPACE); +#endif + } + return result; +} + // Window class registering code (from qapplication_win.cpp) QString QWindowsContext::registerWindowClass(const QWindow *w) @@ -567,8 +593,8 @@ QString QWindowsContext::registerWindowClass(const QWindow *w) break; } // Create a unique name for the flag combination - QString cname; - cname += QLatin1String("Qt5QWindow"); + QString cname = classNamePrefix(); + cname += QLatin1String("QWindow"); switch (type) { case Qt::Tool: cname += QLatin1String("Tool"); @@ -878,7 +904,7 @@ HWND QWindowsContext::createDummyWindow(const QString &classNameIn, { if (!wndProc) wndProc = DefWindowProc; - QString className = registerWindowClass(classNameIn, wndProc); + QString className = registerWindowClass(classNamePrefix() + classNameIn, wndProc); return CreateWindowEx(0, reinterpret_cast<LPCWSTR>(className.utf16()), windowName, style, CW_USEDEFAULT, CW_USEDEFAULT, @@ -1192,9 +1218,27 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, t->displayChanged(); QWindowsWindow::displayChanged(); return d->m_screenManager.handleDisplayChange(wParam, lParam); - case QtWindows::SettingChangedEvent: + case QtWindows::SettingChangedEvent: { QWindowsWindow::settingsChanged(); + const bool darkMode = QWindowsTheme::queryDarkMode(); + if (darkMode != QWindowsContextPrivate::m_darkMode) { + QWindowsContextPrivate::m_darkMode = darkMode; + auto nativeInterface = + static_cast<QWindowsNativeInterface *>(QWindowsIntegration::instance()->nativeInterface()); + emit nativeInterface->darkModeChanged(darkMode); + const auto options = QWindowsIntegration::instance()->options(); + if ((options & QWindowsIntegration::DarkModeWindowFrames) != 0) { + for (QWindowsWindow *w : d->m_windows) + w->setDarkBorder(QWindowsContextPrivate::m_darkMode); + } + if ((options & QWindowsIntegration::DarkModeStyle) != 0) { + QWindowsTheme::instance()->refresh(); + for (QWindowsWindow *w : d->m_windows) + QWindowSystemInterface::handleThemeChange(w->window()); + } + } return d->m_screenManager.handleScreenChanges(); + } default: break; } @@ -1627,7 +1671,6 @@ static inline bool isTopLevel(HWND hwnd) There is another one for timers, sockets, etc in QEventDispatcherWin32. - \ingroup qt-lighthouse-win */ extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index 07398bd61c..c89b8b91f4 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -180,6 +180,7 @@ public: int defaultDPI() const; + static QString classNamePrefix(); QString registerWindowClass(const QWindow *w); QString registerWindowClass(QString cname, WNDPROC proc, unsigned style = 0, HBRUSH brush = nullptr, @@ -225,6 +226,8 @@ public: void setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness); static int processDpiAwareness(); + static bool isDarkMode(); + void setDetectAltGrModifier(bool a); // Returns a combination of SystemInfoFlags diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index 59457f1720..338bb9ff8f 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -73,17 +73,16 @@ Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap); \brief Cache key for storing values in a QHash with a QCursor as key. \internal - \ingroup qt-lighthouse-win */ QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c) : bitmapCacheKey(c.pixmap().cacheKey()), maskCacheKey(0) { if (!bitmapCacheKey) { - Q_ASSERT(c.bitmap()); - Q_ASSERT(c.mask()); - bitmapCacheKey = c.bitmap()->cacheKey(); - maskCacheKey = c.mask()->cacheKey(); + Q_ASSERT(!c.bitmap(Qt::ReturnByValue).isNull()); + Q_ASSERT(!c.mask(Qt::ReturnByValue).isNull()); + bitmapCacheKey = c.bitmap(Qt::ReturnByValue).cacheKey(); + maskCacheKey = c.mask(Qt::ReturnByValue).cacheKey(); } } @@ -97,7 +96,6 @@ QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c) as do the Window manager frames (resize/move handles). \internal - \ingroup qt-lighthouse-win \sa QWindowsWindowCursor */ @@ -169,9 +167,9 @@ static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits, // Create a cursor from image and mask of the format QImage::Format_Mono. static HCURSOR createBitmapCursor(const QCursor &cursor, qreal scaleFactor = 1) { - Q_ASSERT(cursor.shape() == Qt::BitmapCursor && cursor.bitmap()); - QImage bbits = cursor.bitmap()->toImage(); - QImage mbits = cursor.mask()->toImage(); + Q_ASSERT(cursor.shape() == Qt::BitmapCursor && !cursor.bitmap(Qt::ReturnByValue).isNull()); + QImage bbits = cursor.bitmap(Qt::ReturnByValue).toImage(); + QImage mbits = cursor.mask(Qt::ReturnByValue).toImage(); scaleFactor /= bbits.devicePixelRatioF(); if (!qFuzzyCompare(scaleFactor, 1)) { const QSize scaledSize = (QSizeF(bbits.size()) * scaleFactor).toSize(); @@ -816,7 +814,6 @@ HCURSOR QWindowsCursor::hCursor(const QCursor &c) const cursor handle resource. \internal - \ingroup qt-lighthouse-win \sa QWindowsCursor */ diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index b7ab952a1d..37115d5c6e 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -91,7 +91,7 @@ static inline QString guidToString(const GUID &g) str << '{' << g.Data1 << ", " << g.Data2 << ", " << g.Data3; str.setFieldWidth(2); str.setFieldAlignment(QTextStream::AlignRight); - str.setPadChar(QLatin1Char('0')); + str.setPadChar(u'0'); str << ",{" << g.Data4[0] << ", " << g.Data4[1] << ", " << g.Data4[2] << ", " << g.Data4[3] << ", " << g.Data4[4] << ", " << g.Data4[5] << ", " << g.Data4[6] << ", " << g.Data4[7] << "}};"; @@ -128,7 +128,6 @@ namespace QWindowsDialogs remove all those messages (usually 1) and post the last one with a reset button state. - \ingroup qt-lighthouse-win */ void eatMouseMove() @@ -171,7 +170,6 @@ void eatMouseMove() \sa QWindowsDialogHelperBase \internal - \ingroup qt-lighthouse-win */ class QWindowsNativeDialogBase : public QObject @@ -211,7 +209,6 @@ private: \sa QWindowsDialogThread, QWindowsNativeDialogBase \internal - \ingroup qt-lighthouse-win */ template <class BaseClass> @@ -265,7 +262,6 @@ QWindowsNativeDialogBase *QWindowsDialogHelperBase<BaseClass>::ensureNativeDialo \sa QWindowsDialogHelperBase \internal - \ingroup qt-lighthouse-win */ class QWindowsDialogThread : public QThread @@ -406,7 +402,6 @@ void QWindowsDialogHelperBase<BaseClass>::exec() does not reliably work. Provides thread-safe setters (for the non-modal case). \internal - \ingroup qt-lighthouse-win \sa QFileDialogOptions */ @@ -466,14 +461,14 @@ inline void QWindowsFileDialogSharedData::setSelectedNameFilter(const QString &f inline QList<QUrl> QWindowsFileDialogSharedData::selectedFiles() const { m_data->mutex.lock(); - const QList<QUrl> result = m_data->selectedFiles; + const auto result = m_data->selectedFiles; m_data->mutex.unlock(); return result; } inline QString QWindowsFileDialogSharedData::selectedFile() const { - const QList<QUrl> files = selectedFiles(); + const auto files = selectedFiles(); return files.isEmpty() ? QString() : files.front().toLocalFile(); } @@ -500,7 +495,6 @@ inline void QWindowsFileDialogSharedData::fromOptions(const QSharedPointer<QFile \sa QWindowsNativeFileDialogBase, QWindowsFileDialogHelper \internal - \ingroup qt-lighthouse-win */ class QWindowsNativeFileDialogBase; @@ -546,7 +540,6 @@ IFileDialogEvents *QWindowsNativeFileDialogEventHandler::create(QWindowsNativeFi \sa QWindowsNativeFileDialogBase \internal - \ingroup qt-lighthouse-win */ class QWindowsShellItem { @@ -789,7 +782,6 @@ QDebug operator<<(QDebug d, IShellItem *i) \sa QWindowsNativeFileDialogEventHandler, QWindowsFileDialogHelper \internal - \ingroup qt-lighthouse-win */ class QWindowsNativeFileDialogBase : public QWindowsNativeDialogBase @@ -915,7 +907,7 @@ IShellItem *QWindowsNativeFileDialogBase::shellItem(const QUrl &url) return nullptr; } return result; - } else if (url.scheme() == QLatin1String("clsid")) { + } else if (url.scheme() == u"clsid") { // Support for virtual folders via GUID // (see https://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx) // specified as "clsid:<GUID>" (without '{', '}'). @@ -1040,20 +1032,20 @@ static QList<FilterSpec> filterSpecs(const QStringList &filters, // Split filter specification as 'Texts (*.txt[;] *.doc)', '*.txt[;] *.doc' // into description and filters specification as '*.txt;*.doc' for (const QString &filterString : filters) { - const int openingParenPos = filterString.lastIndexOf(QLatin1Char('(')); + const int openingParenPos = filterString.lastIndexOf(u'('); const int closingParenPos = openingParenPos != -1 ? - filterString.indexOf(QLatin1Char(')'), openingParenPos + 1) : -1; + filterString.indexOf(u')', openingParenPos + 1) : -1; FilterSpec filterSpec; filterSpec.filter = closingParenPos == -1 ? filterString : filterString.mid(openingParenPos + 1, closingParenPos - openingParenPos - 1).trimmed(); if (filterSpec.filter.isEmpty()) - filterSpec.filter += QLatin1Char('*'); + filterSpec.filter += u'*'; filterSpec.filter.replace(filterSeparatorRE, separator); filterSpec.description = filterString; if (hideFilterDetails && openingParenPos != -1) { // Do not show pattern in description filterSpec.description.truncate(openingParenPos); - while (filterSpec.description.endsWith(QLatin1Char(' '))) + while (filterSpec.description.endsWith(u' ')) filterSpec.description.truncate(filterSpec.description.size() - 1); } *totalStringLength += filterSpec.filter.size() + filterSpec.description.size(); @@ -1084,8 +1076,8 @@ void QWindowsNativeFileDialogBase::setNameFilters(const QStringList &filters) // 'AAA files (a.*) (a.*)' QString description = specs[i].description; const QString &filter = specs[i].filter; - if (!m_hideFiltersDetails && !filter.startsWith(QLatin1String("*."))) { - const int pos = description.lastIndexOf(QLatin1Char('(')); + if (!m_hideFiltersDetails && !filter.startsWith(u"*.")) { + const int pos = description.lastIndexOf(u'('); if (pos > 0) description.truncate(pos); } @@ -1151,8 +1143,8 @@ static bool isHexRange(const QString& s, int start, int end) for (;start < end; ++start) { QChar ch = s.at(start); if (!(ch.isDigit() - || (ch >= QLatin1Char('a') && ch <= QLatin1Char('f')) - || (ch >= QLatin1Char('A') && ch <= QLatin1Char('F')))) + || (ch >= u'a' && ch <= u'f') + || (ch >= u'A' && ch <= u'F'))) return false; } return true; @@ -1161,7 +1153,7 @@ static bool isHexRange(const QString& s, int start, int end) static inline bool isClsid(const QString &s) { // detect "374DE290-123F-4565-9164-39C4925E467B". - const QChar dash(QLatin1Char('-')); + const QChar dash(u'-'); return s.size() == 36 && isHexRange(s, 0, 8) && s.at(8) == dash @@ -1204,7 +1196,7 @@ void QWindowsNativeFileDialogBase::selectNameFilter(const QString &filter) if (index < 0) { qWarning("%s: Invalid parameter '%s' not found in '%s'.", __FUNCTION__, qPrintable(filter), - qPrintable(m_nameFilters.join(QLatin1String(", ")))); + qPrintable(m_nameFilters.join(u", "))); return; } m_fileDialog->SetFileTypeIndex(index + 1); // one-based. @@ -1295,7 +1287,6 @@ HRESULT QWindowsNativeFileDialogEventHandler::OnFileOk(IFileDialog *) Implements single-selection methods. \internal - \ingroup qt-lighthouse-win */ class QWindowsNativeSaveFileDialog : public QWindowsNativeFileDialogBase @@ -1313,15 +1304,15 @@ public: // Also handles the simple name filter case "*.txt" -> "txt" static inline QString suffixFromFilter(const QString &filter) { - int suffixPos = filter.indexOf(QLatin1String("*.")); + int suffixPos = filter.indexOf(u"*."); if (suffixPos < 0) return QString(); suffixPos += 2; - int endPos = filter.indexOf(QLatin1Char(' '), suffixPos + 1); + int endPos = filter.indexOf(u' ', suffixPos + 1); if (endPos < 0) - endPos = filter.indexOf(QLatin1Char(';'), suffixPos + 1); + endPos = filter.indexOf(u';', suffixPos + 1); if (endPos < 0) - endPos = filter.indexOf(QLatin1Char(')'), suffixPos + 1); + endPos = filter.indexOf(u')', suffixPos + 1); if (endPos < 0) endPos = filter.size(); return filter.mid(suffixPos, endPos - suffixPos); @@ -1372,7 +1363,6 @@ QList<QUrl> QWindowsNativeSaveFileDialog::selectedFiles() const Implements multi-selection methods. \internal - \ingroup qt-lighthouse-win */ class QWindowsNativeOpenFileDialog : public QWindowsNativeFileDialogBase @@ -1406,27 +1396,27 @@ static void cleanupTemporaryItemCopies() static bool validFileNameCharacter(QChar c) { - return c.isLetterOrNumber() || c == QLatin1Char('_') || c == QLatin1Char('-'); + return c.isLetterOrNumber() || c == u'_' || c == u'-'; } QString tempFilePattern(QString name) { - const int lastSlash = qMax(name.lastIndexOf(QLatin1Char('/')), - name.lastIndexOf(QLatin1Char('\\'))); + const int lastSlash = qMax(name.lastIndexOf(u'/'), + name.lastIndexOf(u'\\')); if (lastSlash != -1) name.remove(0, lastSlash + 1); - int lastDot = name.lastIndexOf(QLatin1Char('.')); + int lastDot = name.lastIndexOf(u'.'); if (lastDot < 0) lastDot = name.size(); name.insert(lastDot, QStringLiteral("_XXXXXX")); for (int i = lastDot - 1; i >= 0; --i) { if (!validFileNameCharacter(name.at(i))) - name[i] = QLatin1Char('_'); + name[i] = u'_'; } - name.prepend(QDir::tempPath() + QLatin1Char('/')); + name.prepend(QDir::tempPath() + u'/'); return name; } @@ -1456,7 +1446,7 @@ static QString createTemporaryItemCopy(QWindowsShellItem &qItem, QString *errorM static QUrl itemToDialogUrl(QWindowsShellItem &qItem, QString *errorMessage) { QUrl url = qItem.url(); - if (url.isLocalFile() || url.scheme().startsWith(QLatin1String("http"))) + if (url.isLocalFile() || url.scheme().startsWith(u"http")) return url; const QString path = qItem.path(); if (path.isEmpty() && !qItem.isDir() && qItem.canStream()) { @@ -1545,7 +1535,6 @@ QWindowsNativeFileDialogBase *QWindowsNativeFileDialogBase::create(QFileDialogOp but only on QQuickWindows, which do not have a fallback. \internal - \ingroup qt-lighthouse-win */ class QWindowsFileDialogHelper : public QWindowsDialogHelperBase<QPlatformFileDialogHelper> @@ -1681,7 +1670,6 @@ QString QWindowsFileDialogHelper::selectedNameFilter() const \internal \sa QWindowsXpFileDialogHelper - \ingroup qt-lighthouse-win */ class QWindowsXpNativeFileDialog : public QWindowsNativeDialogBase @@ -1859,10 +1847,12 @@ void QWindowsXpNativeFileDialog::populateOpenFileName(OPENFILENAME *ofn, HWND ow // for the target. If it contains any invalid character, the dialog // will not show. ofn->nMaxFile = 65535; - const QString initiallySelectedFile = - QDir::toNativeSeparators(m_data.selectedFile()).remove(QLatin1Char('<')). - remove(QLatin1Char('>')).remove(QLatin1Char('"')).remove(QLatin1Char('|')); - ofn->lpstrFile = qStringToWCharArray(initiallySelectedFile, ofn->nMaxFile); + QString initiallySelectedFile = m_data.selectedFile(); + initiallySelectedFile.remove(u'<'); + initiallySelectedFile.remove(u'>'); + initiallySelectedFile.remove(u'"'); + initiallySelectedFile.remove(u'|'); + ofn->lpstrFile = qStringToWCharArray(QDir::toNativeSeparators(initiallySelectedFile), ofn->nMaxFile); ofn->lpstrInitialDir = qStringToWCharArray(QDir::toNativeSeparators(m_data.directory().toLocalFile())); ofn->lpstrTitle = (wchar_t*)m_title.utf16(); // Determine lpstrDefExt. Note that the current MSDN docs document this @@ -1872,7 +1862,7 @@ void QWindowsXpNativeFileDialog::populateOpenFileName(OPENFILENAME *ofn, HWND ow // the extension of the current filter". if (m_options->acceptMode() == QFileDialogOptions::AcceptSave) { QString defaultSuffix = m_options->defaultSuffix(); - if (defaultSuffix.startsWith(QLatin1Char('.'))) + if (defaultSuffix.startsWith(u'.')) defaultSuffix.remove(0, 1); // QTBUG-33156, also create empty strings to trigger the appending mechanism. ofn->lpstrDefExt = qStringToWCharArray(defaultSuffix); @@ -1905,7 +1895,7 @@ QList<QUrl> QWindowsXpNativeFileDialog::execFileNames(HWND owner, int *selectedF wchar_t *ptr = ofn.lpstrFile + dir.size() + 1; if (*ptr) { result.pop_front(); - const QString path = dir + QLatin1Char('/'); + const QString path = dir + u'/'; while (*ptr) { const QString fileName = QString::fromWCharArray(ptr); result.push_back(QUrl::fromLocalFile(path + fileName)); @@ -1927,7 +1917,6 @@ QList<QUrl> QWindowsXpNativeFileDialog::execFileNames(HWND owner, int *selectedF \sa QWindowsXpNativeFileDialog \internal - \ingroup qt-lighthouse-win */ class QWindowsXpFileDialogHelper : public QWindowsDialogHelperBase<QPlatformFileDialogHelper> @@ -2004,7 +1993,6 @@ QString QWindowsXpFileDialogHelper::selectedNameFilter() const \sa QWindowsColorDialogHelper \sa #define USE_NATIVE_COLOR_DIALOG \internal - \ingroup qt-lighthouse-win */ using SharedPointerColor = QSharedPointer<QColor>; @@ -2084,7 +2072,6 @@ void QWindowsNativeColorDialog::doExec(HWND owner) \sa #define USE_NATIVE_COLOR_DIALOG \sa QWindowsNativeColorDialog \internal - \ingroup qt-lighthouse-win */ class QWindowsColorDialogHelper : public QWindowsDialogHelperBase<QPlatformColorDialogHelper> diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index 3e4c93d47a..bb1e1345dc 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -75,7 +75,6 @@ QT_BEGIN_NAMESPACE \sa QWindowsOleDropSource \internal - \ingroup qt-lighthouse-win */ class QWindowsDragCursorWindow : public QRasterWindow @@ -135,7 +134,6 @@ void QWindowsDragCursorWindow::setPixmap(const QPixmap &p) \sa QWindowsDrag \internal - \ingroup qt-lighthouse-win */ IDataObject *QWindowsDropMimeData::retrieveDataObject() const @@ -217,7 +215,6 @@ static Qt::MouseButtons lastButtons = Qt::NoButton; \sa QWindowsDrag \internal - \ingroup qt-lighthouse-win */ class QWindowsOleDropSource : public QWindowsComBase<IDropSource> @@ -485,7 +482,6 @@ QWindowsOleDropSource::GiveFeedback(DWORD dwEffect) \sa QWindowsDrag \internal - \ingroup qt-lighthouse-win */ QWindowsOleDropTarget::QWindowsOleDropTarget(QWindow *w) : m_window(w) @@ -659,7 +655,6 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState, \class QWindowsDrag \brief Windows drag implementation. \internal - \ingroup qt-lighthouse-win */ bool QWindowsDrag::m_canceled = false; diff --git a/src/plugins/platforms/windows/qwindowsdropdataobject.cpp b/src/plugins/platforms/windows/qwindowsdropdataobject.cpp index e1a41c0ede..a06a14a980 100644 --- a/src/plugins/platforms/windows/qwindowsdropdataobject.cpp +++ b/src/plugins/platforms/windows/qwindowsdropdataobject.cpp @@ -54,7 +54,6 @@ QT_BEGIN_NAMESPACE (instead of creating local hyperlinks). \internal - \ingroup qt-lighthouse-win */ QWindowsDropDataObject::QWindowsDropDataObject(QMimeData *mimeData) : @@ -95,7 +94,7 @@ bool QWindowsDropDataObject::shouldIgnore(LPFORMATETC pformatetc) const || pformatetc->cfFormat == CF_TEXT || formatName == QStringLiteral("UniformResourceLocator") || formatName == QStringLiteral("UniformResourceLocatorW")) { - QList<QUrl> urls = dropData->urls(); + const auto urls = dropData->urls(); return std::all_of(urls.cbegin(), urls.cend(), [] (const QUrl &u) { return u.isLocalFile(); }); } } diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index e9f3dc5189..4ae087dfaa 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -63,7 +63,6 @@ QT_BEGIN_NAMESPACE there is no need to differentiate between dynamic or Angle-only builds in here. \internal - \ingroup qt-lighthouse-win */ QWindowsLibEGL QWindowsEGLStaticContext::libEGL; @@ -88,7 +87,7 @@ static void *resolveFunc(HMODULE lib, const char *name) while (!proc && argSize <= 64) { nameStr = baseNameStr; if (argSize >= 0) - nameStr += QLatin1Char('@') + QString::number(argSize); + nameStr += u'@' + QString::number(argSize); argSize = argSize < 0 ? 0 : argSize + 4; proc = (void *) ::GetProcAddress(lib, nameStr.toLatin1().constData()); } @@ -376,7 +375,6 @@ QSurfaceFormat QWindowsEGLStaticContext::formatFromConfig(EGLDisplay display, EG \endlist \internal - \ingroup qt-lighthouse-win */ QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext, diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index 8bf88300e9..6fa5a8a2b3 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -196,6 +196,7 @@ bool QWindowsOpengl32DLL::init(bool softwareRendering) wglShareLists = reinterpret_cast<BOOL (WINAPI *)(HGLRC, HGLRC)>(resolve("wglShareLists")); wglSwapBuffers = reinterpret_cast<BOOL (WINAPI *)(HDC)>(resolve("wglSwapBuffers")); wglSetPixelFormat = reinterpret_cast<BOOL (WINAPI *)(HDC, int, const PIXELFORMATDESCRIPTOR *)>(resolve("wglSetPixelFormat")); + wglDescribePixelFormat = reinterpret_cast<int (WINAPI *)(HDC, int, UINT, PIXELFORMATDESCRIPTOR *)>(resolve("wglDescribePixelFormat")); glGetError = reinterpret_cast<GLenum (APIENTRY *)()>(resolve("glGetError")); glGetIntegerv = reinterpret_cast<void (APIENTRY *)(GLenum , GLint *)>(resolve("glGetIntegerv")); @@ -214,6 +215,11 @@ BOOL QWindowsOpengl32DLL::setPixelFormat(HDC dc, int pf, const PIXELFORMATDESCRI return moduleIsNotOpengl32() ? wglSetPixelFormat(dc, pf, pfd) : SetPixelFormat(dc, pf, pfd); } +int QWindowsOpengl32DLL::describePixelFormat(HDC dc, int pf, UINT size, PIXELFORMATDESCRIPTOR *pfd) +{ + return moduleIsNotOpengl32() ? wglDescribePixelFormat(dc, pf, size, pfd) : DescribePixelFormat(dc, pf, size, pfd); +} + QWindowsOpenGLContext *QOpenGLStaticContext::createContext(QOpenGLContext *context) { return new QWindowsGLContext(this, context); @@ -322,11 +328,11 @@ static inline bool static void describeFormats(HDC hdc) { - const int pfiMax = DescribePixelFormat(hdc, 0, 0, nullptr); + const int pfiMax = QOpenGLStaticContext::opengl32.describePixelFormat(hdc, 0, 0, nullptr); for (int i = 0; i < pfiMax; i++) { PIXELFORMATDESCRIPTOR pfd; initPixelFormatDescriptor(&pfd); - DescribePixelFormat(hdc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + QOpenGLStaticContext::opengl32.describePixelFormat(hdc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd); qCDebug(lcQpaGl) << '#' << i << '/' << pfiMax << ':' << pfd; } } @@ -617,7 +623,7 @@ static int choosePixelFormat(HDC hdc, // Verify if format is acceptable. Note that the returned // formats have been observed to not contain PFD_SUPPORT_OPENGL, ignore. initPixelFormatDescriptor(obtainedPfd); - DescribePixelFormat(hdc, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), obtainedPfd); + QOpenGLStaticContext::opengl32.describePixelFormat(hdc, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), obtainedPfd); if (!isAcceptableFormat(additional, *obtainedPfd, true)) { qCDebug(lcQpaGl) << __FUNCTION__ << " obtained px #" << pixelFormat << " not acceptable=" << *obtainedPfd; @@ -796,7 +802,7 @@ static HGLRC createContext(const QOpenGLStaticContext &staticContext, static inline HWND createDummyGLWindow() { return QWindowsContext::instance()-> - createDummyWindow(QStringLiteral("QtOpenGLDummyWindow"), + createDummyWindow(QStringLiteral("OpenGLDummyWindow"), L"OpenGLDummyWindow", nullptr, WS_OVERLAPPED | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); } @@ -852,7 +858,6 @@ static inline QOpenGLContextData createDummyWindowOpenGLContextData() context and to apply to a QSurfaceFormat. \internal - \ingroup qt-lighthouse-win */ QWindowsOpenGLContextFormat QWindowsOpenGLContextFormat::current() @@ -907,7 +912,6 @@ void QWindowsOpenGLContextFormat::apply(QSurfaceFormat *format) const is a current GL context. \internal - \ingroup qt-lighthouse-win */ class QOpenGLTemporaryContext @@ -940,7 +944,6 @@ QOpenGLTemporaryContext::~QOpenGLTemporaryContext() /*! \class QWindowsOpenGLAdditionalFormat \brief Additional format information that is not in QSurfaceFormat - \ingroup qt-lighthouse-win */ /*! @@ -958,7 +961,6 @@ QOpenGLTemporaryContext::~QOpenGLTemporaryContext() \sa QWindowsGLContext \internal - \ingroup qt-lighthouse-win */ #define SAMPLE_BUFFER_EXTENSION "GL_ARB_multisample" @@ -1045,7 +1047,6 @@ QOpenGLStaticContext *QOpenGLStaticContext::create(bool softwareRendering) QOpenGLContextData and are released in doneCurrent(). \internal - \ingroup qt-lighthouse-win */ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext, diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h index 8b0c33f7d5..8794368fe4 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.h +++ b/src/plugins/platforms/windows/qwindowsglcontext.h @@ -89,7 +89,7 @@ struct QWindowsOpenGLContextFormat QSurfaceFormat::OpenGLContextProfile profile = QSurfaceFormat::NoProfile; int version = 0; //! majorVersion<<8 + minorVersion - QSurfaceFormat::FormatOptions options = nullptr; + QSurfaceFormat::FormatOptions options; }; #ifndef QT_NO_DEBUG_STREAM @@ -107,6 +107,7 @@ struct QWindowsOpengl32DLL // Wrappers. Always use these instead of SwapBuffers/wglSwapBuffers/etc. BOOL swapBuffers(HDC dc); BOOL setPixelFormat(HDC dc, int pf, const PIXELFORMATDESCRIPTOR *pfd); + int describePixelFormat(HDC dc, int pf, UINT size, PIXELFORMATDESCRIPTOR *pfd); // WGL HGLRC (WINAPI * wglCreateContext)(HDC dc); @@ -130,6 +131,7 @@ private: // For Mesa llvmpipe shipped with a name other than opengl32.dll BOOL (WINAPI * wglSwapBuffers)(HDC dc); BOOL (WINAPI * wglSetPixelFormat)(HDC dc, int pf, const PIXELFORMATDESCRIPTOR *pfd); + int (WINAPI * wglDescribePixelFormat)(HDC dc, int pf, UINT size, PIXELFORMATDESCRIPTOR *pfd); }; class QOpenGLStaticContext : public QWindowsStaticOpenGLContext diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index 19d632dc10..03be0b9451 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -160,7 +160,6 @@ Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id); // from qlocale_win.cpp needs to be checked (mouse grab might interfere with candidate window). \internal - \ingroup qt-lighthouse-win */ @@ -285,7 +284,8 @@ void QWindowsInputContext::showInputPanel() // the Surface seems unnecessary there anyway. But leave it hidden for IME. // Only trigger the native OSK if the Qt OSK is not in use. static bool imModuleEmpty = qEnvironmentVariableIsEmpty("QT_IM_MODULE"); - if (imModuleEmpty + bool nativeVKDisabled = QCoreApplication::testAttribute(Qt::AA_DisableNativeVirtualKeyboard); + if ((imModuleEmpty && !nativeVKDisabled) && QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 16299)) { ShowCaret(platformWindow->handle()); diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index d37b405db8..f4bf58ee31 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -128,7 +128,6 @@ QT_BEGIN_NAMESPACE QWindowsUser32DLL and QWindowsShell32DLL. All function pointers should go to these structs to avoid lookups in several places. - \ingroup qt-lighthouse-win */ struct QWindowsIntegrationPrivate @@ -162,7 +161,7 @@ bool parseIntOption(const QString ¶meter,const QLatin1String &option, IntType minimumValue, IntType maximumValue, IntType *target) { const int valueLength = parameter.size() - option.size() - 1; - if (valueLength < 1 || !parameter.startsWith(option) || parameter.at(option.size()) != QLatin1Char('=')) + if (valueLength < 1 || !parameter.startsWith(option) || parameter.at(option.size()) != u'=') return false; bool ok; const QStringRef valueRef = parameter.rightRef(valueLength); @@ -186,39 +185,43 @@ static inline unsigned parseOptions(const QStringList ¶mList, { unsigned options = 0; for (const QString ¶m : paramList) { - if (param.startsWith(QLatin1String("fontengine="))) { - if (param.endsWith(QLatin1String("freetype"))) { + if (param.startsWith(u"fontengine=")) { + if (param.endsWith(u"freetype")) { options |= QWindowsIntegration::FontDatabaseFreeType; - } else if (param.endsWith(QLatin1String("native"))) { + } else if (param.endsWith(u"native")) { options |= QWindowsIntegration::FontDatabaseNative; } - } else if (param.startsWith(QLatin1String("dialogs="))) { - if (param.endsWith(QLatin1String("xp"))) { + } else if (param.startsWith(u"dialogs=")) { + if (param.endsWith(u"xp")) { options |= QWindowsIntegration::XpNativeDialogs; - } else if (param.endsWith(QLatin1String("none"))) { + } else if (param.endsWith(u"none")) { options |= QWindowsIntegration::NoNativeDialogs; } - } else if (param == QLatin1String("altgr")) { + } else if (param == u"altgr") { options |= QWindowsIntegration::DetectAltGrModifier; - } else if (param == QLatin1String("gl=gdi")) { + } else if (param == u"gl=gdi") { options |= QWindowsIntegration::DisableArb; - } else if (param == QLatin1String("nodirectwrite")) { + } else if (param == u"nodirectwrite") { options |= QWindowsIntegration::DontUseDirectWriteFonts; - } else if (param == QLatin1String("nocolorfonts")) { + } else if (param == u"nocolorfonts") { options |= QWindowsIntegration::DontUseColorFonts; - } else if (param == QLatin1String("nomousefromtouch")) { + } else if (param == u"nomousefromtouch") { options |= QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch; } else if (parseIntOption(param, QLatin1String("verbose"), 0, INT_MAX, &QWindowsContext::verbose) || parseIntOption(param, QLatin1String("tabletabsoluterange"), 0, INT_MAX, tabletAbsoluteRange) || parseIntOption(param, QLatin1String("dpiawareness"), QtWindows::ProcessDpiUnaware, QtWindows::ProcessPerMonitorDpiAware, dpiAwareness)) { - } else if (param == QLatin1String("menus=native")) { + } else if (param == u"menus=native") { options |= QWindowsIntegration::AlwaysUseNativeMenus; - } else if (param == QLatin1String("menus=none")) { + } else if (param == u"menus=none") { options |= QWindowsIntegration::NoNativeMenus; - } else if (param == QLatin1String("nowmpointer")) { + } else if (param == u"nowmpointer") { options |= QWindowsIntegration::DontUseWMPointer; - } else if (param == QLatin1String("reverse")) { + } else if (param == u"reverse") { options |= QWindowsIntegration::RtlEnabled; + } else if (param == u"darkmode=1") { + options |= QWindowsIntegration::DarkModeWindowFrames; + } else if (param == u"darkmode=2") { + options |= QWindowsIntegration::DarkModeWindowFrames | QWindowsIntegration::DarkModeStyle; } else { qWarning() << "Unknown option" << param; } diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h index b49d21022b..1f16d13769 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.h +++ b/src/plugins/platforms/windows/qwindowsintegration.h @@ -70,7 +70,9 @@ public: NoNativeMenus = 0x200, DontUseWMPointer = 0x400, DetectAltGrModifier = 0x800, - RtlEnabled = 0x1000 + RtlEnabled = 0x1000, + DarkModeWindowFrames = 0x2000, + DarkModeStyle = 0x4000 }; explicit QWindowsIntegration(const QStringList ¶mList); diff --git a/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp b/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp index 44b7523fa6..ad3f02f83b 100644 --- a/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp +++ b/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp @@ -60,7 +60,6 @@ \sa QInternalMimeData, QWindowsMime, QWindowsMimeConverter \internal - \ingroup qt-lighthouse-win */ bool QWindowsInternalMimeData::hasFormat_sys(const QString &mime) const diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index 4f0f846749..4f46c05f7a 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -88,7 +88,6 @@ QT_BEGIN_NAMESPACE \class QWindowsKeyMapper \brief Translates Windows keys to QWindowSystemInterface events. \internal - \ingroup qt-lighthouse-win In addition, handles some special keys to display system menus, etc. The code originates from \c qkeymapper_win.cpp. @@ -1019,14 +1018,14 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg, if (dirStatus == VK_LSHIFT && ((msg.wParam == VK_SHIFT && GetKeyState(VK_LCONTROL)) || (msg.wParam == VK_CONTROL && GetKeyState(VK_LSHIFT)))) { - sendExtendedPressRelease(receiver, Qt::Key_Direction_L, nullptr, + sendExtendedPressRelease(receiver, Qt::Key_Direction_L, {}, scancode, vk_key, nModifiers, QString(), false); result = true; dirStatus = 0; } else if (dirStatus == VK_RSHIFT && ( (msg.wParam == VK_SHIFT && GetKeyState(VK_RCONTROL)) || (msg.wParam == VK_CONTROL && GetKeyState(VK_RSHIFT)))) { - sendExtendedPressRelease(receiver, Qt::Key_Direction_R, nullptr, + sendExtendedPressRelease(receiver, Qt::Key_Direction_R, {}, scancode, vk_key, nModifiers, QString(), false); result = true; dirStatus = 0; @@ -1388,7 +1387,7 @@ QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) { const Qt::KeyboardModifiers missingMods = keyMods & ~neededMods; const int matchedKey = int(key) + missingMods; - const QList<int>::iterator it = + const auto it = std::find_if(result.begin(), result.end(), [key] (int k) { return (k & ~Qt::KeyboardModifierMask) == key; }); // QTBUG-67200: Use the match with the least modifiers (prefer diff --git a/src/plugins/platforms/windows/qwindowsmenu.cpp b/src/plugins/platforms/windows/qwindowsmenu.cpp index 221e4ff6ec..5f21bdfa33 100644 --- a/src/plugins/platforms/windows/qwindowsmenu.cpp +++ b/src/plugins/platforms/windows/qwindowsmenu.cpp @@ -65,7 +65,6 @@ QT_BEGIN_NAMESPACE Qt Widgets, either the containers or the items might be deleted first. \internal - \ingroup qt-lighthouse-win */ static uint nextId = 1; @@ -445,7 +444,7 @@ QString QWindowsMenuItem::nativeText() const QString result = m_text; #if QT_CONFIG(shortcut) if (!m_shortcut.isEmpty()) { - result += QLatin1Char('\t'); + result += u'\t'; result += m_shortcut.toString(QKeySequence::NativeText); } #endif diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp index b9d8b191f5..6733ab9fed 100644 --- a/src/plugins/platforms/windows/qwindowsmime.cpp +++ b/src/plugins/platforms/windows/qwindowsmime.cpp @@ -107,7 +107,7 @@ static inline QByteArray msgConversionError(const char *func, const char *format msg += ": Unable to convert DIB image. The image converter plugin for '"; msg += format; msg += "' is not available. Available formats: "; - const QList<QByteArray> &formats = QImageReader::supportedImageFormats(); + const auto &formats = QImageReader::supportedImageFormats(); for (const QByteArray &af : formats) { msg += af; msg += ' '; @@ -447,7 +447,6 @@ QDebug operator<<(QDebug d, IDataObject *dataObj) \class QWindowsMime \brief The QWindowsMime class maps open-standard MIME to Window Clipboard formats. \internal - \ingroup qt-lighthouse-win Qt's drag-and-drop and clipboard facilities use the MIME standard. On X11, this maps trivially to the Xdnd protocol, but on Windows @@ -635,11 +634,11 @@ bool QWindowsMimeText::convertFromMime(const FORMATETC &formatetc, const QMimeDa int ri = 0; bool cr = false; for (int i=0; i < s; ++i) { - if (*u == QLatin1Char('\r')) + if (*u == u'\r') cr = true; else { - if (*u == QLatin1Char('\n') && !cr) - res[ri++] = QLatin1Char('\r'); + if (*u == u'\n' && !cr) + res[ri++] = u'\r'; cr = false; } res[ri++] = *u; @@ -663,7 +662,7 @@ bool QWindowsMimeText::convertFromMime(const FORMATETC &formatetc, const QMimeDa bool QWindowsMimeText::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const { - return mimeType.startsWith(QLatin1String("text/plain")) + return mimeType.startsWith(u"text/plain") && (canGetData(CF_UNICODETEXT, pDataObj) || canGetData(CF_TEXT, pDataObj)); } @@ -680,7 +679,7 @@ QString QWindowsMimeText::mimeForFormat(const FORMATETC &formatetc) const QVector<FORMATETC> QWindowsMimeText::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const { QVector<FORMATETC> formatics; - if (mimeType.startsWith(QLatin1String("text/plain")) && mimeData->hasText()) { + if (mimeType.startsWith(u"text/plain") && mimeData->hasText()) { formatics += setCf(CF_UNICODETEXT); formatics += setCf(CF_TEXT); } @@ -747,7 +746,7 @@ QWindowsMimeURI::QWindowsMimeURI() bool QWindowsMimeURI::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const { if (mimeData->hasUrls() && getCf(formatetc) == CF_HDROP) { - const QList<QUrl> urls = mimeData->urls(); + const auto urls = mimeData->urls(); for (const QUrl &url : urls) { if (url.isLocalFile()) return true; @@ -760,7 +759,7 @@ bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeDat { if (canConvertFromMime(formatetc, mimeData)) { if (getCf(formatetc) == CF_HDROP) { - const QList<QUrl> &urls = mimeData->urls(); + const auto &urls = mimeData->urls(); QStringList fileNames; int size = sizeof(DROPFILES)+2; for (const QUrl &url : urls) { @@ -791,7 +790,7 @@ bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeDat return setData(result, pmedium); } if (getCf(formatetc) == CF_INETURL_W) { - QList<QUrl> urls = mimeData->urls(); + const auto urls = mimeData->urls(); QByteArray result; if (!urls.isEmpty()) { QString url = urls.at(0).toString(); @@ -803,7 +802,7 @@ bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeDat return setData(result, pmedium); } if (getCf(formatetc) == CF_INETURL) { - QList<QUrl> urls = mimeData->urls(); + const auto urls = mimeData->urls(); QByteArray result; if (!urls.isEmpty()) result = urls.at(0).toString().toLocal8Bit(); @@ -816,7 +815,7 @@ bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeDat bool QWindowsMimeURI::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const { - return mimeType == QLatin1String("text/uri-list") + return mimeType == u"text/uri-list" && (canGetData(CF_HDROP, pDataObj) || canGetData(CF_INETURL_W, pDataObj) || canGetData(CF_INETURL, pDataObj)); } @@ -831,7 +830,7 @@ QString QWindowsMimeURI::mimeForFormat(const FORMATETC &formatetc) const QVector<FORMATETC> QWindowsMimeURI::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const { QVector<FORMATETC> formatics; - if (mimeType == QLatin1String("text/uri-list")) { + if (mimeType == u"text/uri-list") { if (canConvertFromMime(setCf(CF_HDROP), mimeData)) formatics += setCf(CF_HDROP); if (canConvertFromMime(setCf(CF_INETURL_W), mimeData)) @@ -844,7 +843,7 @@ QVector<FORMATETC> QWindowsMimeURI::formatsForMime(const QString &mimeType, cons QVariant QWindowsMimeURI::convertToMime(const QString &mimeType, LPDATAOBJECT pDataObj, QVariant::Type preferredType) const { - if (mimeType == QLatin1String("text/uri-list")) { + if (mimeType == u"text/uri-list") { if (canGetData(CF_HDROP, pDataObj)) { QList<QVariant> urls; @@ -916,7 +915,7 @@ QWindowsMimeHtml::QWindowsMimeHtml() QVector<FORMATETC> QWindowsMimeHtml::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const { QVector<FORMATETC> formatetcs; - if (mimeType == QLatin1String("text/html") && (!mimeData->html().isEmpty())) + if (mimeType == u"text/html" && (!mimeData->html().isEmpty())) formatetcs += setCf(CF_HTML); return formatetcs; } @@ -930,7 +929,7 @@ QString QWindowsMimeHtml::mimeForFormat(const FORMATETC &formatetc) const bool QWindowsMimeHtml::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const { - return mimeType == QLatin1String("text/html") && canGetData(CF_HTML, pDataObj); + return mimeType == u"text/html" && canGetData(CF_HTML, pDataObj); } @@ -1053,7 +1052,7 @@ QWindowsMimeImage::QWindowsMimeImage() QVector<FORMATETC> QWindowsMimeImage::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const { QVector<FORMATETC> formatetcs; - if (mimeData->hasImage() && mimeType == QLatin1String("application/x-qt-image")) { + if (mimeData->hasImage() && mimeType == u"application/x-qt-image") { //add DIBV5 if image has alpha channel. Do not add CF_PNG here as it will confuse MS Office (QTBUG47656). auto image = qvariant_cast<QImage>(mimeData->imageData()); if (!image.isNull() && image.hasAlphaChannel()) @@ -1075,7 +1074,7 @@ QString QWindowsMimeImage::mimeForFormat(const FORMATETC &formatetc) const bool QWindowsMimeImage::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const { - return mimeType == QLatin1String("application/x-qt-image") + return mimeType == u"application/x-qt-image" && (canGetData(CF_DIB, pDataObj) || canGetData(CF_PNG, pDataObj)); } @@ -1149,7 +1148,7 @@ QVariant QWindowsMimeImage::convertToMime(const QString &mimeType, IDataObject * { Q_UNUSED(preferredType); QVariant result; - if (mimeType != QLatin1String("application/x-qt-image")) + if (mimeType != u"application/x-qt-image") return result; //Try to convert from a format which has more data //DIBV5, use only if its is not synthesized @@ -1220,7 +1219,7 @@ bool QBuiltInMimes::convertFromMime(const FORMATETC &formatetc, const QMimeData { if (canConvertFromMime(formatetc, mimeData)) { QByteArray data; - if (outFormats.value(getCf(formatetc)) == QLatin1String("text/html")) { + if (outFormats.value(getCf(formatetc)) == u"text/html") { // text/html is in wide chars on windows (compatible with mozillia) QString html = mimeData->html(); // same code as in the text converter up above @@ -1232,11 +1231,11 @@ bool QBuiltInMimes::convertFromMime(const FORMATETC &formatetc, const QMimeData int ri = 0; bool cr = false; for (int i=0; i < s; ++i) { - if (*u == QLatin1Char('\r')) + if (*u == u'\r') cr = true; else { - if (*u == QLatin1Char('\n') && !cr) - res[ri++] = QLatin1Char('\r'); + if (*u == u'\n' && !cr) + res[ri++] = u'\r'; cr = false; } res[ri++] = *u; @@ -1285,7 +1284,7 @@ QVariant QBuiltInMimes::convertToMime(const QString &mimeType, IDataObject *pDat QByteArray data = getData(inFormats.key(mimeType), pDataObj); if (!data.isEmpty()) { qCDebug(lcQpaMime) << __FUNCTION__; - if (mimeType == QLatin1String("text/html") && preferredType == QVariant::String) { + if (mimeType == u"text/html" && preferredType == QVariant::String) { // text/html is in wide chars on windows (compatible with Mozilla) val = QString::fromWCharArray(reinterpret_cast<const wchar_t *>(data.constData())); } else { @@ -1404,12 +1403,12 @@ static bool isCustomMimeType(const QString &mimeType) static QString customMimeType(const QString &mimeType, int *lindex = nullptr) { int len = sizeof(x_qt_windows_mime) - 1; - int n = mimeType.lastIndexOf(QLatin1Char('\"')) - len; + int n = mimeType.lastIndexOf(u'\"') - len; QString ret = mimeType.mid(len, n); - const int beginPos = mimeType.indexOf(QLatin1String(";index=")); + const int beginPos = mimeType.indexOf(u";index="); if (beginPos > -1) { - const int endPos = mimeType.indexOf(QLatin1Char(';'), beginPos + 1); + const int endPos = mimeType.indexOf(u';', beginPos + 1); const int indexStartPos = beginPos + 7; if (lindex) *lindex = mimeType.midRef(indexStartPos, endPos == -1 ? endPos : endPos - indexStartPos).toInt(); @@ -1480,7 +1479,7 @@ QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const } } if (!ianaType) - format = QLatin1String(x_qt_windows_mime) + clipFormat + QLatin1Char('\"'); + format = QLatin1String(x_qt_windows_mime) + clipFormat + u'"'; else format = clipFormat; } @@ -1495,7 +1494,6 @@ QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const \class QWindowsMimeConverter \brief Manages the list of QWindowsMime instances. \internal - \ingroup qt-lighthouse-win \sa QWindowsMime */ diff --git a/src/plugins/platforms/windows/qwindowsmime.h b/src/plugins/platforms/windows/qwindowsmime.h index 1c389e8800..f8708f1259 100644 --- a/src/plugins/platforms/windows/qwindowsmime.h +++ b/src/plugins/platforms/windows/qwindowsmime.h @@ -43,7 +43,6 @@ #include <QtCore/qt_windows.h> #include <QtCore/qvector.h> -#include <QtCore/qlist.h> #include <QtCore/qvariant.h> QT_BEGIN_NAMESPACE @@ -95,7 +94,7 @@ public: private: void ensureInitialized() const; - mutable QList<QWindowsMime *> m_mimes; + mutable QVector<QWindowsMime *> m_mimes; mutable int m_internalMimeCount = 0; }; diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 6df5e6aa27..1b2d831268 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -145,7 +145,6 @@ static inline QTouchDevice *createTouchDevice() Dispatches mouse and touch events. Separate for code cleanliness. \internal - \ingroup qt-lighthouse-win */ QWindowsMouseHandler::QWindowsMouseHandler() = default; @@ -165,7 +164,7 @@ void QWindowsMouseHandler::clearEvents() Qt::MouseButtons QWindowsMouseHandler::queryMouseButtons() { - Qt::MouseButtons result = nullptr; + Qt::MouseButtons result; const bool mouseSwapped = GetSystemMetrics(SM_SWAPBUTTON); if (GetAsyncKeyState(VK_LBUTTON) < 0) result |= mouseSwapped ? Qt::RightButton: Qt::LeftButton; @@ -630,7 +629,7 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, QTouchPointList touchPoints; touchPoints.reserve(winTouchPointCount); - Qt::TouchPointStates allStates = nullptr; + Qt::TouchPointStates allStates; GetTouchInputInfo(reinterpret_cast<HTOUCHINPUT>(msg.lParam), UINT(msg.wParam), winTouchInputs.data(), sizeof(TOUCHINPUT)); diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp index d1d181d66e..1195f15a59 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp @@ -47,6 +47,7 @@ #include "qwindowsopengltester.h" #include "qwindowsintegration.h" #include "qwindowsmime.h" +#include "qwindowstheme.h" #include "qwin10helpers.h" #include <QtGui/qwindow.h> @@ -316,4 +317,15 @@ QVariant QWindowsNativeInterface::gpuList() const return result; } +bool QWindowsNativeInterface::isDarkMode() const +{ + return QWindowsContext::isDarkMode(); +} + +// Dark mode support level 2 (style) +bool QWindowsNativeInterface::isDarkModeStyle() const +{ + return (QWindowsIntegration::instance()->options() & QWindowsIntegration::DarkModeStyle) != 0; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.h b/src/plugins/platforms/windows/qwindowsnativeinterface.h index ce395dc5a4..387f65ae8f 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.h +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.h @@ -58,13 +58,14 @@ QT_BEGIN_NAMESPACE \endlist \internal - \ingroup qt-lighthouse-win */ class QWindowsNativeInterface : public QPlatformNativeInterface { Q_OBJECT Q_PROPERTY(bool asyncExpose READ asyncExpose WRITE setAsyncExpose) + Q_PROPERTY(bool darkMode READ isDarkMode STORED false NOTIFY darkModeChanged) + Q_PROPERTY(bool darkModeStyle READ isDarkModeStyle STORED false) Q_PROPERTY(QVariant gpu READ gpu STORED false) Q_PROPERTY(QVariant gpuList READ gpuList STORED false) @@ -92,6 +93,9 @@ public: bool asyncExpose() const; void setAsyncExpose(bool value); + bool isDarkMode() const; + bool isDarkModeStyle() const; + QVariant gpu() const; QVariant gpuList() const; @@ -109,6 +113,9 @@ public: QFunctionPointer platformFunction(const QByteArray &function) const override; +Q_SIGNALS: + void darkModeChanged(bool); + private: static QWindowsWindowFunctions::WindowActivationBehavior m_windowActivationBehavior; }; diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp index f3450e2806..0a7fef6c30 100644 --- a/src/plugins/platforms/windows/qwindowsole.cpp +++ b/src/plugins/platforms/windows/qwindowsole.cpp @@ -70,7 +70,6 @@ QT_BEGIN_NAMESPACE \endlist \internal - \ingroup qt-lighthouse-win */ QWindowsOleDataObject::QWindowsOleDataObject(QMimeData *mimeData) : @@ -228,7 +227,6 @@ QWindowsOleDataObject::EnumDAdvise(LPENUMSTATDATA FAR*) \class QWindowsOleEnumFmtEtc \brief Enumerates the FORMATETC structures supported by QWindowsOleDataObject. \internal - \ingroup qt-lighthouse-win */ QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector<FORMATETC> &fmtetcs) diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp index afc1991e2c..72092a4481 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.cpp +++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp @@ -206,7 +206,7 @@ QString GpuDescription::toString() const str << " Card name : " << description << "\n Driver Name : " << driverName << "\n Driver Version : " << driverVersion.toString() - << "\n Vendor ID : 0x" << qSetPadChar(QLatin1Char('0')) + << "\n Vendor ID : 0x" << qSetPadChar(u'0') << Qt::uppercasedigits << Qt::hex << qSetFieldWidth(4) << vendorId << "\n Device ID : 0x" << qSetFieldWidth(4) << deviceId << "\n SubSys ID : 0x" << qSetFieldWidth(8) << subSysId @@ -285,7 +285,7 @@ static inline QString resolveBugListFile(const QString &fileName) // then resolve via QStandardPaths::ConfigLocation. const QString settingsPath = QLibraryInfo::location(QLibraryInfo::SettingsPath); if (!settingsPath.isEmpty()) { // SettingsPath is empty unless specified in qt.conf. - const QFileInfo fi(settingsPath + QLatin1Char('/') + fileName); + const QFileInfo fi(settingsPath + u'/' + fileName); if (fi.isFile()) return fi.absoluteFilePath(); } diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp index b477147da7..fba24d8696 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp +++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp @@ -482,7 +482,7 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd, << " message=" << Qt::hex << msg.message << " count=" << Qt::dec << count; - Qt::TouchPointStates allStates = nullptr; + Qt::TouchPointStates allStates; for (quint32 i = 0; i < count; ++i) { if (QWindowsContext::verbose > 1) diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index df63adf558..9a4f8d152c 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -73,7 +73,7 @@ static inline QDpi monitorDPI(HMONITOR hMonitor) return {0, 0}; } -using WindowsScreenDataList = QList<QWindowsScreenData>; +using WindowsScreenDataList = QVector<QWindowsScreenData>; static bool monitorData(HMONITOR hMonitor, QWindowsScreenData *data) { @@ -87,7 +87,7 @@ static bool monitorData(HMONITOR hMonitor, QWindowsScreenData *data) data->geometry = QRect(QPoint(info.rcMonitor.left, info.rcMonitor.top), QPoint(info.rcMonitor.right - 1, info.rcMonitor.bottom - 1)); data->availableGeometry = QRect(QPoint(info.rcWork.left, info.rcWork.top), QPoint(info.rcWork.right - 1, info.rcWork.bottom - 1)); data->name = QString::fromWCharArray(info.szDevice); - if (data->name == QLatin1String("WinDisc")) { + if (data->name == u"WinDisc") { data->flags |= QWindowsScreenData::LockScreen; } else { if (const HDC hdc = CreateDC(info.szDevice, nullptr, nullptr, nullptr)) { @@ -171,7 +171,6 @@ static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d) \brief Windows screen. \sa QWindowsScreenManager \internal - \ingroup qt-lighthouse-win */ QWindowsScreen::QWindowsScreen(const QWindowsScreenData &data) : @@ -432,7 +431,6 @@ QPlatformScreen::SubpixelAntialiasingType QWindowsScreen::subpixelAntialiasingTy \sa QWindowsScreen \internal - \ingroup qt-lighthouse-win */ QWindowsScreenManager::QWindowsScreenManager() = default; @@ -467,7 +465,7 @@ bool QWindowsScreenManager::handleDisplayChange(WPARAM wParam, LPARAM lParam) return false; } -static inline int indexOfMonitor(const QList<QWindowsScreen *> &screens, +static inline int indexOfMonitor(const QWindowsScreenManager::WindowsScreenList &screens, const QString &monitorName) { for (int i= 0; i < screens.size(); ++i) @@ -476,7 +474,7 @@ static inline int indexOfMonitor(const QList<QWindowsScreen *> &screens, return -1; } -static inline int indexOfMonitor(const QList<QWindowsScreenData> &screenData, +static inline int indexOfMonitor(const WindowsScreenDataList &screenData, const QString &monitorName) { for (int i = 0; i < screenData.size(); ++i) diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h index 2fd56f53cf..5c095808f2 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.h +++ b/src/plugins/platforms/windows/qwindowsscreen.h @@ -127,7 +127,7 @@ private: class QWindowsScreenManager { public: - using WindowsScreenList = QList<QWindowsScreen *>; + using WindowsScreenList = QVector<QWindowsScreen *>; QWindowsScreenManager(); diff --git a/src/plugins/platforms/windows/qwindowsservices.cpp b/src/plugins/platforms/windows/qwindowsservices.cpp index 83b052bb49..6a2708ee26 100644 --- a/src/plugins/platforms/windows/qwindowsservices.cpp +++ b/src/plugins/platforms/windows/qwindowsservices.cpp @@ -92,7 +92,7 @@ static inline QString mailCommand() // "rundll32.exe .. url.dll,MailToProtocolHandler %l" is returned. Launching it // silently fails or brings up a broken dialog after a long time, so exclude it and // fall back to ShellExecute() which brings up the URL assocation dialog. - if (command.isEmpty() || command.contains(QLatin1String(",MailToProtocolHandler"))) + if (command.isEmpty() || command.contains(u",MailToProtocolHandler")) return QString(); wchar_t expandedCommand[MAX_PATH] = {0}; return ExpandEnvironmentStrings(reinterpret_cast<const wchar_t *>(command.utf16()), @@ -108,7 +108,7 @@ static inline bool launchMail(const QUrl &url) return false; } //Make sure the path for the process is in quotes - const QChar doubleQuote = QLatin1Char('"'); + const QChar doubleQuote = u'"'; if (!command.startsWith(doubleQuote)) { const int exeIndex = command.indexOf(QStringLiteral(".exe "), 0, Qt::CaseInsensitive); if (exeIndex != -1) { @@ -140,7 +140,7 @@ static inline bool launchMail(const QUrl &url) bool QWindowsServices::openUrl(const QUrl &url) { const QString scheme = url.scheme(); - if (scheme == QLatin1String("mailto") && launchMail(url)) + if (scheme == u"mailto" && launchMail(url)) return true; return shellExecute(url); } diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp index 9409d2db4d..def011e4bd 100644 --- a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp +++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp @@ -168,7 +168,7 @@ static inline HWND createTrayIconMessageWindow() return nullptr; // Register window class in the platform plugin. const QString className = - ctx->registerWindowClass(QStringLiteral("QTrayIconMessageWindowClass"), + ctx->registerWindowClass(QWindowsContext::classNamePrefix() + QStringLiteral("TrayIconMessageWindowClass"), qWindowsTrayIconWndProc); const wchar_t windowName[] = L"QTrayIconMessageWindow"; return CreateWindowEx(0, reinterpret_cast<const wchar_t *>(className.utf16()), @@ -184,7 +184,6 @@ static inline HWND createTrayIconMessageWindow() \brief Windows native system tray icon \internal - \ingroup qt-lighthouse-win */ QWindowsSystemTrayIcon::QWindowsSystemTrayIcon() @@ -261,7 +260,7 @@ void QWindowsSystemTrayIcon::showMessage(const QString &title, const QString &me // For empty messages, ensures that they show when only title is set QString message = messageIn; if (message.isEmpty() && !title.isEmpty()) - message.append(QLatin1Char(' ')); + message.append(u' '); NOTIFYICONDATA tnd; initNotifyIconData(tnd); diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp index cd5a78abb6..287ba931d9 100644 --- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp +++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp @@ -173,7 +173,6 @@ QWindowsWinTab32DLL QWindowsTabletSupport::m_winTab32DLL; \brief Functions from wintabl32.dll shipped with WACOM tablets used by QWindowsTabletSupport. \internal - \ingroup qt-lighthouse-win */ bool QWindowsWinTab32DLL::init() @@ -205,7 +204,6 @@ bool QWindowsWinTab32DLL::init() \internal \since 5.2 - \ingroup qt-lighthouse-win */ QWindowsTabletSupport::QWindowsTabletSupport(HWND window, HCTX context) diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index 40f9652cbd..7f47cd712f 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -63,6 +63,7 @@ #include <QtCore/qcoreapplication.h> #include <QtCore/qdebug.h> #include <QtCore/qtextstream.h> +#include <QtCore/qoperatingsystemversion.h> #include <QtCore/qsysinfo.h> #include <QtCore/qcache.h> #include <QtCore/qthread.h> @@ -78,6 +79,7 @@ #include <QtFontDatabaseSupport/private/qwindowsfontdatabase_p.h> #include <private/qhighdpiscaling_p.h> #include <private/qsystemlibrary_p.h> +#include <private/qwinregistry_p.h> #include <algorithm> @@ -96,7 +98,7 @@ static inline QTextStream& operator<<(QTextStream &str, const QColor &c) { str.setIntegerBase(16); str.setFieldWidth(2); - str.setPadChar(QLatin1Char('0')); + str.setPadChar(u'0'); str << " rgb: #" << c.red() << c.green() << c.blue(); str.setIntegerBase(10); str.setFieldWidth(0); @@ -164,7 +166,7 @@ public: QMutexLocker readyLocker(&m_readyMutex); while (!m_cancelled.loadRelaxed()) { if (!m_params && !m_cancelled.loadRelaxed() - && !m_readyCondition.wait(&m_readyMutex, 1000)) + && !m_readyCondition.wait(&m_readyMutex, QDeadlineTimer(1000ll))) continue; if (m_params) { @@ -189,7 +191,7 @@ public: CoUninitialize(); } - bool runWithParams(QShGetFileInfoParams *params, unsigned long timeOutMSecs) + bool runWithParams(QShGetFileInfoParams *params, qint64 timeOutMSecs) { QMutexLocker doneLocker(&m_doneMutex); @@ -198,7 +200,7 @@ public: m_readyCondition.wakeAll(); m_readyMutex.unlock(); - return m_doneCondition.wait(&m_doneMutex, timeOutMSecs); + return m_doneCondition.wait(&m_doneMutex, QDeadlineTimer(timeOutMSecs)); } void cancel() @@ -220,7 +222,7 @@ private: static bool shGetFileInfoBackground(const QString &fileName, DWORD attributes, SHFILEINFO *info, UINT flags, - unsigned long timeOutMSecs = 5000) + qint64 timeOutMSecs = 5000) { static QShGetFileInfoThread *getFileInfoThread = nullptr; if (!getFileInfoThread) { @@ -241,6 +243,14 @@ static bool shGetFileInfoBackground(const QString &fileName, DWORD attributes, return result; } +// Dark Mode constants +enum DarkModeColors : QRgb { + darkModeBtnHighlightRgb = 0xc0c0c0, + darkModeBtnShadowRgb = 0x808080, + darkModeHighlightRgb = 0x0055ff, // deviating from 0x800080 + darkModeMenuHighlightRgb = darkModeHighlightRgb +}; + // from QStyle::standardPalette static inline QPalette standardPalette() { @@ -258,23 +268,55 @@ static inline QPalette standardPalette() return palette; } -static inline QPalette systemPalette() +static void populateLightSystemBasePalette(QPalette &result) { - QPalette result = standardPalette(); result.setColor(QPalette::WindowText, getSysColor(COLOR_WINDOWTEXT)); - result.setColor(QPalette::Button, getSysColor(COLOR_BTNFACE)); - result.setColor(QPalette::Light, getSysColor(COLOR_BTNHIGHLIGHT)); + const QColor btnFace = getSysColor(COLOR_BTNFACE); + result.setColor(QPalette::Button, btnFace); + const QColor btnHighlight = getSysColor(COLOR_BTNHIGHLIGHT); + result.setColor(QPalette::Light, btnHighlight); result.setColor(QPalette::Dark, getSysColor(COLOR_BTNSHADOW)); result.setColor(QPalette::Mid, result.button().color().darker(150)); result.setColor(QPalette::Text, getSysColor(COLOR_WINDOWTEXT)); - result.setColor(QPalette::BrightText, getSysColor(COLOR_BTNHIGHLIGHT)); + result.setColor(QPalette::BrightText, btnHighlight); result.setColor(QPalette::Base, getSysColor(COLOR_WINDOW)); - result.setColor(QPalette::Window, getSysColor(COLOR_BTNFACE)); + result.setColor(QPalette::Window, btnFace); result.setColor(QPalette::ButtonText, getSysColor(COLOR_BTNTEXT)); result.setColor(QPalette::Midlight, getSysColor(COLOR_3DLIGHT)); result.setColor(QPalette::Shadow, getSysColor(COLOR_3DDKSHADOW)); result.setColor(QPalette::Highlight, getSysColor(COLOR_HIGHLIGHT)); result.setColor(QPalette::HighlightedText, getSysColor(COLOR_HIGHLIGHTTEXT)); +} + +static void populateDarkSystemBasePalette(QPalette &result) +{ + const QColor darkModeWindowText = Qt::white; + result.setColor(QPalette::WindowText, darkModeWindowText); + const QColor darkModebtnFace = Qt::black; + result.setColor(QPalette::Button, darkModebtnFace); + const QColor btnHighlight = QColor(darkModeBtnHighlightRgb); + result.setColor(QPalette::Light, btnHighlight); + result.setColor(QPalette::Dark, QColor(darkModeBtnShadowRgb)); + result.setColor(QPalette::Mid, result.button().color().darker(150)); + result.setColor(QPalette::Text, darkModeWindowText); + result.setColor(QPalette::BrightText, btnHighlight); + result.setColor(QPalette::Base, darkModebtnFace); + result.setColor(QPalette::Window, darkModebtnFace); + result.setColor(QPalette::ButtonText, darkModeWindowText); + result.setColor(QPalette::Midlight, darkModeWindowText); + result.setColor(QPalette::Shadow, darkModeWindowText); + result.setColor(QPalette::Highlight, QColor(darkModeHighlightRgb)); + result.setColor(QPalette::HighlightedText, darkModeWindowText); +} + +static QPalette systemPalette(bool light) +{ + QPalette result = standardPalette(); + if (light) + populateLightSystemBasePalette(result); + else + populateDarkSystemBasePalette(result); + result.setColor(QPalette::Link, Qt::blue); result.setColor(QPalette::LinkVisited, Qt::magenta); result.setColor(QPalette::Inactive, QPalette::Button, result.button().color()); @@ -300,19 +342,19 @@ static inline QPalette systemPalette() result.setColor(QPalette::Disabled, QPalette::Text, disabled); result.setColor(QPalette::Disabled, QPalette::ButtonText, disabled); result.setColor(QPalette::Disabled, QPalette::Highlight, - getSysColor(COLOR_HIGHLIGHT)); + light ? getSysColor(COLOR_HIGHLIGHT) : QColor(darkModeHighlightRgb)); result.setColor(QPalette::Disabled, QPalette::HighlightedText, - getSysColor(COLOR_HIGHLIGHTTEXT)); + light ? getSysColor(COLOR_HIGHLIGHTTEXT) : QColor(Qt::white)); result.setColor(QPalette::Disabled, QPalette::Base, result.window().color()); return result; } -static inline QPalette toolTipPalette(const QPalette &systemPalette) +static inline QPalette toolTipPalette(const QPalette &systemPalette, bool light) { QPalette result(systemPalette); - const QColor tipBgColor(getSysColor(COLOR_INFOBK)); - const QColor tipTextColor(getSysColor(COLOR_INFOTEXT)); + const QColor tipBgColor = light ? getSysColor(COLOR_INFOBK) : QColor(Qt::black); + const QColor tipTextColor = light ? getSysColor(COLOR_INFOTEXT) : QColor(Qt::white); result.setColor(QPalette::All, QPalette::Button, tipBgColor); result.setColor(QPalette::All, QPalette::Window, tipBgColor); @@ -337,12 +379,13 @@ static inline QPalette toolTipPalette(const QPalette &systemPalette) return result; } -static inline QPalette menuPalette(const QPalette &systemPalette) +static inline QPalette menuPalette(const QPalette &systemPalette, bool light) { QPalette result(systemPalette); - const QColor menuColor(getSysColor(COLOR_MENU)); - const QColor menuTextColor(getSysColor(COLOR_MENUTEXT)); - const QColor disabled(getSysColor(COLOR_GRAYTEXT)); + const QColor menuColor = light ? getSysColor(COLOR_MENU) : QColor(Qt::black); + const QColor menuTextColor = light ? getSysColor(COLOR_MENUTEXT) : QColor(Qt::white); + const QColor disabled = light + ? getSysColor(COLOR_GRAYTEXT) : QColor(darkModeBtnHighlightRgb); // we might need a special color group for the result. result.setColor(QPalette::Active, QPalette::Button, menuColor); result.setColor(QPalette::Active, QPalette::Text, menuTextColor); @@ -351,8 +394,10 @@ static inline QPalette menuPalette(const QPalette &systemPalette) result.setColor(QPalette::Disabled, QPalette::WindowText, disabled); result.setColor(QPalette::Disabled, QPalette::Text, disabled); const bool isFlat = booleanSystemParametersInfo(SPI_GETFLATMENU, false); - result.setColor(QPalette::Disabled, QPalette::Highlight, - getSysColor(isFlat ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT)); + const QColor highlightColor = light + ? (getSysColor(isFlat ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT)) + : QColor(darkModeMenuHighlightRgb); + result.setColor(QPalette::Disabled, QPalette::Highlight, highlightColor); result.setColor(QPalette::Disabled, QPalette::HighlightedText, disabled); result.setColor(QPalette::Disabled, QPalette::Button, result.color(QPalette::Active, QPalette::Button)); @@ -373,12 +418,12 @@ static inline QPalette menuPalette(const QPalette &systemPalette) return result; } -static inline QPalette *menuBarPalette(const QPalette &menuPalette) +static inline QPalette *menuBarPalette(const QPalette &menuPalette, bool light) { QPalette *result = nullptr; if (booleanSystemParametersInfo(SPI_GETFLATMENU, false)) { result = new QPalette(menuPalette); - const QColor menubar(getSysColor(COLOR_MENUBAR)); + const QColor menubar(light ? getSysColor(COLOR_MENUBAR) : QColor(Qt::black)); result->setColor(QPalette::Active, QPalette::Button, menubar); result->setColor(QPalette::Disabled, QPalette::Button, menubar); result->setColor(QPalette::Inactive, QPalette::Button, menubar); @@ -485,10 +530,26 @@ void QWindowsTheme::refreshPalettes() if (!QGuiApplication::desktopSettingsAware()) return; - m_palettes[SystemPalette] = new QPalette(systemPalette()); - m_palettes[ToolTipPalette] = new QPalette(toolTipPalette(*m_palettes[SystemPalette])); - m_palettes[MenuPalette] = new QPalette(menuPalette(*m_palettes[SystemPalette])); - m_palettes[MenuBarPalette] = menuBarPalette(*m_palettes[MenuPalette]); + const bool light = + !QWindowsContext::isDarkMode() + || (QWindowsIntegration::instance()->options() & QWindowsIntegration::DarkModeStyle) == 0; + m_palettes[SystemPalette] = new QPalette(systemPalette(light)); + m_palettes[ToolTipPalette] = new QPalette(toolTipPalette(*m_palettes[SystemPalette], light)); + m_palettes[MenuPalette] = new QPalette(menuPalette(*m_palettes[SystemPalette], light)); + m_palettes[MenuBarPalette] = menuBarPalette(*m_palettes[MenuPalette], light); + if (!light) { + m_palettes[ButtonPalette] = new QPalette(*m_palettes[SystemPalette]); + m_palettes[ButtonPalette]->setColor(QPalette::Button, QColor(0x666666u)); + const QColor checkBoxBlue(0x0078d7u); + const QColor white(Qt::white); + m_palettes[CheckBoxPalette] = new QPalette(*m_palettes[SystemPalette]); + m_palettes[CheckBoxPalette]->setColor(QPalette::Window, checkBoxBlue); + m_palettes[CheckBoxPalette]->setColor(QPalette::Base, checkBoxBlue); + m_palettes[CheckBoxPalette]->setColor(QPalette::Button, checkBoxBlue); + m_palettes[CheckBoxPalette]->setColor(QPalette::ButtonText, white); + m_palettes[RadioButtonPalette] = new QPalette(*m_palettes[CheckBoxPalette]); + + } } void QWindowsTheme::clearFonts() @@ -497,6 +558,12 @@ void QWindowsTheme::clearFonts() std::fill(m_fonts, m_fonts + NFonts, nullptr); } +void QWindowsTheme::refresh() +{ + refreshPalettes(); + refreshFonts(); +} + void QWindowsTheme::refreshFonts() { clearFonts(); @@ -731,13 +798,13 @@ static QString dirIconPixmapCacheKey(int iIcon, int iconSize, int imageListSize) { QString key = QLatin1String("qt_dir_") + QString::number(iIcon); if (iconSize == SHGFI_LARGEICON) - key += QLatin1Char('l'); + key += u'l'; switch (imageListSize) { case sHIL_EXTRALARGE: - key += QLatin1Char('e'); + key += u'e'; break; case sHIL_JUMBO: - key += QLatin1Char('j'); + key += u'j'; break; } return key; @@ -815,9 +882,9 @@ QString QWindowsFileIconEngine::cacheKey() const // It is faster to just look at the file extensions; // avoiding slow QFileInfo::isExecutable() (QTBUG-13182) QString suffix = fileInfo().suffix(); - if (!suffix.compare(QLatin1String("exe"), Qt::CaseInsensitive) - || !suffix.compare(QLatin1String("lnk"), Qt::CaseInsensitive) - || !suffix.compare(QLatin1String("ico"), Qt::CaseInsensitive)) { + if (!suffix.compare(u"exe", Qt::CaseInsensitive) + || !suffix.compare(u"lnk", Qt::CaseInsensitive) + || !suffix.compare(u"ico", Qt::CaseInsensitive)) { return QString(); } return QLatin1String("qt_.") @@ -946,6 +1013,23 @@ bool QWindowsTheme::useNativeMenus() return result; } +bool QWindowsTheme::queryDarkMode() +{ + if (QOperatingSystemVersion::current() + < QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 17763) + || queryHighContrast()) { + return false; + } + const auto setting = QWinRegistryKey(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)") + .dwordValue(L"AppsUseLightTheme"); + return setting.second && setting.first == 0; +} + +bool QWindowsTheme::queryHighContrast() +{ + return booleanSystemParametersInfo(SPI_GETHIGHCONTRAST, false); +} + QPlatformMenuItem *QWindowsTheme::createPlatformMenuItem() const { qCDebug(lcQpaMenus) << __FUNCTION__; diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h index 07120230ce..af28f2878c 100644 --- a/src/plugins/platforms/windows/qwindowstheme.h +++ b/src/plugins/platforms/windows/qwindowstheme.h @@ -71,7 +71,7 @@ public: QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const override; - QIcon fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions = nullptr) const override; + QIcon fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions = {}) const override; void windowsThemeChanged(QWindow *window); void displayChanged() { refreshIconPixmapSizes(); } @@ -84,13 +84,15 @@ public: void showPlatformMenuBar() override; static bool useNativeMenus(); + static bool queryDarkMode(); + static bool queryHighContrast(); void refreshFonts(); + void refresh(); static const char *name; private: - void refresh() { refreshPalettes(); refreshFonts(); } void clearPalettes(); void refreshPalettes(); void clearFonts(); diff --git a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h index ffe2e62069..a31e00c0ac 100644 --- a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h +++ b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h @@ -55,7 +55,6 @@ QT_BEGIN_NAMESPACE to be done by using QWaitCondition/QMutex. \internal - \ingroup qt-lighthouse-win */ class QWindowsThreadPoolRunner { diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 04478d5f1f..6b53e3d4c4 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -253,7 +253,7 @@ QDebug operator<<(QDebug d, const GUID &guid) { QDebugStateSaver saver(d); d.nospace(); - d << '{' << Qt::hex << Qt::uppercasedigits << qSetPadChar(QLatin1Char('0')) + d << '{' << Qt::hex << Qt::uppercasedigits << qSetPadChar(u'0') << qSetFieldWidth(8) << guid.Data1 << qSetFieldWidth(0) << '-' << qSetFieldWidth(4) << guid.Data2 << qSetFieldWidth(0) << '-' << qSetFieldWidth(4) @@ -489,7 +489,6 @@ static QMargins invisibleMargins(QPoint screenPoint) \sa QWindowCreationContext \internal - \ingroup qt-lighthouse-win */ struct WindowCreationData @@ -592,7 +591,7 @@ static QPoint calcPosition(const QWindow *w, const QWindowCreationContextPtr &co return posFrame; // Find the original screen containing the coordinates. - const QList<QScreen *> screens = screenForGL->virtualSiblings(); + const auto screens = screenForGL->virtualSiblings(); const QScreen *orgScreen = nullptr; for (QScreen *screen : screens) { if (screen->handle()->availableGeometry().contains(posFrame)) { @@ -749,6 +748,11 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag } } +static inline bool shouldApplyDarkFrame(const QWindow *w) +{ + return w->isTopLevel() && !w->flags().testFlag(Qt::FramelessWindowHint); +} + QWindowsWindowData WindowCreationData::create(const QWindow *w, const WindowData &data, QString title) const { @@ -816,6 +820,12 @@ QWindowsWindowData return result; } + if (QWindowsContext::isDarkMode() + && (QWindowsIntegration::instance()->options() & QWindowsIntegration::DarkModeWindowFrames) != 0 + && shouldApplyDarkFrame(w)) { + QWindowsWindow::setDarkBorderToWindow(result.hwnd, true); + } + if (mirrorParentWidth != 0) { context->obtainedPos.setX(mirrorParentWidth - context->obtainedSize.width() - context->obtainedPos.x()); @@ -906,7 +916,6 @@ static QSize toNativeSizeConstrained(QSize dip, const QScreen *s) into account. \internal - \ingroup qt-lighthouse-win */ QMargins QWindowsGeometryHint::frameOnPrimaryScreen(DWORD style, DWORD exStyle) @@ -1076,7 +1085,6 @@ bool QWindowsGeometryHint::positionIncludesFrame(const QWindow *w) \since 5.6 \internal - \ingroup qt-lighthouse-win */ bool QWindowsBaseWindow::isRtlLayout(HWND hwnd) @@ -1165,7 +1173,6 @@ QPoint QWindowsBaseWindow::mapFromGlobal(const QPoint &pos) const \brief Window wrapping GetDesktopWindow not allowing any manipulation. \since 5.6 \internal - \ingroup qt-lighthouse-win */ /*! @@ -1178,7 +1185,6 @@ QPoint QWindowsBaseWindow::mapFromGlobal(const QPoint &pos) const \since 5.6 \internal - \ingroup qt-lighthouse-win */ QWindowsForeignWindow::QWindowsForeignWindow(QWindow *window, HWND hwnd) @@ -1237,7 +1243,6 @@ void QWindowsForeignWindow::setVisible(bool visible) \sa WindowCreationData, QWindowsContext \internal - \ingroup qt-lighthouse-win */ QWindowCreationContext::QWindowCreationContext(const QWindow *w, const QScreen *s, @@ -1307,7 +1312,6 @@ void QWindowCreationContext::applyToMinMaxInfo(MINMAXINFO *mmi) const \endlist \internal - \ingroup qt-lighthouse-win */ const char *QWindowsWindow::embeddedNativeParentHandleProperty = "_q_embedded_native_parent_handle"; @@ -1397,6 +1401,11 @@ void QWindowsWindow::fireExpose(const QRegion ®ion, bool force) QWindowSystemInterface::handleExposeEvent(window(), region); } +void QWindowsWindow::fireFullExpose(bool force) +{ + fireExpose(QRect(QPoint(0, 0), m_data.geometry.size()), force); +} + void QWindowsWindow::destroyWindow() { qCDebug(lcQpaWindows) << __FUNCTION__ << this << window() << m_data.hwnd; @@ -1557,7 +1566,7 @@ void QWindowsWindow::setVisible(bool visible) // over the rendering of the window // There is nobody waiting for this, so we don't need to flush afterwards. if (isLayered()) - fireExpose(QRect(0, 0, win->width(), win->height())); + fireFullExpose(); // QTBUG-44928, QTBUG-7386: This is to resolve the problem where popups are // opened from the system tray and not being implicitly activated @@ -1900,12 +1909,13 @@ void QWindowsWindow::handleResized(int wParam) handleWindowStateChange(m_windowState | Qt::WindowMinimized); return; case SIZE_MAXIMIZED: + handleGeometryChange(); if (!testFlag(WithinSetStyle) && !testFlag(WithinSetGeometry)) handleWindowStateChange(Qt::WindowMaximized | (isFullScreen_sys() ? Qt::WindowFullScreen : Qt::WindowNoState)); - handleGeometryChange(); break; case SIZE_RESTORED: + handleGeometryChange(); if (!testFlag(WithinSetStyle) && !testFlag(WithinSetGeometry)) { if (isFullScreen_sys()) handleWindowStateChange( @@ -1914,7 +1924,6 @@ void QWindowsWindow::handleResized(int wParam) else if (m_windowState != Qt::WindowNoState && !testFlag(MaximizeToFullScreen)) handleWindowStateChange(Qt::WindowNoState); } - handleGeometryChange(); break; } } @@ -1962,7 +1971,7 @@ void QWindowsWindow::handleGeometryChange() && m_data.geometry.size() != previousGeometry.size() // Exclude plain move // One dimension grew -> Windows will send expose, no need to synthesize. && !(m_data.geometry.width() > previousGeometry.width() || m_data.geometry.height() > previousGeometry.height())) { - fireExpose(QRect(QPoint(0, 0), m_data.geometry.size()), true); + fireFullExpose(true); } const bool wasSync = testFlag(SynchronousGeometryChangeEvent); @@ -2161,7 +2170,7 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state) QWindow *w = window(); bool exposeEventsSent = false; if (isLayered()) { - fireExpose(QRegion(0, 0, w->width(), w->height())); + fireFullExpose(); exposeEventsSent = true; } const QWindowList allWindows = QGuiApplication::allWindows(); @@ -2169,7 +2178,7 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state) if (child != w && child->isVisible() && child->transientParent() == w) { QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(child); if (platformWindow && platformWindow->isLayered()) { - platformWindow->fireExpose(QRegion(0, 0, child->width(), child->height())); + platformWindow->fireFullExpose(); exposeEventsSent = true; } } @@ -2283,8 +2292,10 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowStates newState) if (!screen) screen = QGuiApplication::primaryScreen(); // That area of the virtual desktop might not be covered by a screen anymore. - if (!screen->geometry().intersects(m_savedFrameGeometry)) - m_savedFrameGeometry.moveTo(screen->geometry().topLeft()); + if (const auto platformScreen = screen->handle()) { + if (!platformScreen->geometry().intersects(m_savedFrameGeometry)) + m_savedFrameGeometry.moveTo(platformScreen->geometry().topLeft()); + } if (newState & Qt::WindowMinimized) { setMinimizedGeometry(m_data.hwnd, m_savedFrameGeometry); @@ -2602,37 +2613,41 @@ bool QWindowsWindow::setMouseGrabEnabled(bool grab) return grab; } -static inline DWORD cornerToWinOrientation(Qt::Corner corner) +static inline DWORD edgesToWinOrientation(Qt::Edges edges) { - switch (corner) { - case Qt::TopLeftCorner: - return 0xf004; // SZ_SIZETOPLEFT; - case Qt::TopRightCorner: - return 0xf005; // SZ_SIZETOPRIGHT - case Qt::BottomLeftCorner: - return 0xf007; // SZ_SIZEBOTTOMLEFT - case Qt::BottomRightCorner: - return 0xf008; // SZ_SIZEBOTTOMRIGHT - } - return 0; + if (edges == Qt::LeftEdge) + return 0xf001; // SC_SIZELEFT; + else if (edges == (Qt::RightEdge)) + return 0xf002; // SC_SIZERIGHT + else if (edges == (Qt::TopEdge)) + return 0xf003; // SC_SIZETOP + else if (edges == (Qt::TopEdge | Qt::LeftEdge)) + return 0xf004; // SC_SIZETOPLEFT + else if (edges == (Qt::TopEdge | Qt::RightEdge)) + return 0xf005; // SC_SIZETOPRIGHT + else if (edges == (Qt::BottomEdge)) + return 0xf006; // SC_SIZEBOTTOM + else if (edges == (Qt::BottomEdge | Qt::LeftEdge)) + return 0xf007; // SC_SIZEBOTTOMLEFT + else if (edges == (Qt::BottomEdge | Qt::RightEdge)) + return 0xf008; // SC_SIZEBOTTOMRIGHT + + return 0xf000; // SC_SIZE } -bool QWindowsWindow::startSystemResize(const QPoint &, Qt::Corner corner) +bool QWindowsWindow::startSystemResize(Qt::Edges edges) { - if (!GetSystemMenu(m_data.hwnd, FALSE)) + if (Q_UNLIKELY(window()->flags().testFlag(Qt::MSWindowsFixedSizeDialogHint))) return false; ReleaseCapture(); - PostMessage(m_data.hwnd, WM_SYSCOMMAND, cornerToWinOrientation(corner), 0); + PostMessage(m_data.hwnd, WM_SYSCOMMAND, edgesToWinOrientation(edges), 0); setFlag(SizeGripOperation); return true; } -bool QWindowsWindow::startSystemMove(const QPoint &) +bool QWindowsWindow::startSystemMove() { - if (!GetSystemMenu(m_data.hwnd, FALSE)) - return false; - ReleaseCapture(); PostMessage(m_data.hwnd, WM_SYSCOMMAND, 0xF012 /*SC_DRAGMOVE*/, 0); return true; @@ -2901,6 +2916,39 @@ bool QWindowsWindow::isTopLevel() const return window()->isTopLevel() && !m_data.embedded; } +enum : WORD { + DwmwaUseImmersiveDarkMode = 20, + DwmwaUseImmersiveDarkModeBefore20h1 = 19 +}; + +static bool queryDarkBorder(HWND hwnd) +{ + BOOL result = FALSE; + const bool ok = + SUCCEEDED(DwmGetWindowAttribute(hwnd, DwmwaUseImmersiveDarkMode, &result, sizeof(result))) + || SUCCEEDED(DwmGetWindowAttribute(hwnd, DwmwaUseImmersiveDarkModeBefore20h1, &result, sizeof(result))); + if (!ok) + qWarning("%s: Unable to retrieve dark window border setting.", __FUNCTION__); + return result == TRUE; +} + +bool QWindowsWindow::setDarkBorderToWindow(HWND hwnd, bool d) +{ + const BOOL darkBorder = d ? TRUE : FALSE; + const bool ok = + SUCCEEDED(DwmSetWindowAttribute(hwnd, DwmwaUseImmersiveDarkMode, &darkBorder, sizeof(darkBorder))) + || SUCCEEDED(DwmSetWindowAttribute(hwnd, DwmwaUseImmersiveDarkModeBefore20h1, &darkBorder, sizeof(darkBorder))); + if (!ok) + qWarning("%s: Unable to set dark window border.", __FUNCTION__); + return ok; +} + +void QWindowsWindow::setDarkBorder(bool d) +{ + if (shouldApplyDarkFrame(window()) && queryDarkBorder(m_data.hwnd) != d) + setDarkBorderToWindow(m_data.hwnd, d); +} + QWindowsMenuBar *QWindowsWindow::menuBar() const { return m_menuBar.data(); diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index aaf02d2a81..cd6179bf03 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -277,8 +277,8 @@ public: bool setMouseGrabEnabled(bool grab) override; inline bool hasMouseCapture() const { return GetCapture() == m_data.hwnd; } - bool startSystemResize(const QPoint &pos, Qt::Corner corner) override; - bool startSystemMove(const QPoint &pos) override; + bool startSystemResize(Qt::Edges edges) override; + bool startSystemMove() override; void setFrameStrutEventsEnabled(bool enabled) override; bool frameStrutEventsEnabled() const override { return testFlag(FrameStrutEventsEnabled); } @@ -287,6 +287,9 @@ public: HWND handle() const override { return m_data.hwnd; } bool isTopLevel() const override; + static bool setDarkBorderToWindow(HWND hwnd, bool d); + void setDarkBorder(bool d); + QWindowsMenuBar *menuBar() const; void setMenuBar(QWindowsMenuBar *mb); @@ -370,6 +373,7 @@ private: void handleWindowStateChange(Qt::WindowStates state); inline void destroyIcon(); void fireExpose(const QRegion ®ion, bool force=false); + void fireFullExpose(bool force=false); void calculateFullFrameMargins(); mutable QWindowsWindowData m_data; diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp index c89dea3dfb..3962d2d27f 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp @@ -166,11 +166,27 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve } if (event->value().type() == QVariant::String) { if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { - // Notifies changes in string values. - VARIANT oldVal, newVal; - clearVariant(&oldVal); - setVariantString(event->value().toString(), &newVal); - QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal); + + // Tries to notify the change using UiaRaiseNotificationEvent(), which is only available on + // Windows 10 version 1709 or newer. Otherwise uses UiaRaiseAutomationPropertyChangedEvent(). + + BSTR displayString = bStrFromQString(event->value().toString()); + BSTR activityId = bStrFromQString(QString()); + + HRESULT hr = QWindowsUiaWrapper::instance()->raiseNotificationEvent(provider, NotificationKind_Other, + NotificationProcessing_ImportantMostRecent, + displayString, activityId); + + ::SysFreeString(displayString); + ::SysFreeString(activityId); + + if (hr == static_cast<HRESULT>(UIA_E_NOTSUPPORTED)) { + VARIANT oldVal, newVal; + clearVariant(&oldVal); + setVariantString(event->value().toString(), &newVal); + QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal); + ::SysFreeString(newVal.bstrVal); + } } } else if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) { if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { @@ -289,11 +305,9 @@ HRESULT QWindowsUiaMainProvider::GetPatternProvider(PATTERNID idPattern, IUnknow } break; case UIA_TogglePatternId: - // Checkbox controls. - if (accessible->role() == QAccessible::CheckBox - || (accessible->role() == QAccessible::MenuItem && accessible->state().checkable)) { + // Checkboxes and other checkable controls. + if (accessible->state().checkable) *pRetVal = new QWindowsUiaToggleProvider(id()); - } break; case UIA_SelectionPatternId: // Lists of items. @@ -402,12 +416,14 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR // Control type converted from role. auto controlType = roleToControlTypeId(accessible->role()); - // The native OSK should be disbled if the Qt OSK is in use. + // The native OSK should be disbled if the Qt OSK is in use, + // or if disabled via application attribute. static bool imModuleEmpty = qEnvironmentVariableIsEmpty("QT_IM_MODULE"); + bool nativeVKDisabled = QCoreApplication::testAttribute(Qt::AA_DisableNativeVirtualKeyboard); // If we want to disable the native OSK auto-showing // we have to report text fields as non-editable. - if (controlType == UIA_EditControlTypeId && !imModuleEmpty) + if (controlType == UIA_EditControlTypeId && (!imModuleEmpty || nativeVKDisabled)) controlType = UIA_TextControlTypeId; setVariantI4(controlType, pRetVal); @@ -455,6 +471,10 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR setVariantBool(wt == Qt::Popup || wt == Qt::ToolTip || wt == Qt::SplashScreen, pRetVal); } break; + case UIA_IsDialogPropertyId: + setVariantBool(accessible->role() == QAccessible::Dialog + || accessible->role() == QAccessible::AlertMessage, pRetVal); + break; case UIA_FullDescriptionPropertyId: setVariantString(accessible->text(QAccessible::Description), pRetVal); break; @@ -482,7 +502,7 @@ QString QWindowsUiaMainProvider::automationIdForAccessible(const QAccessibleInte if (name.isEmpty()) return QString(); if (!result.isEmpty()) - result.prepend(QLatin1Char('.')); + result.prepend(u'.'); result.prepend(name); obj = obj->parent(); } diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp index 3305e9c5c4..fb41012cf4 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp @@ -49,6 +49,7 @@ #include <QtCore/qloggingcategory.h> #include <QtCore/qstring.h> #include <QtCore/qlist.h> +#include <QtCore/qvector.h> QT_BEGIN_NAMESPACE @@ -78,7 +79,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::GetSelection(SAFEARRAY * return UIA_E_ELEMENTNOTAVAILABLE; // First put selected items in a list, then build a safe array with the right size. - QList<QAccessibleInterface *> selectedList; + QVector<QAccessibleInterface *> selectedList; for (int i = 0; i < accessible->childCount(); ++i) { if (QAccessibleInterface *child = accessible->child(i)) { if (child->state().selected) { diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp index 2a94012590..1348ec7cc0 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp @@ -80,7 +80,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTableItemProvider::GetRowHeaderItems(SAFEAR if (!tableCellInterface) return UIA_E_ELEMENTNOTAVAILABLE; - QList<QAccessibleInterface *> headers = tableCellInterface->rowHeaderCells(); + const auto headers = tableCellInterface->rowHeaderCells(); if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) { for (LONG i = 0; i < headers.size(); ++i) { @@ -110,7 +110,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTableItemProvider::GetColumnHeaderItems(SAF if (!tableCellInterface) return UIA_E_ELEMENTNOTAVAILABLE; - QList<QAccessibleInterface *> headers = tableCellInterface->columnHeaderCells(); + const auto headers = tableCellInterface->columnHeaderCells(); if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) { for (LONG i = 0; i < headers.size(); ++i) { diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp index ab04384616..682b8c19c0 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp @@ -161,7 +161,7 @@ long roleToControlTypeId(QAccessible::Role role) {QAccessible::Sound, UIA_CustomControlTypeId}, {QAccessible::Cursor, UIA_CustomControlTypeId}, {QAccessible::Caret, UIA_CustomControlTypeId}, - {QAccessible::AlertMessage, UIA_CustomControlTypeId}, + {QAccessible::AlertMessage, UIA_WindowControlTypeId}, {QAccessible::Window, UIA_WindowControlTypeId}, {QAccessible::Client, UIA_GroupControlTypeId}, {QAccessible::PopupMenu, UIA_MenuControlTypeId}, diff --git a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp index 114d6dacd8..fee8063f13 100644 --- a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp +++ b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp @@ -397,7 +397,15 @@ bool QWinRTFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit RETURN_FALSE_IF_FAILED_WITH_ARGS("Failed to set default file extension \"%s\"", qPrintable(suffix)); } - const QString suggestedName = QFileInfo(d->saveFileName.toLocalFile()).fileName(); + QString suggestedName = QFileInfo(d->saveFileName.toLocalFile()).fileName(); + if (suggestedName.isEmpty() && dialogOptions->initiallySelectedFiles().size() > 0) + suggestedName = QFileInfo(dialogOptions->initiallySelectedFiles().first().toLocalFile()) + .fileName(); + if (suggestedName.isEmpty()) { + const auto fileInfo = QFileInfo(dialogOptions->initialDirectory().toLocalFile()); + if (!fileInfo.isDir()) + suggestedName = fileInfo.fileName(); + } if (!suggestedName.isEmpty()) { HStringReference nativeSuggestedName(reinterpret_cast<const wchar_t *>(suggestedName.utf16()), uint(suggestedName.length())); diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h index c3ce8d8745..fda53f17a1 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h @@ -52,7 +52,7 @@ class QXcbEglContext : public QEGLPlatformContext public: QXcbEglContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share, EGLDisplay display, const QVariant &nativeHandle) - : QEGLPlatformContext(glFormat, share, display, 0, nativeHandle) + : QEGLPlatformContext(glFormat, share, display, nullptr, nativeHandle) { } diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp index 65beac227c..30e3381993 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp @@ -93,7 +93,7 @@ void QXcbEglWindow::create() { QXcbWindow::create(); - m_surface = eglCreateWindowSurface(m_glIntegration->eglDisplay(), m_config, m_window, 0); + m_surface = eglCreateWindowSurface(m_glIntegration->eglDisplay(), m_config, m_window, nullptr); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp index 2b77062b16..75189a9c80 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -223,13 +223,13 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat const QVariant &nativeHandle) : QPlatformOpenGLContext() , m_display(static_cast<Display *>(screen->connection()->xlib_display())) - , m_config(0) - , m_context(0) - , m_shareContext(0) + , m_config(nullptr) + , m_context(nullptr) + , m_shareContext(nullptr) , m_format(format) , m_isPBufferCurrent(false) , m_ownsContext(nativeHandle.isNull()) - , m_getGraphicsResetStatus(0) + , m_getGraphicsResetStatus(nullptr) , m_lost(false) { if (nativeHandle.isNull()) @@ -254,14 +254,14 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share) GLXFBConfig config = qglx_findConfig(m_display, screen->screenNumber(), m_format); m_config = config; - XVisualInfo *visualInfo = 0; + XVisualInfo *visualInfo = nullptr; Window window = 0; // Temporary window used to query OpenGL context if (config) { const QByteArrayList glxExt = QByteArray(glXQueryExtensionsString(m_display, screen->screenNumber())).split(' '); // Resolve entry point for glXCreateContextAttribsARB - glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; + glXCreateContextAttribsARBProc glXCreateContextAttribsARB = nullptr; if (glxExt.contains("GLX_ARB_create_context")) glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); @@ -271,7 +271,7 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share) // Use glXCreateContextAttribsARB if available // Also, GL ES context creation requires GLX_EXT_create_context_es2_profile - if (glXCreateContextAttribsARB != 0 + if (glXCreateContextAttribsARB != nullptr && (m_format.renderableType() != QSurfaceFormat::OpenGLES || (supportsProfiles && glxExt.contains("GLX_EXT_create_context_es2_profile")))) { // Try to create an OpenGL context for each known OpenGL version in descending // order from the requested version. @@ -358,9 +358,9 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share) m_context = glXCreateContextAttribsARB(m_display, config, m_shareContext, true, contextAttributes.data()); if (!m_context && m_shareContext) { // re-try without a shared glx context - m_context = glXCreateContextAttribsARB(m_display, config, 0, true, contextAttributes.data()); + m_context = glXCreateContextAttribsARB(m_display, config, nullptr, true, contextAttributes.data()); if (m_context) - m_shareContext = 0; + m_shareContext = nullptr; } } } @@ -375,9 +375,9 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share) m_context = glXCreateNewContext(m_display, config, GLX_RGBA_TYPE, m_shareContext, true); if (!m_context && m_shareContext) { // re-try without a shared glx context - m_context = glXCreateNewContext(m_display, config, GLX_RGBA_TYPE, 0, true); + m_context = glXCreateNewContext(m_display, config, GLX_RGBA_TYPE, nullptr, true); if (m_context) - m_shareContext = 0; + m_shareContext = nullptr; } } @@ -399,7 +399,7 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share) m_context = glXCreateContext(m_display, visualInfo, m_shareContext, true); if (!m_context && m_shareContext) { // re-try without a shared glx context - m_shareContext = 0; + m_shareContext = nullptr; m_context = glXCreateContext(m_display, visualInfo, nullptr, true); } @@ -429,7 +429,7 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share, const qWarning("QGLXContext: Requires a QGLXNativeContext"); return; } - QGLXNativeContext handle = nativeHandle.value<QGLXNativeContext>(); + QGLXNativeContext handle = qvariant_cast<QGLXNativeContext>(nativeHandle); GLXContext context = handle.context(); if (!context) { qWarning("QGLXContext: No GLXContext given"); @@ -444,7 +444,7 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share, const // Legacy contexts created using glXCreateContext are created using a visual // and the FBConfig cannot be queried. The only way to adapt these contexts // is to figure out the visual id. - XVisualInfo *vinfo = 0; + XVisualInfo *vinfo = nullptr; // If the VisualID is provided use it. VisualID vid = handle.visualId(); if (!vid) { @@ -464,13 +464,13 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share, const vinfo = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask, &v, &n); if (n < 1) { XFree(vinfo); - vinfo = 0; + vinfo = nullptr; } } // For contexts created with an FBConfig using the modern functions providing the // visual or window is not mandatory. Just query the config from the context. - GLXFBConfig config = 0; + GLXFBConfig config = nullptr; if (!vinfo) { int configId = 0; if (glXQueryContext(dpy, context, GLX_FBCONFIG_ID, &configId) != Success) { @@ -595,8 +595,8 @@ bool QGLXContext::makeCurrent(QPlatformSurface *surface) if (interval >= 0 && interval != window->swapInterval() && screen) { typedef void (*qt_glXSwapIntervalEXT)(Display *, GLXDrawable, int); typedef void (*qt_glXSwapIntervalMESA)(unsigned int); - static qt_glXSwapIntervalEXT glXSwapIntervalEXT = 0; - static qt_glXSwapIntervalMESA glXSwapIntervalMESA = 0; + static qt_glXSwapIntervalEXT glXSwapIntervalEXT = nullptr; + static qt_glXSwapIntervalMESA glXSwapIntervalMESA = nullptr; static bool resolved = false; if (!resolved) { resolved = true; @@ -621,9 +621,9 @@ bool QGLXContext::makeCurrent(QPlatformSurface *surface) void QGLXContext::doneCurrent() { if (m_isPBufferCurrent) - glXMakeContextCurrent(m_display, 0, 0, 0); + glXMakeContextCurrent(m_display, 0, 0, nullptr); else - glXMakeCurrent(m_display, 0, 0); + glXMakeCurrent(m_display, 0, nullptr); m_isPBufferCurrent = false; } @@ -658,12 +658,12 @@ QSurfaceFormat QGLXContext::format() const bool QGLXContext::isSharing() const { - return m_shareContext != 0; + return m_shareContext != nullptr; } bool QGLXContext::isValid() const { - return m_context != 0 && !m_lost; + return m_context != nullptr && !m_lost; } bool QGLXContext::m_queriedDummyContext = false; @@ -675,7 +675,7 @@ bool QGLXContext::m_supportsThreading = true; // binary search. static const char *qglx_threadedgl_blacklist_renderer[] = { "Chromium", // QTBUG-32225 (initialization fails) - 0 + nullptr }; static const char *qglx_threadedgl_blacklist_vendor[] = { @@ -695,7 +695,7 @@ void QGLXContext::queryDummyContext() return; QOpenGLContext *oldContext = QOpenGLContext::currentContext(); - QSurface *oldSurface = 0; + QSurface *oldSurface = nullptr; if (oldContext) oldSurface = oldContext->surface(); @@ -732,7 +732,7 @@ void QGLXContext::queryDummyContext() if (const char *renderer = (const char *) glGetString(GL_RENDERER)) { for (int i = 0; qglx_threadedgl_blacklist_renderer[i]; ++i) { - if (strstr(renderer, qglx_threadedgl_blacklist_renderer[i]) != 0) { + if (strstr(renderer, qglx_threadedgl_blacklist_renderer[i]) != nullptr) { qCDebug(lcQpaGl).nospace() << "Multithreaded OpenGL disabled: " "blacklisted renderer \"" << qglx_threadedgl_blacklist_renderer[i] @@ -744,7 +744,7 @@ void QGLXContext::queryDummyContext() } if (const char *vendor = (const char *) glGetString(GL_VENDOR)) { for (int i = 0; qglx_threadedgl_blacklist_vendor[i]; ++i) { - if (strstr(vendor, qglx_threadedgl_blacklist_vendor[i]) != 0) { + if (strstr(vendor, qglx_threadedgl_blacklist_vendor[i]) != nullptr) { qCDebug(lcQpaGl).nospace() << "Multithreaded OpenGL disabled: " "blacklisted vendor \"" << qglx_threadedgl_blacklist_vendor[i] @@ -759,7 +759,7 @@ void QGLXContext::queryDummyContext() // Blacklist Mesa drivers due to QTCREATORBUG-10875 (crash in creator), // QTBUG-34492 (flickering in fullscreen) and QTBUG-38221 const char *mesaVersionStr = nullptr; - if (strstr(glxvendor, "Mesa Project") != 0) { + if (strstr(glxvendor, "Mesa Project") != nullptr) { mesaVersionStr = (const char *) glGetString(GL_VERSION); m_supportsThreading = false; } diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp index 34895caaa2..6814dbd844 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp @@ -133,7 +133,7 @@ bool QXcbGlxIntegration::handleXcbEvent(xcb_generic_event_t *event, uint respons Display *xdisplay = static_cast<Display *>(m_connection->xlib_display()); XLockDisplay(xdisplay); bool locked = true; - Bool (*proc)(Display*, XEvent*, xEvent*) = XESetWireToEvent(xdisplay, responseType, 0); + Bool (*proc)(Display*, XEvent*, xEvent*) = XESetWireToEvent(xdisplay, responseType, nullptr); if (proc) { XESetWireToEvent(xdisplay, responseType, proc); XEvent dummy; @@ -212,7 +212,7 @@ QPlatformOffscreenSurface *QXcbGlxIntegration::createPlatformOffscreenSurface(QO if (glxPbufferUsable) return new QGLXPbuffer(surface); else - return 0; // trigger fallback to hidden QWindow + return nullptr; // trigger fallback to hidden QWindow } diff --git a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp index 82b6d60bcd..aa91d9266b 100644 --- a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp +++ b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp @@ -37,6 +37,8 @@ ** ****************************************************************************/ +#include <QtCore/qrandom.h> + #include <private/qpixmapcache_p.h> #include <private/qpaintengine_p.h> #include <private/qpolygonclipper_p.h> @@ -504,7 +506,7 @@ static Picture getPatternFill(int screen, const QBrush &b) return X11->pattern_fills[i].picture; } // none found, replace one - int i = qrand() % 16; + int i = QRandomGenerator::global()->generate() % 16; if (X11->pattern_fills[i].screen != screen && X11->pattern_fills[i].picture) { XRenderFreePicture (QXcbX11Info::display(), X11->pattern_fills[i].picture); diff --git a/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp b/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp index 57b1882e4b..6a483fc7e5 100644 --- a/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp +++ b/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp @@ -37,6 +37,8 @@ ** ****************************************************************************/ +#include <QtCore/qrandom.h> + #include "qxcbconnection.h" #include "qcolormap_x11_p.h" #include "qxcbnativepainting.h" @@ -279,7 +281,7 @@ Picture QXcbX11Data::getSolidFill(int screen, const QColor &c) return X11->solid_fills[i].picture; } // none found, replace one - int i = qrand() % 16; + int i = QRandomGenerator::global()->generate() % 16; if (X11->solid_fills[i].screen != screen && X11->solid_fills[i].picture) { XRenderFreePicture (X11->display, X11->solid_fills[i].picture); diff --git a/src/plugins/platforms/xcb/qxcbatom.cpp b/src/plugins/platforms/xcb/qxcbatom.cpp index a73d28319d..780816605a 100644 --- a/src/plugins/platforms/xcb/qxcbatom.cpp +++ b/src/plugins/platforms/xcb/qxcbatom.cpp @@ -267,7 +267,7 @@ void QXcbAtom::initializeAllAtoms(xcb_connection_t *connection) { cookies[i] = xcb_intern_atom(connection, false, strlen(names[i]), names[i]); for (i = 0; i < QXcbAtom::NAtoms; ++i) { - xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection, cookies[i], 0); + xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection, cookies[i], nullptr); m_allAtoms[i] = reply->atom; free(reply); } diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 741317d766..8f55bc2e96 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -229,7 +229,7 @@ void QXcbBackingStoreImage::resize(const QSize &size) m_xcb_format->bits_per_pixel, 0, byteOrder, XCB_IMAGE_ORDER_MSB_FIRST, - 0, ~0, 0); + nullptr, ~0, nullptr); const size_t segmentSize = imageDataSize(m_xcb_image); @@ -412,13 +412,13 @@ bool QXcbBackingStoreImage::createSystemVShmSegment(xcb_connection_t *c, size_t return false; } - void *addr = shmat(id, 0, 0); + void *addr = shmat(id, nullptr, 0); if (addr == (void *)-1) { qCWarning(lcQpaXcb, "shmat() failed (%d: %s) for id %d", errno, strerror(errno), id); return false; } - if (shmctl(id, IPC_RMID, 0) == -1) + if (shmctl(id, IPC_RMID, nullptr) == -1) qCWarning(lcQpaXcb, "Error while marking the shared memory segment to be destroyed"); const auto seg = xcb_generate_id(c); @@ -780,7 +780,7 @@ QXcbBackingStore::~QXcbBackingStore() QPaintDevice *QXcbBackingStore::paintDevice() { if (!m_image) - return 0; + return nullptr; return m_rgbImage.isNull() ? m_image->image() : &m_rgbImage; } @@ -1036,7 +1036,7 @@ void QXcbSystemTrayBackingStore::recreateImage(QXcbWindow *win, const QSize &siz xcb_create_pixmap(xcb_connection(), 32, m_xrenderPixmap, screen->root(), size.width(), size.height()); m_xrenderPicture = xcb_generate_id(xcb_connection()); - xcb_render_create_picture(xcb_connection(), m_xrenderPicture, m_xrenderPixmap, m_xrenderPictFormat, 0, 0); + xcb_render_create_picture(xcb_connection(), m_xrenderPicture, m_xrenderPixmap, m_xrenderPictFormat, 0, nullptr); // XRender expects premultiplied alpha if (m_image) @@ -1077,7 +1077,7 @@ void QXcbSystemTrayBackingStore::initXRenderMode() m_windowPicture = xcb_generate_id(conn); xcb_void_cookie_t cookie = - xcb_render_create_picture_checked(conn, m_windowPicture, platformWindow->xcb_window(), vfmt->format, 0, 0); + xcb_render_create_picture_checked(conn, m_windowPicture, platformWindow->xcb_window(), vfmt->format, 0, nullptr); xcb_generic_error_t *error = xcb_request_check(conn, cookie); if (error) { qWarning("QXcbSystemTrayBackingStore: Failed to create Picture with format %x for window %x, error code %d", diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index 2cb6720d40..fe9ddfece7 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -123,8 +123,9 @@ protected: return list.contains(format); } - QVariant retrieveData_sys(const QString &fmt, QVariant::Type requestedType) const override + QVariant retrieveData_sys(const QString &fmt, QVariant::Type type) const override { + auto requestedType = QMetaType::Type(type); if (fmt.isEmpty() || isEmpty()) return QByteArray(); @@ -226,8 +227,8 @@ QXcbClipboard::QXcbClipboard(QXcbConnection *c) { Q_ASSERT(QClipboard::Clipboard == 0); Q_ASSERT(QClipboard::Selection == 1); - m_clientClipboard[QClipboard::Clipboard] = 0; - m_clientClipboard[QClipboard::Selection] = 0; + m_clientClipboard[QClipboard::Clipboard] = nullptr; + m_clientClipboard[QClipboard::Selection] = nullptr; m_timestamp[QClipboard::Clipboard] = XCB_CURRENT_TIME; m_timestamp[QClipboard::Selection] = XCB_CURRENT_TIME; m_owner = connection()->getQtSelectionOwner(); @@ -316,7 +317,7 @@ QClipboard::Mode QXcbClipboard::modeForAtom(xcb_atom_t a) const QMimeData * QXcbClipboard::mimeData(QClipboard::Mode mode) { if (mode > QClipboard::Selection) - return 0; + return nullptr; xcb_window_t clipboardOwner = getSelectionOwner(atomForMode(mode)); if (clipboardOwner == owner()) { @@ -334,7 +335,7 @@ void QXcbClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) if (mode > QClipboard::Selection) return; - QXcbClipboardMime *xClipboard = 0; + QXcbClipboardMime *xClipboard = nullptr; // verify if there is data to be cleared on global X Clipboard. if (!data) { xClipboard = qobject_cast<QXcbClipboardMime *>(mimeData(mode)); @@ -353,7 +354,7 @@ void QXcbClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) if (m_clientClipboard[mode]) { if (m_clientClipboard[QClipboard::Clipboard] != m_clientClipboard[QClipboard::Selection]) delete m_clientClipboard[mode]; - m_clientClipboard[mode] = 0; + m_clientClipboard[mode] = nullptr; m_timestamp[mode] = XCB_CURRENT_TIME; } @@ -416,7 +417,7 @@ xcb_window_t QXcbClipboard::requestor() const XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class platformScreen->screen()->root_visual, // visual 0, // value mask - 0); // value list + nullptr); // value list QXcbWindow::setWindowTitle(connection(), window, QStringLiteral("Qt Clipboard Requestor Window")); @@ -529,7 +530,7 @@ void QXcbClipboard::handleSelectionClearRequest(xcb_selection_clear_event_t *eve if (newOwner != XCB_NONE) { if (m_clientClipboard[QClipboard::Clipboard] != m_clientClipboard[QClipboard::Selection]) delete m_clientClipboard[mode]; - m_clientClipboard[mode] = 0; + m_clientClipboard[mode] = nullptr; m_timestamp[mode] = XCB_CURRENT_TIME; } } @@ -576,7 +577,7 @@ void QXcbClipboard::handleSelectionRequest(xcb_selection_request_event_t *req) xcb_atom_t multipleAtom = atom(QXcbAtom::MULTIPLE); xcb_atom_t timestampAtom = atom(QXcbAtom::TIMESTAMP); - struct AtomPair { xcb_atom_t target; xcb_atom_t property; } *multi = 0; + struct AtomPair { xcb_atom_t target; xcb_atom_t property; } *multi = nullptr; xcb_atom_t multi_type = XCB_NONE; int multi_format = 0; int nmulti = 0; @@ -587,7 +588,7 @@ void QXcbClipboard::handleSelectionRequest(xcb_selection_request_event_t *req) QByteArray multi_data; if (req->property == XCB_NONE || !clipboardReadProperty(req->requestor, req->property, false, &multi_data, - 0, &multi_type, &multi_format) + nullptr, &multi_type, &multi_format) || multi_format != 32) { // MULTIPLE property not formatted correctly xcb_send_event(xcb_connection(), false, req->requestor, XCB_EVENT_MASK_NO_EVENT, (const char *)&event); @@ -842,7 +843,7 @@ QByteArray QXcbClipboard::clipboardReadIncrementalProperty(xcb_window_t win, xcb continue; prev_time = event->time; - if (clipboardReadProperty(win, property, true, &tmp_buf, &length, 0, 0)) { + if (clipboardReadProperty(win, property, true, &tmp_buf, &length, nullptr, nullptr)) { if (length == 0) { // no more data, we're done if (nullterm) { buf.resize(offset+1); @@ -900,7 +901,7 @@ QByteArray QXcbClipboard::getSelection(xcb_atom_t selection, xcb_atom_t target, return buf; xcb_atom_t type; - if (clipboardReadProperty(win, property, true, &buf, 0, &type, 0)) { + if (clipboardReadProperty(win, property, true, &buf, nullptr, &type, nullptr)) { if (type == atom(QXcbAtom::INCR)) { int nbytes = buf.size() >= 4 ? *((int*)buf.data()) : 0; buf = clipboardReadIncrementalProperty(win, property, nbytes, false); diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index cac6345b66..435c4aee93 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -66,14 +66,10 @@ #include <errno.h> #include <xcb/xfixes.h> -#if QT_CONFIG(xkb) #define explicit dont_use_cxx_explicit #include <xcb/xkb.h> #undef explicit -#endif -#if QT_CONFIG(xcb_xinput) #include <xcb/xinput.h> -#endif QT_BEGIN_NAMESPACE @@ -88,12 +84,6 @@ Q_LOGGING_CATEGORY(lcQpaKeyboard, "qt.qpa.xkeyboard") Q_LOGGING_CATEGORY(lcQpaClipboard, "qt.qpa.clipboard") Q_LOGGING_CATEGORY(lcQpaXDnd, "qt.qpa.xdnd") -// this event type was added in libxcb 1.10, -// but we support also older version -#ifndef XCB_GE_GENERIC -#define XCB_GE_GENERIC 35 -#endif - QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, xcb_visualid_t defaultVisualId, const char *displayName) : QXcbBasicConnection(displayName) , m_canGrabServer(canGrabServer) @@ -112,12 +102,10 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra initializeScreens(); -#if QT_CONFIG(xcb_xinput) if (hasXInput2()) { xi2SetupDevices(); xi2SelectStateEvents(); } -#endif m_wmSupport.reset(new QXcbWMSupport(this)); m_keyboard = new QXcbKeyboard(this); @@ -196,7 +184,7 @@ QXcbWindow *QXcbConnection::platformWindowFromId(xcb_window_t id) QXcbWindowEventListener *listener = m_mapper.value(id, 0); if (listener) return listener->toWindow(); - return 0; + return nullptr; } #define HANDLE_PLATFORM_WINDOW_EVENT(event_t, windowMember, handler) \ @@ -467,7 +455,7 @@ void QXcbConnection::printXcbError(const char *message, xcb_generic_error_t *err static Qt::MouseButtons translateMouseButtons(int s) { - Qt::MouseButtons ret = 0; + Qt::MouseButtons ret; if (s & XCB_BUTTON_MASK_1) ret |= Qt::LeftButton; if (s & XCB_BUTTON_MASK_2) @@ -518,7 +506,6 @@ Qt::MouseButton QXcbConnection::translateMouseButton(xcb_button_t s) } } -#if QT_CONFIG(xkb) namespace { typedef union { /* All XKB events share these fields. */ @@ -534,7 +521,6 @@ namespace { xcb_xkb_state_notify_event_t state_notify; } _xkb_event; } -#endif void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) { @@ -611,16 +597,12 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) HANDLE_PLATFORM_WINDOW_EVENT(xcb_client_message_event_t, window, handleClientMessageEvent); } case XCB_ENTER_NOTIFY: -#if QT_CONFIG(xcb_xinput) if (hasXInput2() && !xi2MouseEventsDisabled()) break; -#endif HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent); case XCB_LEAVE_NOTIFY: -#if QT_CONFIG(xcb_xinput) if (hasXInput2() && !xi2MouseEventsDisabled()) break; -#endif m_keyboard->updateXKBStateFromCore(reinterpret_cast<xcb_leave_notify_event_t *>(event)->state); HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent); case XCB_FOCUS_IN: @@ -682,13 +664,11 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) } break; } -#if QT_CONFIG(xcb_xinput) case XCB_GE_GENERIC: // Here the windowEventListener is invoked from xi2HandleEvent() if (hasXInput2() && isXIEvent(event)) xi2HandleEvent(reinterpret_cast<xcb_ge_event_t *>(event)); break; -#endif default: handled = false; // event type not recognized break; @@ -712,7 +692,6 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) auto change_event = reinterpret_cast<xcb_randr_screen_change_notify_event_t *>(event); if (auto virtualDesktop = virtualDesktopForRootWindow(change_event->root)) virtualDesktop->handleScreenChange(change_event); -#if QT_CONFIG(xkb) } else if (isXkbType(response_type)) { auto xkb_event = reinterpret_cast<_xkb_event *>(event); if (xkb_event->any.deviceID == m_keyboard->coreDeviceId()) { @@ -735,7 +714,6 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) break; } } -#endif } else { handled = false; // event type still not recognized } @@ -825,7 +803,7 @@ xcb_window_t QXcbConnection::getQtSelectionOwner() XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class xcbScreen->root_visual, // visual 0, // value mask - 0); // value list + nullptr); // value list QXcbWindow::setWindowTitle(connection(), m_qtSelectionOwner, QLatin1String("Qt Selection Owner for ") + QCoreApplication::applicationName()); @@ -852,7 +830,7 @@ xcb_window_t QXcbConnection::clientLeader() 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->screen()->root_visual, - 0, 0); + 0, nullptr); QXcbWindow::setWindowTitle(connection(), m_clientLeader, @@ -912,7 +890,6 @@ bool QXcbConnection::compressEvent(xcb_generic_event_t *event) const }); } -#if QT_CONFIG(xcb_xinput) // compress XI_* events if (responseType == XCB_GE_GENERIC) { if (!hasXInput2()) @@ -948,7 +925,6 @@ bool QXcbConnection::compressEvent(xcb_generic_event_t *event) const return false; } -#endif if (responseType == XCB_CONFIGURE_NOTIFY) { // compress multiple configure notify events for the same window @@ -978,7 +954,6 @@ bool QXcbConnection::isUserInputEvent(xcb_generic_event_t *event) const if (isInputEvent) return true; -#if QT_CONFIG(xcb_xinput) if (connection()->hasXInput2()) { isInputEvent = isXIType(event, XCB_INPUT_BUTTON_PRESS) || isXIType(event, XCB_INPUT_BUTTON_RELEASE) || @@ -993,7 +968,6 @@ bool QXcbConnection::isUserInputEvent(xcb_generic_event_t *event) const } if (isInputEvent) return true; -#endif if (eventType == XCB_CLIENT_MESSAGE) { auto clientMessage = reinterpret_cast<const xcb_client_message_event_t *>(event); @@ -1057,7 +1031,7 @@ void QXcbConnection::sync() { // from xcb_aux_sync xcb_get_input_focus_cookie_t cookie = xcb_get_input_focus(xcb_connection()); - free(xcb_get_input_focus_reply(xcb_connection(), cookie, 0)); + free(xcb_get_input_focus_reply(xcb_connection(), cookie, nullptr)); } QXcbSystemTrayTracker *QXcbConnection::systemTrayTracker() const @@ -1075,14 +1049,14 @@ QXcbSystemTrayTracker *QXcbConnection::systemTrayTracker() const Qt::MouseButtons QXcbConnection::queryMouseButtons() const { int stateMask = 0; - QXcbCursor::queryPointer(connection(), 0, 0, &stateMask); + QXcbCursor::queryPointer(connection(), nullptr, nullptr, &stateMask); return translateMouseButtons(stateMask); } Qt::KeyboardModifiers QXcbConnection::queryKeyboardModifiers() const { int stateMask = 0; - QXcbCursor::queryPointer(connection(), 0, 0, &stateMask); + QXcbCursor::queryPointer(connection(), nullptr, nullptr, &stateMask); return keyboard()->translateModifiers(stateMask); } @@ -1140,7 +1114,7 @@ void QXcbSyncWindowRequest::invalidate() { if (m_window) { m_window->clearSyncWindowRequest(); - m_window = 0; + m_window = nullptr; } } @@ -1160,7 +1134,7 @@ void QXcbConnectionGrabber::release() { if (m_connection) { m_connection->ungrabServer(); - m_connection = 0; + m_connection = nullptr; } } diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 7cf25d41a6..8a4b577d2e 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -104,10 +104,8 @@ public: virtual void handleFocusInEvent(const xcb_focus_in_event_t *) {} virtual void handleFocusOutEvent(const xcb_focus_out_event_t *) {} virtual void handlePropertyNotifyEvent(const xcb_property_notify_event_t *) {} -#if QT_CONFIG(xcb_xinput) virtual void handleXIMouseEvent(xcb_ge_event_t *, Qt::MouseEventSource = Qt::MouseEventNotSynthesized) {} virtual void handleXIEnterLeave(xcb_ge_event_t *) {} -#endif virtual QXcbWindow *toWindow() { return nullptr; } }; @@ -129,7 +127,7 @@ class Q_XCB_EXPORT QXcbConnection : public QXcbBasicConnection { Q_OBJECT public: - QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, xcb_visualid_t defaultVisualId, const char *displayName = 0); + QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, xcb_visualid_t defaultVisualId, const char *displayName = nullptr); ~QXcbConnection(); QXcbConnection *connection() const { return const_cast<QXcbConnection *>(this); } @@ -225,7 +223,6 @@ public: bool isUserInputEvent(xcb_generic_event_t *event) const; -#if QT_CONFIG(xcb_xinput) void xi2SelectStateEvents(); void xi2SelectDeviceEvents(xcb_window_t window); void xi2SelectDeviceEventsCompatibility(xcb_window_t window); @@ -233,10 +230,9 @@ public: bool xi2MouseEventsDisabled() const; Qt::MouseButton xiToQtMouseButton(uint32_t b); void xi2UpdateScrollingDevices(); - bool startSystemMoveResizeForTouchBegin(xcb_window_t window, const QPoint &point, int corner); + bool startSystemMoveResizeForTouch(xcb_window_t window, int edges); void abortSystemMoveResizeForTouch(); bool isTouchScreen(int id); -#endif bool canGrab() const { return m_canGrabServer; } @@ -267,7 +263,6 @@ private: inline bool timeGreaterThan(xcb_timestamp_t a, xcb_timestamp_t b) const { return static_cast<int32_t>(a - b) > 0 || b == XCB_CURRENT_TIME; } -#if QT_CONFIG(xcb_xinput) void xi2SetupDevice(void *info, bool removeExisting = true); void xi2SetupDevices(); struct TouchDeviceData { @@ -299,7 +294,7 @@ private: int deviceId = 0; QTabletEvent::PointerType pointerType = QTabletEvent::UnknownPointer; QTabletEvent::TabletDevice tool = QTabletEvent::Stylus; - Qt::MouseButtons buttons = 0; + Qt::MouseButtons buttons; qint64 serialId = 0; bool inProximity = false; struct ValuatorClassInfo { @@ -323,8 +318,8 @@ private: int horizontalIndex = 0; double verticalIncrement = 0; double horizontalIncrement = 0; - Qt::Orientations orientations = 0; - Qt::Orientations legacyOrientations = 0; + Qt::Orientations orientations; + Qt::Orientations legacyOrientations; QPointF lastScrollPosition; }; QHash<int, ScrollingDevice> m_scrollingDevices; @@ -339,9 +334,8 @@ private: xcb_window_t window = XCB_NONE; uint16_t deviceid; uint32_t pointid; - int corner; + int edges; } m_startSystemMoveResizeInfo; -#endif // QT_CONFIG(xcb_xinput) const bool m_canGrabServer; const xcb_visualid_t m_defaultVisualId; @@ -366,7 +360,7 @@ private: WindowMapper m_mapper; - Qt::MouseButtons m_buttonState = nullptr; + Qt::MouseButtons m_buttonState; Qt::MouseButton m_button = Qt::NoButton; QXcbWindow *m_focusWindow = nullptr; @@ -389,12 +383,10 @@ private: QTimer m_focusInTimer; }; -#if QT_CONFIG(xcb_xinput) #if QT_CONFIG(tabletevent) Q_DECLARE_TYPEINFO(QXcbConnection::TabletData::ValuatorClassInfo, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(QXcbConnection::TabletData, Q_MOVABLE_TYPE); #endif -#endif class QXcbConnectionGrabber { diff --git a/src/plugins/platforms/xcb/qxcbconnection_basic.cpp b/src/plugins/platforms/xcb/qxcbconnection_basic.cpp index 9a028e5a7e..18dee89adb 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_basic.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_basic.cpp @@ -45,14 +45,10 @@ #include <xcb/xfixes.h> #include <xcb/xinerama.h> #include <xcb/render.h> -#if QT_CONFIG(xcb_xinput) #include <xcb/xinput.h> -#endif -#if QT_CONFIG(xkb) #define explicit dont_use_cxx_explicit #include <xcb/xkb.h> #undef explicit -#endif #if QT_CONFIG(xcb_xlib) #define register /* C++17 deprecated register */ @@ -97,7 +93,7 @@ static int nullErrorHandler(Display *dpy, XErrorEvent *err) static int ioErrorHandler(Display *dpy) { xcb_connection_t *conn = XGetXCBConnection(dpy); - if (conn != NULL) { + if (conn != nullptr) { /* Print a message with a textual description of the error */ int code = xcb_connection_has_error(conn); const char *str = "Unknown error"; @@ -138,14 +134,7 @@ QXcbBasicConnection::QXcbBasicConnection(const char *displayName) xcb_extension_t *extensions[] = { &xcb_shm_id, &xcb_xfixes_id, &xcb_randr_id, &xcb_shape_id, &xcb_sync_id, - &xcb_render_id, -#if QT_CONFIG(xkb) - &xcb_xkb_id, -#endif -#if QT_CONFIG(xcb_xinput) - &xcb_input_id, -#endif - 0 + &xcb_render_id, &xcb_xkb_id, &xcb_input_id, nullptr }; for (xcb_extension_t **ext_it = extensions; *ext_it; ++ext_it) @@ -160,10 +149,8 @@ QXcbBasicConnection::QXcbBasicConnection(const char *displayName) initializeXinerama(); initializeXFixes(); initializeXRender(); -#if QT_CONFIG(xcb_xinput) if (!qEnvironmentVariableIsSet("QT_XCB_NO_XI2")) initializeXInput2(); -#endif initializeXShape(); initializeXKB(); } @@ -213,7 +200,6 @@ bool QXcbBasicConnection::hasBigRequest() const return m_maximumRequestLength > m_setup->maximum_request_length; } -#if QT_CONFIG(xcb_xinput) // Starting from the xcb version 1.9.3 struct xcb_ge_event_t has changed: // - "pad0" became "extension" // - "pad1" and "pad" became "pad0" @@ -240,7 +226,6 @@ bool QXcbBasicConnection::isXIType(xcb_generic_event_t *event, uint16_t type) co auto *e = reinterpret_cast<qt_xcb_ge_event_t *>(event); return e->event_type == type; } -#endif // QT_CONFIG(xcb_xinput) bool QXcbBasicConnection::isXFixesType(uint responseType, int eventType) const { @@ -370,7 +355,6 @@ void QXcbBasicConnection::initializeXRandr() m_xrandrFirstEvent = reply->first_event; } -#if QT_CONFIG(xcb_xinput) void QXcbBasicConnection::initializeXInput2() { const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_input_id); @@ -393,7 +377,6 @@ void QXcbBasicConnection::initializeXInput2() m_xinputFirstEvent = reply->first_event; m_xi2Minor = xinputQuery->minor_version; } -#endif void QXcbBasicConnection::initializeXShape() { @@ -417,7 +400,6 @@ void QXcbBasicConnection::initializeXShape() void QXcbBasicConnection::initializeXKB() { -#if QT_CONFIG(xkb) const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_xkb_id); if (!reply || !reply->present) { qCWarning(lcQpaXcb, "XKeyboard extension not present on the X server"); @@ -439,7 +421,6 @@ void QXcbBasicConnection::initializeXKB() m_hasXkb = true; m_xkbFirstEvent = reply->first_event; -#endif } QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbconnection_basic.h b/src/plugins/platforms/xcb/qxcbconnection_basic.h index 1bd4310562..109186f966 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_basic.h +++ b/src/plugins/platforms/xcb/qxcbconnection_basic.h @@ -99,12 +99,10 @@ public: bool hasXinerama() const { return m_hasXinerama; } bool hasBigRequest() const; -#if QT_CONFIG(xcb_xinput) bool isAtLeastXI21() const { return m_xi2Enabled && m_xi2Minor >= 1; } bool isAtLeastXI22() const { return m_xi2Enabled && m_xi2Minor >= 2; } bool isXIEvent(xcb_generic_event_t *event) const; bool isXIType(xcb_generic_event_t *event, uint16_t type) const; -#endif bool isXFixesType(uint responseType, int eventType) const; bool isXRandrType(uint responseType, int eventType) const; @@ -119,9 +117,7 @@ protected: void initializeXShape(); void initializeXKB(); void initializeXSync(); -#if QT_CONFIG(xcb_xinput) void initializeXInput2(); -#endif private: #if QT_CONFIG(xcb_xlib) @@ -147,11 +143,9 @@ private: QPair<int, int> m_xrenderVersion; bool m_xi2Enabled = false; -#if QT_CONFIG(xcb_xinput) int m_xi2Minor = -1; int m_xiOpCode = -1; uint32_t m_xinputFirstEvent = 0; -#endif uint32_t m_xfixesFirstEvent = 0; uint32_t m_xrandrFirstEvent = 0; diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 0a82bbc7a9..27a2526df1 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -166,7 +166,7 @@ void QXcbConnection::xi2SetupDevice(void *info, bool removeExisting) } case XCB_INPUT_DEVICE_CLASS_TYPE_BUTTON: { auto *bci = reinterpret_cast<xcb_input_button_class_t *>(classinfo); - xcb_atom_t *labels = 0; + xcb_atom_t *labels = nullptr; if (bci->num_buttons >= 5) { labels = xcb_input_button_class_labels(bci); xcb_atom_t label4 = labels[3]; @@ -424,7 +424,7 @@ QXcbConnection::TouchDeviceData *QXcbConnection::touchDeviceForId(int id) QXcbConnection::TouchDeviceData *QXcbConnection::populateTouchDevices(void *info) { auto *deviceinfo = reinterpret_cast<xcb_input_xi_device_info_t *>(info); - QTouchDevice::Capabilities caps = 0; + QTouchDevice::Capabilities caps; int type = -1; int maxTouchPoints = 1; bool isTouchDevice = false; @@ -514,12 +514,10 @@ QXcbConnection::TouchDeviceData *QXcbConnection::populateTouchDevices(void *info return isTouchDevice ? &m_touchDevices[deviceinfo->deviceid] : nullptr; } -#if QT_CONFIG(tabletevent) static inline qreal fixed1616ToReal(xcb_input_fp1616_t val) { return qreal(val) / 0x10000; } -#endif // QT_CONFIG(tabletevent) void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) { @@ -527,7 +525,7 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) int sourceDeviceId = xiEvent->deviceid; // may be the master id qt_xcb_input_device_event_t *xiDeviceEvent = nullptr; xcb_input_enter_event_t *xiEnterEvent = nullptr; - QXcbWindowEventListener *eventListener = 0; + QXcbWindowEventListener *eventListener = nullptr; switch (xiEvent->event_type) { case XCB_INPUT_BUTTON_PRESS: @@ -753,7 +751,7 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo xcb_input_xi_allow_events(xcb_connection(), XCB_CURRENT_TIME, xiDeviceEvent->deviceid, XCB_INPUT_EVENT_MODE_REJECT_TOUCH, xiDeviceEvent->detail, xiDeviceEvent->event); - window->doStartSystemMoveResize(QPoint(x, y), m_startSystemMoveResizeInfo.corner); + window->doStartSystemMoveResize(QPoint(x, y), m_startSystemMoveResizeInfo.edges); m_startSystemMoveResizeInfo.window = XCB_NONE; } } @@ -787,19 +785,20 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo touchPoint.state = Qt::TouchPointStationary; } -bool QXcbConnection::startSystemMoveResizeForTouchBegin(xcb_window_t window, const QPoint &point, int corner) +bool QXcbConnection::startSystemMoveResizeForTouch(xcb_window_t window, int edges) { QHash<int, TouchDeviceData>::const_iterator devIt = m_touchDevices.constBegin(); for (; devIt != m_touchDevices.constEnd(); ++devIt) { TouchDeviceData deviceData = devIt.value(); if (deviceData.qtTouchDevice->type() == QTouchDevice::TouchScreen) { - QHash<int, QPointF>::const_iterator pointIt = deviceData.pointPressedPosition.constBegin(); - for (; pointIt != deviceData.pointPressedPosition.constEnd(); ++pointIt) { - if (pointIt.value().toPoint() == point) { + auto pointIt = deviceData.touchPoints.constBegin(); + for (; pointIt != deviceData.touchPoints.constEnd(); ++pointIt) { + Qt::TouchPointState state = pointIt.value().state; + if (state == Qt::TouchPointMoved || state == Qt::TouchPointPressed || state == Qt::TouchPointStationary) { m_startSystemMoveResizeInfo.window = window; m_startSystemMoveResizeInfo.deviceid = devIt.key(); m_startSystemMoveResizeInfo.pointid = pointIt.key(); - m_startSystemMoveResizeInfo.corner = corner; + m_startSystemMoveResizeInfo.edges = edges; return true; } } diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp index fbadab4d50..42c7a52bd4 100644 --- a/src/plugins/platforms/xcb/qxcbcursor.cpp +++ b/src/plugins/platforms/xcb/qxcbcursor.cpp @@ -67,10 +67,10 @@ enum { }; #undef CursorShape -static PtrXcursorLibraryLoadCursor ptrXcursorLibraryLoadCursor = 0; -static PtrXcursorLibraryGetTheme ptrXcursorLibraryGetTheme = 0; -static PtrXcursorLibrarySetTheme ptrXcursorLibrarySetTheme = 0; -static PtrXcursorLibraryGetDefaultSize ptrXcursorLibraryGetDefaultSize = 0; +static PtrXcursorLibraryLoadCursor ptrXcursorLibraryLoadCursor = nullptr; +static PtrXcursorLibraryGetTheme ptrXcursorLibraryGetTheme = nullptr; +static PtrXcursorLibrarySetTheme ptrXcursorLibrarySetTheme = nullptr; +static PtrXcursorLibraryGetDefaultSize ptrXcursorLibraryGetDefaultSize = nullptr; #endif static xcb_font_t cursorFont = 0; @@ -118,7 +118,7 @@ static const uint8_t mcur_fdiag_bits[] = { static const uint8_t *cursor_bits16[] = { cur_ver_bits, mcur_ver_bits, cur_hor_bits, mcur_hor_bits, cur_bdiag_bits, mcur_bdiag_bits, cur_fdiag_bits, mcur_fdiag_bits, - 0, 0, cur_blank_bits, cur_blank_bits }; + nullptr, nullptr, cur_blank_bits, cur_blank_bits }; static const uint8_t vsplit_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -219,7 +219,7 @@ static const uint8_t busym_bits[] = { static const uint8_t * const cursor_bits32[] = { vsplit_bits, vsplitm_bits, hsplit_bits, hsplitm_bits, - 0, 0, 0, 0, whatsthis_bits, whatsthism_bits, busy_bits, busym_bits + nullptr, nullptr, nullptr, nullptr, whatsthis_bits, whatsthism_bits, busy_bits, busym_bits }; static const uint8_t forbidden_bits[] = { @@ -289,10 +289,10 @@ QXcbCursorCacheKey::QXcbCursorCacheKey(const QCursor &c) if (pixmapCacheKey) { bitmapCacheKey = pixmapCacheKey; } else { - Q_ASSERT(c.bitmap()); - Q_ASSERT(c.mask()); - bitmapCacheKey = c.bitmap()->cacheKey(); - maskCacheKey = c.mask()->cacheKey(); + Q_ASSERT(!c.bitmap(Qt::ReturnByValue).isNull()); + Q_ASSERT(!c.mask(Qt::ReturnByValue).isNull()); + bitmapCacheKey = c.bitmap(Qt::ReturnByValue).cacheKey(); + maskCacheKey = c.mask(Qt::ReturnByValue).cacheKey(); } } } @@ -452,19 +452,19 @@ xcb_cursor_t QXcbCursor::createNonStandardCursor(int cshape) if (cshape == Qt::BlankCursor) { xcb_pixmap_t cp = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(), cur_blank_bits, 16, 16, - 1, 0, 0, 0); + 1, 0, 0, nullptr); xcb_pixmap_t mp = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(), cur_blank_bits, 16, 16, - 1, 0, 0, 0); + 1, 0, 0, nullptr); cursor = xcb_generate_id(conn); xcb_create_cursor(conn, cursor, cp, mp, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 8, 8); } else if (cshape >= Qt::SizeVerCursor && cshape < Qt::SizeAllCursor) { int i = (cshape - Qt::SizeVerCursor) * 2; xcb_pixmap_t pm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(), const_cast<uint8_t*>(cursor_bits16[i]), - 16, 16, 1, 0, 0, 0); + 16, 16, 1, 0, 0, nullptr); xcb_pixmap_t pmm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(), const_cast<uint8_t*>(cursor_bits16[i + 1]), - 16, 16, 1, 0, 0, 0); + 16, 16, 1, 0, 0, nullptr); cursor = xcb_generate_id(conn); xcb_create_cursor(conn, cursor, pm, pmm, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 8, 8); } else if ((cshape >= Qt::SplitVCursor && cshape <= Qt::SplitHCursor) @@ -472,10 +472,10 @@ xcb_cursor_t QXcbCursor::createNonStandardCursor(int cshape) int i = (cshape - Qt::SplitVCursor) * 2; xcb_pixmap_t pm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(), const_cast<uint8_t*>(cursor_bits32[i]), - 32, 32, 1, 0, 0, 0); + 32, 32, 1, 0, 0, nullptr); xcb_pixmap_t pmm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(), const_cast<uint8_t*>(cursor_bits32[i + 1]), - 32, 32, 1, 0, 0, 0); + 32, 32, 1, 0, 0, nullptr); int hs = (cshape == Qt::PointingHandCursor || cshape == Qt::WhatsThisCursor || cshape == Qt::BusyCursor) ? 0 : 16; cursor = xcb_generate_id(conn); @@ -484,20 +484,20 @@ xcb_cursor_t QXcbCursor::createNonStandardCursor(int cshape) int i = (cshape - Qt::ForbiddenCursor) * 2; xcb_pixmap_t pm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(), const_cast<uint8_t*>(cursor_bits20[i]), - 20, 20, 1, 0, 0, 0); + 20, 20, 1, 0, 0, nullptr); xcb_pixmap_t pmm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(), const_cast<uint8_t*>(cursor_bits20[i + 1]), - 20, 20, 1, 0, 0, 0); + 20, 20, 1, 0, 0, nullptr); cursor = xcb_generate_id(conn); xcb_create_cursor(conn, cursor, pm, pmm, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 10, 10); } else if (cshape == Qt::OpenHandCursor || cshape == Qt::ClosedHandCursor) { bool open = cshape == Qt::OpenHandCursor; xcb_pixmap_t pm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(), const_cast<uint8_t*>(open ? openhand_bits : closedhand_bits), - 16, 16, 1, 0, 0, 0); + 16, 16, 1, 0, 0, nullptr); xcb_pixmap_t pmm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(), const_cast<uint8_t*>(open ? openhandm_bits : closedhandm_bits), - 16, 16, 1, 0, 0, 0); + 16, 16, 1, 0, 0, nullptr); cursor = xcb_generate_id(conn); xcb_create_cursor(conn, cursor, pm, pmm, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 8, 8); } else if (cshape == Qt::DragCopyCursor || cshape == Qt::DragMoveCursor @@ -613,8 +613,8 @@ xcb_cursor_t QXcbCursor::createBitmapCursor(QCursor *cursor) qCWarning(lcQpaXcb, "xrender >= 0.5 required to create pixmap cursors"); } else { xcb_connection_t *conn = xcb_connection(); - xcb_pixmap_t cp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->bitmap()->toImage()); - xcb_pixmap_t mp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->mask()->toImage()); + xcb_pixmap_t cp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->bitmap(Qt::ReturnByValue).toImage()); + xcb_pixmap_t mp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->mask(Qt::ReturnByValue).toImage()); c = xcb_generate_id(conn); xcb_create_cursor(conn, c, cp, mp, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, spot.x(), spot.y()); @@ -660,14 +660,14 @@ void QXcbCursor::queryPointer(QXcbConnection *c, QXcbVirtualDesktop **virtualDes QPoint QXcbCursor::pos() const { QPoint p; - queryPointer(connection(), 0, &p); + queryPointer(connection(), nullptr, &p); return p; } void QXcbCursor::setPos(const QPoint &pos) { QXcbVirtualDesktop *virtualDesktop = nullptr; - queryPointer(connection(), &virtualDesktop, 0); + queryPointer(connection(), &virtualDesktop, nullptr); xcb_warp_pointer(xcb_connection(), XCB_NONE, virtualDesktop->root(), 0, 0, 0, 0, pos.x(), pos.y()); xcb_flush(xcb_connection()); } diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index d82129c6bc..cc735f40a8 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -114,7 +114,7 @@ protected: QStringList formats_sys() const override; QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const override; - QVariant xdndObtainData(const QByteArray &format, QVariant::Type requestedType) const; + QVariant xdndObtainData(const QByteArray &format, QMetaType::Type requestedType) const; QXcbDrag *drag; }; @@ -148,7 +148,7 @@ void QXcbDrag::init() source_time = XCB_CURRENT_TIME; target_time = XCB_CURRENT_TIME; - QXcbCursor::queryPointer(connection(), ¤t_virtual_desktop, 0); + QXcbCursor::queryPointer(connection(), ¤t_virtual_desktop, nullptr); drag_types.clear(); //current_embedding_widget = 0; @@ -400,13 +400,13 @@ void QXcbDrag::move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardMod if (!findXdndAwareTarget(globalPos, &target)) return; - QXcbWindow *w = 0; + QXcbWindow *w = nullptr; if (target) { w = connection()->platformWindowFromId(target); if (w && (w->window()->type() == Qt::Desktop) /*&& !w->acceptDrops()*/) - w = 0; + w = nullptr; } else { - w = 0; + w = nullptr; target = current_virtual_desktop->root(); } @@ -542,7 +542,7 @@ void QXcbDrag::drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardMod QXcbWindow *w = connection()->platformWindowFromId(current_proxy_target); if (w && w->window()->type() == Qt::Desktop) // && !w->acceptDrops() - w = 0; + w = nullptr; Transaction t = { connection()->time(), @@ -803,7 +803,7 @@ void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message target_time = e->data.data32[3]; } - QMimeData *dropData = 0; + QMimeData *dropData = nullptr; Qt::DropActions supported_actions = Qt::IgnoreAction; if (currentDrag()) { dropData = currentDrag()->mimeData(); @@ -976,7 +976,7 @@ void QXcbDrag::handleLeave(QPlatformWindow *w, const xcb_client_message_event_t stopListeningForActionListChanges(); - QWindowSystemInterface::handleDrag(w->window(), nullptr, QPoint(), Qt::IgnoreAction, 0, 0); + QWindowSystemInterface::handleDrag(w->window(), nullptr, QPoint(), Qt::IgnoreAction, { }, { }); } void QXcbDrag::send_leave() @@ -1004,7 +1004,7 @@ void QXcbDrag::send_leave() QXcbWindow *w = connection()->platformWindowFromId(current_proxy_target); if (w && (w->window()->type() == Qt::Desktop) /*&& !w->acceptDrops()*/) - w = 0; + w = nullptr; qCDebug(lcQpaXDnd) << "sending XdndLeave to target:" << current_target; @@ -1039,7 +1039,7 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e target_time = l[2]; Qt::DropActions supported_drop_actions; - QMimeData *dropData = 0; + QMimeData *dropData = nullptr; if (currentDrag()) { dropData = currentDrag()->mimeData(); supported_drop_actions = Qt::DropActions(l[4]); @@ -1248,7 +1248,7 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event } } - QDrag *transactionDrag = 0; + QDrag *transactionDrag = nullptr; if (at >= 0) { transactionDrag = transactions.at(at).drag; } else if (at == -2) { @@ -1318,7 +1318,7 @@ bool QXcbDrag::dndEnable(QXcbWindow *w, bool on) if (w->window()->type() == Qt::Desktop) { xcb_delete_property(xcb_connection(), w->xcb_window(), atom(QXcbAtom::XdndProxy)); delete desktop_proxy; - desktop_proxy = 0; + desktop_proxy = nullptr; } else { qCDebug(lcQpaXDnd) << "not deleting XDndAware"; } @@ -1344,11 +1344,11 @@ QXcbDropData::~QXcbDropData() QVariant QXcbDropData::retrieveData_sys(const QString &mimetype, QVariant::Type requestedType) const { QByteArray mime = mimetype.toLatin1(); - QVariant data = xdndObtainData(mime, requestedType); + QVariant data = xdndObtainData(mime, QMetaType::Type(requestedType)); return data; } -QVariant QXcbDropData::xdndObtainData(const QByteArray &format, QVariant::Type requestedType) const +QVariant QXcbDropData::xdndObtainData(const QByteArray &format, QMetaType::Type requestedType) const { QByteArray result; diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h index b6371041e6..0d16afc47e 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.h +++ b/src/plugins/platforms/xcb/qxcbdrag.h @@ -90,7 +90,7 @@ public: void handlePosition(QPlatformWindow *w, const xcb_client_message_event_t *event); void handleLeave(QPlatformWindow *w, const xcb_client_message_event_t *event); void handleDrop(QPlatformWindow *, const xcb_client_message_event_t *event, - Qt::MouseButtons b = nullptr, Qt::KeyboardModifiers mods = nullptr); + Qt::MouseButtons b = { }, Qt::KeyboardModifiers mods = { }); void handleStatus(const xcb_client_message_event_t *event); void handleSelectionRequest(const xcb_selection_request_event_t *event); @@ -113,7 +113,7 @@ private: void init(); void handle_xdnd_position(QPlatformWindow *w, const xcb_client_message_event_t *event, - Qt::MouseButtons b = nullptr, Qt::KeyboardModifiers mods = nullptr); + Qt::MouseButtons b = { }, Qt::KeyboardModifiers mods = { }); void handle_xdnd_status(const xcb_client_message_event_t *event); void send_leave(); diff --git a/src/plugins/platforms/xcb/qxcbimage.cpp b/src/plugins/platforms/xcb/qxcbimage.cpp index 8f33e6ed31..b0e610dd51 100644 --- a/src/plugins/platforms/xcb/qxcbimage.cpp +++ b/src/plugins/platforms/xcb/qxcbimage.cpp @@ -221,7 +221,7 @@ xcb_pixmap_t qt_xcb_XPixmapFromBitmap(QXcbScreen *screen, const QImage &image) for (int i = 0; i < height; i++) memcpy(buf + (destLineSize * i), map + (bytesPerLine * i), destLineSize); xcb_pixmap_t pm = xcb_create_pixmap_from_bitmap_data(conn, screen->root(), buf, - width, height, 1, 0, 0, 0); + width, height, 1, 0, 0, nullptr); delete[] buf; return pm; } @@ -249,7 +249,7 @@ xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image, 32, 32, 32, 32, QSysInfo::ByteOrder == QSysInfo::BigEndian ? XCB_IMAGE_ORDER_MSB_FIRST : XCB_IMAGE_ORDER_LSB_FIRST, XCB_IMAGE_ORDER_MSB_FIRST, - 0, 0, 0); + nullptr, 0, nullptr); if (!xi) { qWarning("qt_xcb_createCursorXRender: xcb_image_create failed"); return XCB_NONE; @@ -266,10 +266,10 @@ xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image, xcb_create_pixmap(conn, 32, pix, screen->root(), w, h); xcb_render_picture_t pic = xcb_generate_id(conn); - xcb_render_create_picture(conn, pic, pix, fmt->id, 0, 0); + xcb_render_create_picture(conn, pic, pix, fmt->id, 0, nullptr); xcb_gcontext_t gc = xcb_generate_id(conn); - xcb_create_gc(conn, gc, pix, 0, 0); + xcb_create_gc(conn, gc, pix, 0, nullptr); xcb_image_put(conn, pix, gc, xi, 0, 0, 0); xcb_free_gc(conn, gc); diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index efda6b67ce..3fd989e1f9 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -130,7 +130,7 @@ QXcbIntegration *QXcbIntegration::m_instance = nullptr; QXcbIntegration::QXcbIntegration(const QStringList ¶meters, int &argc, char **argv) : m_services(new QGenericUnixServices) - , m_instanceName(0) + , m_instanceName(nullptr) , m_canGrab(true) , m_defaultVisualId(UINT_MAX) { @@ -146,7 +146,7 @@ QXcbIntegration::QXcbIntegration(const QStringList ¶meters, int &argc, char m_nativeInterface.reset(new QXcbNativeInterface); // Parse arguments - const char *displayName = 0; + const char *displayName = nullptr; bool noGrabArg = false; bool doGrabArg = false; if (argc) { diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index d0e02ecdd1..e8286381a2 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -49,13 +49,7 @@ #include <private/qguiapplication_p.h> -#if QT_CONFIG(xkb) -#include <xkbcommon/xkbcommon-x11.h> -#endif - -#if QT_CONFIG(xcb_xinput) #include <xcb/xinput.h> -#endif QT_BEGIN_NAMESPACE @@ -392,20 +386,16 @@ void QXcbKeyboard::updateKeymap() xkb_context_set_log_level(m_xkbContext.get(), logLevel); } -#if QT_CONFIG(xkb) if (connection()->hasXKB()) { m_xkbKeymap.reset(xkb_x11_keymap_new_from_device(m_xkbContext.get(), xcb_connection(), core_device_id, XKB_KEYMAP_COMPILE_NO_FLAGS)); if (m_xkbKeymap) m_xkbState.reset(xkb_x11_state_new_from_device(m_xkbKeymap.get(), xcb_connection(), core_device_id)); } else { -#endif m_xkbKeymap.reset(keymapFromCore(keysymMods)); if (m_xkbKeymap) m_xkbState.reset(xkb_state_new(m_xkbKeymap.get())); -#if QT_CONFIG(xkb) } -#endif if (!m_xkbKeymap) { qCWarning(lcQpaKeyboard, "failed to compile a keymap"); @@ -428,7 +418,6 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const return QXkbCommon::possibleKeys(m_xkbState.get(), event, m_superAsMeta, m_hyperAsMeta); } -#if QT_CONFIG(xkb) void QXcbKeyboard::updateXKBState(xcb_xkb_state_notify_event_t *state) { if (m_config && connection()->hasXKB()) { @@ -444,7 +433,6 @@ void QXcbKeyboard::updateXKBState(xcb_xkb_state_notify_event_t *state) handleStateChanges(changedComponents); } } -#endif static xkb_layout_index_t lockedGroup(quint16 state) { @@ -473,7 +461,6 @@ void QXcbKeyboard::updateXKBStateFromCore(quint16 state) } } -#if QT_CONFIG(xcb_xinput) void QXcbKeyboard::updateXKBStateFromXI(void *modInfo, void *groupInfo) { if (m_config && !connection()->hasXKB()) { @@ -491,7 +478,6 @@ void QXcbKeyboard::updateXKBStateFromXI(void *modInfo, void *groupInfo) handleStateChanges(changedComponents); } } -#endif void QXcbKeyboard::handleStateChanges(xkb_state_component changedComponents) { @@ -541,7 +527,6 @@ void QXcbKeyboard::updateXKBMods() QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection) : QXcbObject(connection) { -#if QT_CONFIG(xkb) core_device_id = 0; if (connection->hasXKB()) { selectEvents(); @@ -551,11 +536,9 @@ QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection) return; } } else { -#endif m_key_symbols = xcb_key_symbols_alloc(xcb_connection()); -#if QT_CONFIG(xkb) } -#endif + updateKeymap(); } @@ -573,7 +556,6 @@ void QXcbKeyboard::initialize() void QXcbKeyboard::selectEvents() { -#if QT_CONFIG(xkb) const uint16_t required_map_parts = (XCB_XKB_MAP_PART_KEY_TYPES | XCB_XKB_MAP_PART_KEY_SYMS | XCB_XKB_MAP_PART_MODIFIER_MAP | @@ -597,19 +579,17 @@ void QXcbKeyboard::selectEvents() required_events, required_map_parts, required_map_parts, - 0); + nullptr); xcb_generic_error_t *error = xcb_request_check(xcb_connection(), select); if (error) { free(error); qCWarning(lcQpaXcb, "failed to select notify events from XKB"); } -#endif } void QXcbKeyboard::updateVModMapping() { -#if QT_CONFIG(xkb) xcb_xkb_get_names_value_list_t names_list; memset(&vmod_masks, 0, sizeof(vmod_masks)); @@ -640,7 +620,7 @@ void QXcbKeyboard::updateVModMapping() vmod_mask = name_reply->virtualMods; // find the virtual modifiers for which names are defined. for (bit = 1; vmod_mask; bit <<= 1) { - vmod_name = 0; + vmod_name = nullptr; if (!(vmod_mask & bit)) continue; @@ -667,12 +647,10 @@ void QXcbKeyboard::updateVModMapping() else if (qstrcmp(vmod_name, "Hyper") == 0) vmod_masks.hyper = bit; } -#endif } void QXcbKeyboard::updateVModToRModMapping() { -#if QT_CONFIG(xkb) xcb_xkb_get_map_map_t map; memset(&rmod_masks, 0, sizeof(rmod_masks)); @@ -729,7 +707,6 @@ void QXcbKeyboard::updateVModToRModMapping() else if (vmod_masks.hyper == bit) rmod_masks.hyper = modmap; } -#endif } // Small helper: set modifier bit, if modifier position is valid diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h index e35c82ad24..0ee08aeff2 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.h +++ b/src/plugins/platforms/xcb/qxcbkeyboard.h @@ -43,14 +43,12 @@ #include "qxcbobject.h" #include <xcb/xcb_keysyms.h> -#if QT_CONFIG(xkb) #define explicit dont_use_cxx_explicit #include <xcb/xkb.h> #undef explicit -#endif -#include <xkbcommon/xkbcommon.h> #include <QtXkbCommonSupport/private/qxkbcommon_p.h> +#include <xkbcommon/xkbcommon-x11.h> #include <QEvent> @@ -74,18 +72,14 @@ public: void updateKeymap(); QList<int> possibleKeys(const QKeyEvent *event) const; - // when XKEYBOARD not present on the X server void updateXKBMods(); xkb_mod_mask_t xkbModMask(quint16 state); void updateXKBStateFromCore(quint16 state); -#if QT_CONFIG(xcb_xinput) void updateXKBStateFromXI(void *modInfo, void *groupInfo); -#endif -#if QT_CONFIG(xkb) - // when XKEYBOARD is present on the X server + int coreDeviceId() const { return core_device_id; } void updateXKBState(xcb_xkb_state_notify_event_t *state); -#endif + void handleStateChanges(xkb_state_component changedComponents); protected: @@ -97,10 +91,9 @@ protected: typedef QMap<xcb_keysym_t, int> KeysymModifierMap; struct xkb_keymap *keymapFromCore(const KeysymModifierMap &keysymMods); - // when XKEYBOARD not present on the X server void updateModifiers(const KeysymModifierMap &keysymMods); KeysymModifierMap keysymsToModifiers(); - // when XKEYBOARD is present on the X server + void updateVModMapping(); void updateVModToRModMapping(); @@ -119,7 +112,6 @@ private: _mod_masks rmod_masks; - // when XKEYBOARD not present on the X server xcb_key_symbols_t *m_key_symbols = nullptr; struct _xkb_mods { xkb_mod_index_t shift; @@ -132,11 +124,9 @@ private: xkb_mod_index_t mod5; }; _xkb_mods xkb_mods; -#if QT_CONFIG(xkb) - // when XKEYBOARD is present on the X server + _mod_masks vmod_masks; int core_device_id; -#endif QXkbCommon::ScopedXKBState m_xkbState; QXkbCommon::ScopedXKBKeymap m_xkbKeymap; diff --git a/src/plugins/platforms/xcb/qxcbmime.cpp b/src/plugins/platforms/xcb/qxcbmime.cpp index d611f86a9c..0b3219f792 100644 --- a/src/plugins/platforms/xcb/qxcbmime.cpp +++ b/src/plugins/platforms/xcb/qxcbmime.cpp @@ -159,7 +159,7 @@ QVector<xcb_atom_t> QXcbMime::mimeAtomsForFormat(QXcbConnection *connection, con } QVariant QXcbMime::mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a, const QByteArray &d, const QString &format, - QVariant::Type requestedType, const QByteArray &encoding) + QMetaType::Type requestedType, const QByteArray &encoding) { QByteArray data = d; QString atomName = mimeAtomToString(connection, a); @@ -169,7 +169,7 @@ QVariant QXcbMime::mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a, && atomName == format + QLatin1String(";charset=") + QLatin1String(encoding)) { #if QT_CONFIG(textcodec) - if (requestedType == QVariant::String) { + if (requestedType == QMetaType::QString) { QTextCodec *codec = QTextCodec::codecForName(encoding); if (codec) return codec->toUnicode(data); @@ -264,7 +264,7 @@ QVariant QXcbMime::mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a, return QVariant(); } -xcb_atom_t QXcbMime::mimeAtomForFormat(QXcbConnection *connection, const QString &format, QVariant::Type requestedType, +xcb_atom_t QXcbMime::mimeAtomForFormat(QXcbConnection *connection, const QString &format, QMetaType::Type requestedType, const QVector<xcb_atom_t> &atoms, QByteArray *requestedEncoding) { requestedEncoding->clear(); @@ -297,7 +297,7 @@ xcb_atom_t QXcbMime::mimeAtomForFormat(QXcbConnection *connection, const QString // for string/text requests try to use a format with a well-defined charset // first to avoid encoding problems - if (requestedType == QVariant::String + if (requestedType == QMetaType::QString && format.startsWith(QLatin1String("text/")) && !format.contains(QLatin1String("charset="))) { diff --git a/src/plugins/platforms/xcb/qxcbmime.h b/src/plugins/platforms/xcb/qxcbmime.h index f2136ec9f4..dcb4f6b6c6 100644 --- a/src/plugins/platforms/xcb/qxcbmime.h +++ b/src/plugins/platforms/xcb/qxcbmime.h @@ -60,8 +60,8 @@ public: static bool mimeDataForAtom(QXcbConnection *connection, xcb_atom_t a, QMimeData *mimeData, QByteArray *data, xcb_atom_t *atomFormat, int *dataFormat); static QVariant mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a, const QByteArray &data, const QString &format, - QVariant::Type requestedType, const QByteArray &encoding); - static xcb_atom_t mimeAtomForFormat(QXcbConnection *connection, const QString &format, QVariant::Type requestedType, + QMetaType::Type requestedType, const QByteArray &encoding); + static xcb_atom_t mimeAtomForFormat(QXcbConnection *connection, const QString &format, QMetaType::Type requestedType, const QVector<xcb_atom_t> &atoms, QByteArray *requestedEncoding); }; diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index 81b889a80f..30fa6864ac 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -268,7 +268,7 @@ QPlatformNativeInterface::NativeResourceForIntegrationFunction QXcbNativeInterfa if (lowerCaseResource == "peekeventqueue") return NativeResourceForIntegrationFunction(reinterpret_cast<void *>(peekEventQueue)); - return 0; + return nullptr; } QPlatformNativeInterface::NativeResourceForContextFunction QXcbNativeInterface::nativeResourceFunctionForContext(const QByteArray &resource) @@ -291,7 +291,7 @@ QPlatformNativeInterface::NativeResourceForScreenFunction QXcbNativeInterface::n return NativeResourceForScreenFunction(reinterpret_cast<void *>(setAppTime)); else if (lowerCaseResource == "setappusertime") return NativeResourceForScreenFunction(reinterpret_cast<void *>(setAppUserTime)); - return 0; + return nullptr; } QPlatformNativeInterface::NativeResourceForWindowFunction QXcbNativeInterface::nativeResourceFunctionForWindow(const QByteArray &resource) @@ -365,7 +365,7 @@ void *QXcbNativeInterface::startupId() QXcbConnection *defaultConnection = integration->defaultConnection(); if (defaultConnection) return reinterpret_cast<void *>(const_cast<char *>(defaultConnection->startupId().constData())); - return 0; + return nullptr; } void *QXcbNativeInterface::x11Screen() @@ -374,7 +374,7 @@ void *QXcbNativeInterface::x11Screen() QXcbConnection *defaultConnection = integration->defaultConnection(); if (defaultConnection) return reinterpret_cast<void *>(defaultConnection->primaryScreenNumber()); - return 0; + return nullptr; } void *QXcbNativeInterface::rootWindow() @@ -383,7 +383,7 @@ void *QXcbNativeInterface::rootWindow() QXcbConnection *defaultConnection = integration->defaultConnection(); if (defaultConnection) return reinterpret_cast<void *>(defaultConnection->rootWindow()); - return 0; + return nullptr; } void *QXcbNativeInterface::display() diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 87e1c9bdf8..505f7343ce 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -467,7 +467,7 @@ const xcb_visualtype_t *QXcbVirtualDesktop::visualForId(xcb_visualid_t visualid) { QMap<xcb_visualid_t, xcb_visualtype_t>::const_iterator it = m_visuals.find(visualid); if (it == m_visuals.constEnd()) - return 0; + return nullptr; return &*it; } @@ -587,7 +587,7 @@ QWindow *QXcbScreen::topLevelAt(const QPoint &p) const do { auto translate_reply = Q_XCB_REPLY_UNCHECKED(xcb_translate_coordinates, xcb_connection(), parent, child, x, y); if (!translate_reply) { - return 0; + return nullptr; } parent = child; @@ -596,14 +596,14 @@ QWindow *QXcbScreen::topLevelAt(const QPoint &p) const y = translate_reply->dst_y; if (!child || child == root) - return 0; + return nullptr; QPlatformWindow *platformWindow = connection()->platformWindowFromId(child); if (platformWindow) return platformWindow->window(); } while (parent != child); - return 0; + return nullptr; } void QXcbScreen::windowShown(QXcbWindow *window) diff --git a/src/plugins/platforms/xcb/qxcbsessionmanager.cpp b/src/plugins/platforms/xcb/qxcbsessionmanager.cpp index f880d4d722..e9697f505b 100644 --- a/src/plugins/platforms/xcb/qxcbsessionmanager.cpp +++ b/src/plugins/platforms/xcb/qxcbsessionmanager.cpp @@ -61,15 +61,15 @@ public: QSmSocketReceiver(int socket) { QSocketNotifier* sn = new QSocketNotifier(socket, QSocketNotifier::Read, this); - connect(sn, SIGNAL(activated(int)), this, SLOT(socketActivated(int))); + connect(sn, SIGNAL(activated(QSocketDescriptor)), this, SLOT(socketActivated())); } public Q_SLOTS: - void socketActivated(int); + void socketActivated(); }; -static SmcConn smcConnection = 0; +static SmcConn smcConnection = nullptr; static bool sm_interactionActive; static bool sm_smActive; static int sm_interactStyle; @@ -81,7 +81,7 @@ static bool sm_phase2; static bool sm_in_phase2; bool qt_sm_blockUserInput = false; -static QSmSocketReceiver* sm_receiver = 0; +static QSmSocketReceiver* sm_receiver = nullptr; static void resetSmState(); static void sm_setProperty(const char *name, const char *type, @@ -191,7 +191,7 @@ static void sm_performSaveYourself(QXcbSessionManager *sm) // generate a new session key timeval tv; - gettimeofday(&tv, 0); + gettimeofday(&tv, nullptr); sm->setSessionKey(QString::number(qulonglong(tv.tv_sec)) + QLatin1Char('_') + QString::number(qulonglong(tv.tv_usec))); @@ -203,7 +203,7 @@ static void sm_performSaveYourself(QXcbSessionManager *sm) // tell the session manager about our program in best POSIX style sm_setProperty(QString::fromLatin1(SmProgram), argument0); // tell the session manager about our user as well. - struct passwd *entryPtr = 0; + struct passwd *entryPtr = nullptr; #if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0) QVarLengthArray<char, 1024> buf(qMax<long>(sysconf(_SC_GETPW_R_SIZE_MAX), 1024L)); struct passwd entry; @@ -327,9 +327,9 @@ static void sm_saveYourselfPhase2Callback(SmcConn smcConn, SmPointer clientData) } -void QSmSocketReceiver::socketActivated(int) +void QSmSocketReceiver::socketActivated() { - IceProcessMessages(SmcGetIceConnection(smcConnection), 0, 0); + IceProcessMessages(SmcGetIceConnection(smcConnection), nullptr, nullptr); } @@ -337,11 +337,11 @@ void QSmSocketReceiver::socketActivated(int) QXcbSessionManager::QXcbSessionManager(const QString &id, const QString &key) : QPlatformSessionManager(id, key) - , m_eventLoop(0) + , m_eventLoop(nullptr) { resetSmState(); char cerror[256]; - char* myId = 0; + char* myId = nullptr; QByteArray b_id = id.toLatin1(); char* prevId = b_id.data(); @@ -359,7 +359,7 @@ QXcbSessionManager::QXcbSessionManager(const QString &id, const QString &key) if (!qEnvironmentVariableIsSet("SESSION_MANAGER")) return; - smcConnection = SmcOpenConnection(0, 0, 1, 0, + smcConnection = SmcOpenConnection(nullptr, nullptr, 1, 0, SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask | @@ -382,8 +382,8 @@ QXcbSessionManager::QXcbSessionManager(const QString &id, const QString &key) QXcbSessionManager::~QXcbSessionManager() { if (smcConnection) - SmcCloseConnection(smcConnection, 0, 0); - smcConnection = 0; + SmcCloseConnection(smcConnection, 0, nullptr); + smcConnection = nullptr; delete sm_receiver; } @@ -411,7 +411,7 @@ bool QXcbSessionManager::allowsInteraction() QEventLoop eventLoop; m_eventLoop = &eventLoop; eventLoop.exec(); - m_eventLoop = 0; + m_eventLoop = nullptr; sm_waitingForInteraction = false; if (sm_smActive) { // not cancelled @@ -441,7 +441,7 @@ bool QXcbSessionManager::allowsErrorInteraction() QEventLoop eventLoop; m_eventLoop = &eventLoop; eventLoop.exec(); - m_eventLoop = 0; + m_eventLoop = nullptr; sm_waitingForInteraction = false; if (sm_smActive) { // not cancelled diff --git a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp index 684e603fab..ff5ad98cd2 100644 --- a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp +++ b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp @@ -64,11 +64,11 @@ QXcbSystemTrayTracker *QXcbSystemTrayTracker::create(QXcbConnection *connection) // Selection, tray atoms for GNOME, NET WM Specification const xcb_atom_t trayAtom = connection->atom(QXcbAtom::_NET_SYSTEM_TRAY_OPCODE); if (!trayAtom) - return 0; + return nullptr; const QByteArray netSysTray = QByteArrayLiteral("_NET_SYSTEM_TRAY_S") + QByteArray::number(connection->primaryScreenNumber()); const xcb_atom_t selection = connection->internAtom(netSysTray.constData()); if (!selection) - return 0; + return nullptr; return new QXcbSystemTrayTracker(connection, trayAtom, selection); } diff --git a/src/plugins/platforms/xcb/qxcbvulkaninstance.cpp b/src/plugins/platforms/xcb/qxcbvulkaninstance.cpp index b3f8a5832d..bb82bcec39 100644 --- a/src/plugins/platforms/xcb/qxcbvulkaninstance.cpp +++ b/src/plugins/platforms/xcb/qxcbvulkaninstance.cpp @@ -93,7 +93,7 @@ bool QXcbVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice, VkSurfaceKHR QXcbVulkanInstance::createSurface(QXcbWindow *window) { - VkSurfaceKHR surface = 0; + VkSurfaceKHR surface = VK_NULL_HANDLE; if (!m_createSurface) { m_createSurface = reinterpret_cast<PFN_vkCreateXcbSurfaceKHR>( diff --git a/src/plugins/platforms/xcb/qxcbvulkanwindow.cpp b/src/plugins/platforms/xcb/qxcbvulkanwindow.cpp index 25bc340f97..a05ecab51d 100644 --- a/src/plugins/platforms/xcb/qxcbvulkanwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbvulkanwindow.cpp @@ -43,7 +43,7 @@ QT_BEGIN_NAMESPACE QXcbVulkanWindow::QXcbVulkanWindow(QWindow *window) : QXcbWindow(window), - m_surface(0) + m_surface(VK_NULL_HANDLE) { } diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index a5974ec36e..40106bbeaf 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -67,9 +67,7 @@ #include <xcb/xcb_icccm.h> #include <xcb/xfixes.h> #include <xcb/shape.h> -#if QT_CONFIG(xcb_xinput) #include <xcb/xinput.h> -#endif #include <private/qguiapplication_p.h> #include <private/qwindow_p.h> @@ -176,13 +174,13 @@ static inline XTextProperty* qstringToXTP(Display *dpy, const QString& s) { #include <X11/Xatom.h> - static XTextProperty tp = { 0, 0, 0, 0 }; + static XTextProperty tp = { nullptr, 0, 0, 0 }; static bool free_prop = true; // we can't free tp.value in case it references // the data of the static QByteArray below. if (tp.value) { if (free_prop) XFree(tp.value); - tp.value = 0; + tp.value = nullptr; free_prop = true; } @@ -193,7 +191,7 @@ static inline XTextProperty* qstringToXTP(Display *dpy, const QString& s) QByteArray mapped = mapper->fromUnicode(s); char* tl[2]; tl[0] = mapped.data(); - tl[1] = 0; + tl[1] = nullptr; errCode = XmbTextListToTextProperty(dpy, tl, 1, XStdICCTextStyle, &tp); if (errCode < 0) qCDebug(lcQpaXcb, "XmbTextListToTextProperty result code %d", errCode); @@ -284,7 +282,7 @@ void QXcbWindow::create() m_window = platformScreen->root(); m_depth = platformScreen->screen()->root_depth; m_visualId = platformScreen->screen()->root_visual; - const xcb_visualtype_t *visual = 0; + const xcb_visualtype_t *visual = nullptr; if (connection()->hasDefaultVisualId()) { visual = platformScreen->visualForId(connection()->defaultVisualId()); if (visual) @@ -494,14 +492,12 @@ void QXcbWindow::create() atom(QXcbAtom::_XEMBED_INFO), 32, 2, (void *)data); -#if QT_CONFIG(xcb_xinput) if (connection()->hasXInput2()) { if (connection()->xi2MouseEventsDisabled()) connection()->xi2SelectDeviceEventsCompatibility(m_window); else connection()->xi2SelectDeviceEvents(m_window); } -#endif setWindowState(window()->windowStates()); setWindowFlags(window()->flags()); @@ -825,7 +821,7 @@ bool QXcbWindow::relayFocusToModalWindow() const while (w && w->parent()) w = w->parent(); - QWindow *modalWindow = 0; + QWindow *modalWindow = nullptr; const bool blocked = QGuiApplicationPrivate::instance()->isWindowBlocked(w, &modalWindow); if (blocked && modalWindow != w) { modalWindow->requestActivate(); @@ -882,7 +878,7 @@ enum { QXcbWindow::NetWmStates QXcbWindow::netWmStates() { - NetWmStates result(0); + NetWmStates result; auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_STATE), @@ -935,10 +931,10 @@ void QXcbWindow::setWindowFlags(Qt::WindowFlags flags) xcb_change_window_attributes(xcb_connection(), xcb_window(), mask, values); - QXcbWindowFunctions::WmWindowTypes wmWindowTypes = 0; + QXcbWindowFunctions::WmWindowTypes wmWindowTypes; if (window()->dynamicPropertyNames().contains(wm_window_type_property_id)) { wmWindowTypes = static_cast<QXcbWindowFunctions::WmWindowTypes>( - window()->property(wm_window_type_property_id).value<int>()); + qvariant_cast<int>(window()->property(wm_window_type_property_id))); } setWmWindowType(wmWindowTypes, flags); @@ -1071,7 +1067,7 @@ void QXcbWindow::setNetWmStateOnUnmappedWindow() if (Q_UNLIKELY(m_mapped)) qCWarning(lcQpaXcb()) << "internal error: " << Q_FUNC_INFO << "called on mapped window"; - NetWmStates states(0); + NetWmStates states; const Qt::WindowFlags flags = window()->flags(); if (flags & Qt::WindowStaysOnTopHint) { states |= NetWmStateAbove; @@ -1206,7 +1202,7 @@ void QXcbWindow::updateNetWmUserTime(xcb_timestamp_t timestamp) XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class m_visualId, // visual 0, // value mask - 0); // value list + nullptr); // value list wid = m_netWmUserTimeWindow; xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, atom(QXcbAtom::_NET_WM_USER_TIME_WINDOW), XCB_ATOM_WINDOW, 32, 1, &m_netWmUserTimeWindow); @@ -1236,7 +1232,7 @@ void QXcbWindow::setTransparentForMouseEvents(bool transparent) xcb_rectangle_t rectangle; - xcb_rectangle_t *rect = 0; + xcb_rectangle_t *rect = nullptr; int nrect = 0; if (!transparent) { @@ -1492,7 +1488,7 @@ uint QXcbWindow::visualIdStatic(QWindow *window) QXcbWindowFunctions::WmWindowTypes QXcbWindow::wmWindowTypes() const { - QXcbWindowFunctions::WmWindowTypes result(0); + QXcbWindowFunctions::WmWindowTypes result; auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE), @@ -1900,7 +1896,7 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in if (m_embedded && !m_trayIconWindow) { if (window() != QGuiApplication::focusWindow()) { const QXcbWindow *container = static_cast<const QXcbWindow *>(parent()); - Q_ASSERT(container != 0); + Q_ASSERT(container != nullptr); sendXEmbedMessage(container->xcb_window(), XEMBED_REQUEST_FOCUS); } @@ -1909,9 +1905,7 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in QPoint global(root_x, root_y); if (isWheel) { -#if QT_CONFIG(xcb_xinput) if (!connection()->isAtLeastXI21()) { -#endif QPoint angleDelta; if (detail == 4) angleDelta.setY(120); @@ -1924,9 +1918,7 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in if (modifiers & Qt::AltModifier) angleDelta = angleDelta.transposed(); QWindowSystemInterface::handleWheelEvent(window(), timestamp, local, global, QPoint(), angleDelta, modifiers); -#if QT_CONFIG(xcb_xinput) } -#endif return; } @@ -1962,13 +1954,8 @@ static inline bool doCheckUnGrabAncestor(QXcbConnection *conn) * not pressed, otherwise (e.g. on Alt+Tab) it can igonre important enter/leave events. */ if (conn) { - const bool mouseButtonsPressed = (conn->buttonState() != Qt::NoButton); -#if QT_CONFIG(xcb_xinput) return mouseButtonsPressed || (conn->hasXInput2() && !conn->xi2MouseEventsDisabled()); -#else - return mouseButtonsPressed; -#endif } return true; } @@ -2000,10 +1987,9 @@ void QXcbWindow::handleEnterNotifyEvent(int event_x, int event_y, int root_x, in if (ignoreEnterEvent(mode, detail, connection()) || connection()->mousePressWindow()) return; -#if QT_CONFIG(xcb_xinput) + // Updates scroll valuators, as user might have done some scrolling outside our X client. connection()->xi2UpdateScrollingDevices(); -#endif const QPoint local(event_x, event_y); QWindowSystemInterface::handleEnterEvent(window(), local, global); @@ -2078,7 +2064,6 @@ void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event) event->time, QEvent::MouseMove); } -#if QT_CONFIG(xcb_xinput) static inline int fixed1616ToInt(xcb_input_fp1616_t val) { return int(qreal(val) / 0x10000); @@ -2116,7 +2101,7 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource const Qt::MouseButton button = conn->xiToQtMouseButton(ev->detail); - const char *sourceName = 0; + const char *sourceName = nullptr; if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) { const QMetaObject *metaObject = qt_getEnumMetaObject(source); const QMetaEnum me = metaObject->enumerator(metaObject->indexOfEnumerator(qt_getEnumName(source))); @@ -2179,13 +2164,13 @@ void QXcbWindow::handleXIEnterLeave(xcb_ge_event_t *event) break; } } -#endif QXcbWindow *QXcbWindow::toWindow() { return this; } void QXcbWindow::handleMouseEvent(xcb_timestamp_t time, const QPoint &local, const QPoint &global, Qt::KeyboardModifiers modifiers, QEvent::Type type, Qt::MouseEventSource source) { + m_lastPointerPosition = local; connection()->setTime(time); Qt::MouseButton button = type == QEvent::MouseMove ? Qt::NoButton : connection()->button(); QWindowSystemInterface::handleMouseEvent(window(), time, local, global, @@ -2321,14 +2306,12 @@ bool QXcbWindow::setMouseGrabEnabled(bool grab) if (grab && !connection()->canGrab()) return false; -#if QT_CONFIG(xcb_xinput) if (connection()->hasXInput2() && !connection()->xi2MouseEventsDisabled()) { bool result = connection()->xi2SetMouseGrabEnabled(m_window, grab); if (grab && result) connection()->setMouseGrabber(this); return result; } -#endif if (!grab) { xcb_ungrab_pointer(xcb_connection(), XCB_TIME_CURRENT_TIME); @@ -2378,47 +2361,65 @@ bool QXcbWindow::windowEvent(QEvent *event) return QPlatformWindow::windowEvent(event); } -bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner) +bool QXcbWindow::startSystemResize(Qt::Edges edges) { - return startSystemMoveResize(pos, corner); + return startSystemMoveResize(m_lastPointerPosition, edges); } -bool QXcbWindow::startSystemMove(const QPoint &pos) +bool QXcbWindow::startSystemMove() { - return startSystemMoveResize(pos, 4); + return startSystemMoveResize(m_lastPointerPosition, 16); } -bool QXcbWindow::startSystemMoveResize(const QPoint &pos, int corner) +bool QXcbWindow::startSystemMoveResize(const QPoint &pos, int edges) { - return false; // ### FIXME QTBUG-69716 const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE); if (!connection()->wmSupport()->isSupportedByWM(moveResize)) return false; - const QPoint globalPos = QHighDpi::toNativePixels(window()->mapToGlobal(pos), window()->screen()); -#if QT_CONFIG(xcb_xinput) // ### FIXME QTBUG-53389 - bool startedByTouch = connection()->startSystemMoveResizeForTouchBegin(m_window, globalPos, corner); + bool startedByTouch = connection()->startSystemMoveResizeForTouch(m_window, edges); if (startedByTouch) { - if (connection()->isUnity() || connection()->isGnome()) { - // These desktops fail to move/resize via _NET_WM_MOVERESIZE (WM bug?). + if (connection()->isUnity()) { + // Unity fails to move/resize via _NET_WM_MOVERESIZE (WM bug?). connection()->abortSystemMoveResizeForTouch(); return false; } - // KWin, Openbox, AwesomeWM have been tested to work with _NET_WM_MOVERESIZE. - } else -#endif - { // Started by mouse press. + // KWin, Openbox, AwesomeWM and Gnome have been tested to work with _NET_WM_MOVERESIZE. + } else { // Started by mouse press. if (connection()->isUnity()) return false; // _NET_WM_MOVERESIZE on this WM is bouncy (WM bug?). - doStartSystemMoveResize(globalPos, corner); + doStartSystemMoveResize(mapToGlobal(pos), edges); } return true; } -void QXcbWindow::doStartSystemMoveResize(const QPoint &globalPos, int corner) +static uint qtEdgesToXcbMoveResizeDirection(Qt::Edges edges) +{ + if (edges == (Qt::TopEdge | Qt::LeftEdge)) + return 0; + if (edges == Qt::TopEdge) + return 1; + if (edges == (Qt::TopEdge | Qt::RightEdge)) + return 2; + if (edges == Qt::RightEdge) + return 3; + if (edges == (Qt::RightEdge | Qt::BottomEdge)) + return 4; + if (edges == Qt::BottomEdge) + return 5; + if (edges == (Qt::BottomEdge | Qt::LeftEdge)) + return 6; + if (edges == Qt::LeftEdge) + return 7; + + qWarning() << "Cannot convert " << edges << "to _NET_WM_MOVERESIZE direction."; + return 0; +} + +void QXcbWindow::doStartSystemMoveResize(const QPoint &globalPos, int edges) { const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE); xcb_client_message_event_t xev; @@ -2429,16 +2430,10 @@ void QXcbWindow::doStartSystemMoveResize(const QPoint &globalPos, int corner) xev.format = 32; xev.data.data32[0] = globalPos.x(); xev.data.data32[1] = globalPos.y(); - if (corner == 4) { + if (edges == 16) xev.data.data32[2] = 8; // move - } else { - const bool bottom = corner == Qt::BottomRightCorner || corner == Qt::BottomLeftCorner; - const bool left = corner == Qt::BottomLeftCorner || corner == Qt::TopLeftCorner; - if (bottom) - xev.data.data32[2] = left ? 6 : 4; // bottomleft/bottomright - else - xev.data.data32[2] = left ? 0 : 2; // topleft/topright - } + else + xev.data.data32[2] = qtEdgesToXcbMoveResizeDirection(Qt::Edges(edges)); xev.data.data32[3] = XCB_BUTTON_INDEX_1; xev.data.data32[4] = 0; xcb_ungrab_pointer(connection()->xcb_connection(), XCB_CURRENT_TIME); diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index b84250d109..0cdc40f82d 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -108,8 +108,8 @@ public: bool windowEvent(QEvent *event) override; - bool startSystemResize(const QPoint &pos, Qt::Corner corner) override; - bool startSystemMove(const QPoint &pos) override; + bool startSystemResize(Qt::Edges edges) override; + bool startSystemMove() override; void setOpacity(qreal level) override; void setMask(const QRegion ®ion) override; @@ -138,10 +138,8 @@ public: void handleFocusInEvent(const xcb_focus_in_event_t *event) override; void handleFocusOutEvent(const xcb_focus_out_event_t *event) override; void handlePropertyNotifyEvent(const xcb_property_notify_event_t *event) override; -#if QT_CONFIG(xcb_xinput) void handleXIMouseEvent(xcb_ge_event_t *, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized) override; void handleXIEnterLeave(xcb_ge_event_t *) override; -#endif QXcbWindow *toWindow() override; @@ -171,8 +169,8 @@ public: QXcbScreen *xcbScreen() const; - bool startSystemMoveResize(const QPoint &pos, int corner); - void doStartSystemMoveResize(const QPoint &globalPos, int corner); + bool startSystemMoveResize(const QPoint &pos, int edges); + void doStartSystemMoveResize(const QPoint &globalPos, int edges); static bool isTrayIconWindow(QWindow *window) { @@ -267,6 +265,7 @@ protected: QRegion m_exposeRegion; QSize m_oldWindowSize; + QPoint m_lastPointerPosition; xcb_visualid_t m_visualId = 0; // Last sent state. Initialized to an invalid state, on purpose. diff --git a/src/plugins/platforms/xcb/qxcbxsettings.cpp b/src/plugins/platforms/xcb/qxcbxsettings.cpp index 88f15e344f..902f196ba9 100644 --- a/src/plugins/platforms/xcb/qxcbxsettings.cpp +++ b/src/plugins/platforms/xcb/qxcbxsettings.cpp @@ -256,7 +256,7 @@ QXcbXSettings::QXcbXSettings(QXcbVirtualDesktop *screen) QXcbXSettings::~QXcbXSettings() { delete d_ptr; - d_ptr = 0; + d_ptr = nullptr; } bool QXcbXSettings::initialized() const diff --git a/src/plugins/platforms/xcb/xcb-static/xcb-static.pro b/src/plugins/platforms/xcb/xcb-static/xcb-static.pro deleted file mode 100644 index 078b275381..0000000000 --- a/src/plugins/platforms/xcb/xcb-static/xcb-static.pro +++ /dev/null @@ -1,80 +0,0 @@ -# -# Statically compile in code for -# libxcb-fixes, libxcb-randr, libxcb-shm, libxcb-sync, libxcb-image, -# libxcb-keysyms, libxcb-icccm, libxcb-renderutil, libxcb-xkb, -# libxcb-xinerama, libxcb-xinput -# -CONFIG += static - -XCB_DIR = $$QT_SOURCE_TREE/src/3rdparty/xcb - -MODULE_INCLUDEPATH += $$XCB_DIR/include $$XCB_DIR/sysinclude -INCLUDEPATH += $$XCB_DIR/include/xcb - -QMAKE_USE += xcb/nolink - -# ignore compiler warnings in 3rdparty code -QMAKE_CFLAGS_STATIC_LIB+=-w - -# -# libxcb -# -LIBXCB_DIR = $$XCB_DIR/libxcb - -SOURCES += \ - $$LIBXCB_DIR/xfixes.c \ - $$LIBXCB_DIR/randr.c \ - $$LIBXCB_DIR/shm.c \ - $$LIBXCB_DIR/sync.c \ - $$LIBXCB_DIR/render.c \ - $$LIBXCB_DIR/shape.c \ - $$LIBXCB_DIR/xkb.c \ - $$LIBXCB_DIR/xinerama.c \ - $$LIBXCB_DIR/xinput.c - -# -# xcb-util -# -XCB_UTIL_DIR = $$XCB_DIR/xcb-util - - -SOURCES += \ - $$XCB_UTIL_DIR/xcb_aux.c \ - $$XCB_UTIL_DIR/atoms.c \ - $$XCB_UTIL_DIR/event.c - -# -# xcb-util-image -# -XCB_IMAGE_DIR = $$XCB_DIR/xcb-util-image - -SOURCES += $$XCB_IMAGE_DIR/xcb_image.c - -# -# xcb-util-keysyms -# -XCB_KEYSYMS_DIR = $$XCB_DIR/xcb-util-keysyms - -SOURCES += $$XCB_KEYSYMS_DIR/keysyms.c - -# -# xcb-util-renderutil -# - -XCB_RENDERUTIL_DIR = $$XCB_DIR/xcb-util-renderutil - -SOURCES += $$XCB_RENDERUTIL_DIR/util.c - -# -# xcb-util-wm -# -XCB_WM_DIR = $$XCB_DIR/xcb-util-wm - -SOURCES += \ - $$XCB_WM_DIR/icccm.c - -OTHER_FILES = $$XCB_DIR/README - -TR_EXCLUDE += $$XCB_DIR/* - -load(qt_helper_lib) diff --git a/src/plugins/platforms/xcb/xcb.pro b/src/plugins/platforms/xcb/xcb.pro index 0d27645a60..1c43c5ca04 100644 --- a/src/plugins/platforms/xcb/xcb.pro +++ b/src/plugins/platforms/xcb/xcb.pro @@ -2,8 +2,6 @@ TEMPLATE = subdirs CONFIG += ordered QT_FOR_CONFIG += gui-private -!qtConfig(system-xcb): SUBDIRS += xcb-static - SUBDIRS += xcb_qpa_lib.pro SUBDIRS += xcb-plugin.pro SUBDIRS += gl_integrations diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro index 34c671c8c7..a5d05faa9c 100644 --- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro +++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro @@ -35,6 +35,7 @@ SOURCES = \ qxcbeventdispatcher.cpp \ qxcbconnection_basic.cpp \ qxcbconnection_screens.cpp \ + qxcbconnection_xi2.cpp \ qxcbatom.cpp HEADERS = \ @@ -71,10 +72,6 @@ qtConfig(xcb-xlib) { QMAKE_USE += xcb_xlib } -qtConfig(xcb-xinput) { - SOURCES += qxcbconnection_xi2.cpp -} - qtConfig(xcb-sm) { QMAKE_USE += x11sm SOURCES += qxcbsessionmanager.cpp @@ -94,20 +91,19 @@ qtConfig(vulkan) { qxcbvulkanwindow.h } -!qtConfig(system-xcb) { - QMAKE_USE += xcb-static -} else { - qtConfig(xcb-xinput): QMAKE_USE += xcb_xinput - QMAKE_USE += \ - xcb_icccm xcb_image xcb_keysyms xcb_randr xcb_render xcb_renderutil \ - xcb_shape xcb_shm xcb_sync xcb_xfixes xcb_xinerama -} -QMAKE_USE += xcb +QMAKE_USE += \ + xcb xcb_icccm xcb_image xcb_keysyms xcb_randr xcb_render xcb_renderutil \ + xcb_shape xcb_shm xcb_sync xcb_xfixes xcb_xinerama xcb_xkb xkbcommon xkbcommon_x11 -QMAKE_USE += xkbcommon -qtConfig(xkb) { - QMAKE_USE += xkbcommon_x11 - qtConfig(system-xcb): QMAKE_USE += xcb_xkb +qtConfig(system-xcb-xinput) { + QMAKE_USE += xcb_xinput +} else { + # Use bundled xcb-xinput sources. + XCB_DIR = $$QT_SOURCE_TREE/src/3rdparty/xcb + INCLUDEPATH += $$XCB_DIR/include/ + SOURCES += $$XCB_DIR/libxcb/xinput.c + # Ignore compiler warnings in 3rdparty C code. + QMAKE_CFLAGS+=-w } qtConfig(dlopen): QMAKE_USE += libdl diff --git a/src/plugins/platformthemes/gtk3/main.cpp b/src/plugins/platformthemes/gtk3/main.cpp index fb1c425d8e..860fc3a26e 100644 --- a/src/plugins/platformthemes/gtk3/main.cpp +++ b/src/plugins/platformthemes/gtk3/main.cpp @@ -57,7 +57,7 @@ QPlatformTheme *QGtk3ThemePlugin::create(const QString &key, const QStringList & if (!key.compare(QLatin1String(QGtk3Theme::name), Qt::CaseInsensitive)) return new QGtk3Theme; - return 0; + return nullptr; } QT_END_NAMESPACE diff --git a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp index c64a02fa0c..65564b59a1 100644 --- a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp +++ b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp @@ -165,12 +165,12 @@ void QGtk3Dialog::onResponse(QGtk3Dialog *dialog, int response) void QGtk3Dialog::onParentWindowDestroyed() { // The QGtk3*DialogHelper classes own this object. Make sure the parent doesn't delete it. - setParent(0); + setParent(nullptr); } QGtk3ColorDialogHelper::QGtk3ColorDialogHelper() { - d.reset(new QGtk3Dialog(gtk_color_chooser_dialog_new("", 0))); + d.reset(new QGtk3Dialog(gtk_color_chooser_dialog_new("", nullptr))); connect(d.data(), SIGNAL(accept()), this, SLOT(onAccepted())); connect(d.data(), SIGNAL(reject()), this, SIGNAL(reject())); @@ -238,7 +238,7 @@ void QGtk3ColorDialogHelper::applyOptions() QGtk3FileDialogHelper::QGtk3FileDialogHelper() { - d.reset(new QGtk3Dialog(gtk_file_chooser_dialog_new("", 0, + d.reset(new QGtk3Dialog(gtk_file_chooser_dialog_new("", nullptr, GTK_FILE_CHOOSER_ACTION_OPEN, qUtf8Printable(QGtk3Theme::defaultStandardButtonText(QPlatformDialogHelper::Cancel)), GTK_RESPONSE_CANCEL, qUtf8Printable(QGtk3Theme::defaultStandardButtonText(QPlatformDialogHelper::Ok)), GTK_RESPONSE_OK, @@ -497,7 +497,7 @@ void QGtk3FileDialogHelper::setNameFilters(const QStringList &filters) QGtk3FontDialogHelper::QGtk3FontDialogHelper() { - d.reset(new QGtk3Dialog(gtk_font_chooser_dialog_new("", 0))); + d.reset(new QGtk3Dialog(gtk_font_chooser_dialog_new("", nullptr))); connect(d.data(), SIGNAL(accept()), this, SLOT(onAccepted())); connect(d.data(), SIGNAL(reject()), this, SIGNAL(reject())); diff --git a/src/plugins/platformthemes/gtk3/qgtk3menu.cpp b/src/plugins/platformthemes/gtk3/qgtk3menu.cpp index 4f0bd9d9a0..d9d117faeb 100644 --- a/src/plugins/platformthemes/gtk3/qgtk3menu.cpp +++ b/src/plugins/platformthemes/gtk3/qgtk3menu.cpp @@ -200,7 +200,7 @@ void QGtk3MenuItem::setMenu(QPlatformMenu *menu) { m_menu = qobject_cast<QGtk3Menu *>(menu); if (GTK_IS_MENU_ITEM(m_item)) - gtk_menu_item_set_submenu(GTK_MENU_ITEM(m_item), m_menu ? m_menu->handle() : NULL); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(m_item), m_menu ? m_menu->handle() : nullptr); } bool QGtk3MenuItem::isVisible() const @@ -436,7 +436,7 @@ void QGtk3Menu::showPopup(const QWindow *parentWindow, const QRect &targetRect, if (pw) m_targetPos = pw->mapToGlobal(m_targetPos); - gtk_menu_popup(GTK_MENU(m_menu), NULL, NULL, qt_gtk_menu_position_func, this, 0, gtk_get_current_event_time()); + gtk_menu_popup(GTK_MENU(m_menu), nullptr, nullptr, qt_gtk_menu_position_func, this, 0, gtk_get_current_event_time()); } void QGtk3Menu::dismiss() diff --git a/src/plugins/platformthemes/gtk3/qgtk3theme.cpp b/src/plugins/platformthemes/gtk3/qgtk3theme.cpp index 077955eb4e..93520344f8 100644 --- a/src/plugins/platformthemes/gtk3/qgtk3theme.cpp +++ b/src/plugins/platformthemes/gtk3/qgtk3theme.cpp @@ -86,9 +86,9 @@ QGtk3Theme::QGtk3Theme() { // gtk_init will reset the Xlib error handler, and that causes // Qt applications to quit on X errors. Therefore, we need to manually restore it. - int (*oldErrorHandler)(Display *, XErrorEvent *) = XSetErrorHandler(NULL); + int (*oldErrorHandler)(Display *, XErrorEvent *) = XSetErrorHandler(nullptr); - gtk_init(0, 0); + gtk_init(nullptr, nullptr); XSetErrorHandler(oldErrorHandler); @@ -99,7 +99,7 @@ QGtk3Theme::QGtk3Theme() g_type_ensure(PANGO_TYPE_FONT_FACE); /* Use our custom log handler. */ - g_log_set_handler("Gtk", G_LOG_LEVEL_MESSAGE, gtkMessageHandler, NULL); + g_log_set_handler("Gtk", G_LOG_LEVEL_MESSAGE, gtkMessageHandler, nullptr); } static inline QVariant gtkGetLongPressTime() @@ -173,7 +173,7 @@ QPlatformDialogHelper *QGtk3Theme::createPlatformDialogHelper(DialogType type) c case FontDialog: return new QGtk3FontDialogHelper; default: - return 0; + return nullptr; } } @@ -197,7 +197,7 @@ bool QGtk3Theme::useNativeFileDialog() * dialogs entirely since we can't avoid creation of a platform * dialog helper. */ - return gtk_check_version(3, 15, 5) == 0; + return gtk_check_version(3, 15, 5) == nullptr; } QT_END_NAMESPACE diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp index dcf52921aa..13c39436ba 100644 --- a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp +++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp @@ -225,7 +225,7 @@ void QXdgDesktopPortalFileDialog::openPortal() QRegularExpressionMatch match = regexp.match(filter); if (match.hasMatch()) { QString userVisibleName = match.captured(1); - QStringList filterStrings = match.captured(2).split(QLatin1Char(' '), QString::SkipEmptyParts); + QStringList filterStrings = match.captured(2).split(QLatin1Char(' '), Qt::SkipEmptyParts); FilterConditionList filterConditions; for (const QString &filterString : filterStrings) { diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.h b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.h index 5cfc4df0d0..d38b3ddda3 100644 --- a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.h +++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.h @@ -72,7 +72,7 @@ public: QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const override; QIcon fileIcon(const QFileInfo &fileInfo, - QPlatformTheme::IconOptions iconOptions = nullptr) const override; + QPlatformTheme::IconOptions iconOptions = { }) const override; QIconEngine *createIconEngine(const QString &iconName) const override; diff --git a/src/plugins/printsupport/cups/qcupsprintengine.cpp b/src/plugins/printsupport/cups/qcupsprintengine.cpp index c9683eb99d..43d5e119ad 100644 --- a/src/plugins/printsupport/cups/qcupsprintengine.cpp +++ b/src/plugins/printsupport/cups/qcupsprintengine.cpp @@ -100,10 +100,10 @@ void QCupsPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &v d->cupsOptions = value.toStringList(); break; case PPK_QPageSize: - d->setPageSize(value.value<QPageSize>()); + d->setPageSize(qvariant_cast<QPageSize>(value)); break; case PPK_QPageLayout: { - QPageLayout pageLayout = value.value<QPageLayout>(); + QPageLayout pageLayout = qvariant_cast<QPageLayout>(value); if (pageLayout.isValid() && (d->m_printDevice.isValidPageLayout(pageLayout, d->resolution) || d->m_printDevice.supportsCustomPageSizes() || d->m_printDevice.supportedPageSizes().isEmpty())) { diff --git a/src/plugins/sqldrivers/configure.json b/src/plugins/sqldrivers/configure.json index cd20eef1df..28ccbeadcd 100644 --- a/src/plugins/sqldrivers/configure.json +++ b/src/plugins/sqldrivers/configure.json @@ -72,7 +72,9 @@ { "type": "mysqlConfig", "query": "--libs_r", "cleanlibs": false }, { "type": "mysqlConfig", "query": "--libs", "cleanlibs": false }, { "libs": "-lmysqlclient_r", "condition": "!config.win32" }, + { "libs": "-llibmariadb", "condition": "config.win32" }, { "libs": "-llibmysql", "condition": "config.win32" }, + { "libs": "-lmariadb", "condition": "!config.win32" }, { "libs": "-lmysqlclient", "condition": "!config.win32" } ] }, diff --git a/src/plugins/sqldrivers/db2/qsql_db2.cpp b/src/plugins/sqldrivers/db2/qsql_db2.cpp index 1d7e985731..ddf54666e7 100644 --- a/src/plugins/sqldrivers/db2/qsql_db2.cpp +++ b/src/plugins/sqldrivers/db2/qsql_db2.cpp @@ -1270,7 +1270,7 @@ bool QDB2Driver::open(const QString& db, const QString& user, const QString& pas QString protocol; // Set connection attributes - const QStringList opts(connOpts.split(QLatin1Char(';'), QString::SkipEmptyParts)); + const QStringList opts(connOpts.split(QLatin1Char(';'), Qt::SkipEmptyParts)); for (int i = 0; i < opts.count(); ++i) { const QString tmp(opts.at(i)); int idx; diff --git a/src/plugins/sqldrivers/ibase/qsql_ibase.cpp b/src/plugins/sqldrivers/ibase/qsql_ibase.cpp index 3368c74373..0fa21f504c 100644 --- a/src/plugins/sqldrivers/ibase/qsql_ibase.cpp +++ b/src/plugins/sqldrivers/ibase/qsql_ibase.cpp @@ -730,7 +730,7 @@ static char* createArrayBuffer(char *buffer, const QList<QVariant> &list, if (curDim != dim) { for(i = 0; i < list.size(); ++i) { - if (list.at(i).type() != QVariant::List) { // dimensions mismatch + if (list.at(i).userType() != QVariant::List) { // dimensions mismatch error = QLatin1String("Array dimensons mismatch. Fieldname: %1"); return 0; } @@ -1162,7 +1162,7 @@ bool QIBaseResult::gotoNext(QSqlCachedResult::ValueCache& row, int rowIdx) // null value QVariant v; v.convert(qIBaseTypeName2(d->sqlda->sqlvar[i].sqltype, d->sqlda->sqlvar[i].sqlscale < 0)); - if(v.type() == QVariant::Double) { + if (v.userType() == QVariant::Double) { switch(numericalPrecisionPolicy()) { case QSql::LowPrecisionInt32: v.convert(QVariant::Int); @@ -1477,7 +1477,7 @@ bool QIBaseDriver::open(const QString & db, if (isOpen()) close(); - const QStringList opts(connOpts.split(QLatin1Char(';'), QString::SkipEmptyParts)); + const QStringList opts(connOpts.split(QLatin1Char(';'), Qt::SkipEmptyParts)); QString encString; QByteArray role; @@ -1914,7 +1914,12 @@ void QIBaseDriver::qHandleEventNotification(void *updatedResultBuffer) if (counts[0]) { if (eBuffer->subscriptionState == QIBaseEventBuffer::Subscribed) { +#if QT_DEPRECATED_SINCE(5, 15) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED emit notification(i.key()); +QT_WARNING_POP +#endif emit notification(i.key(), QSqlDriver::UnknownSource, QVariant()); } else if (eBuffer->subscriptionState == QIBaseEventBuffer::Starting) diff --git a/src/plugins/sqldrivers/mysql/main.cpp b/src/plugins/sqldrivers/mysql/main.cpp index d8d70483ef..4c6753097f 100644 --- a/src/plugins/sqldrivers/mysql/main.cpp +++ b/src/plugins/sqldrivers/mysql/main.cpp @@ -61,7 +61,9 @@ QMYSQLDriverPlugin::QMYSQLDriverPlugin() QSqlDriver* QMYSQLDriverPlugin::create(const QString &name) { - if (name == QLatin1String("QMYSQL") || name == QLatin1String("QMYSQL3")) { + if (name == QLatin1String("QMYSQL") || + name == QLatin1String("QMYSQL3") || + name == QLatin1String("QMARIADB")) { QMYSQLDriver* driver = new QMYSQLDriver(); return driver; } diff --git a/src/plugins/sqldrivers/mysql/mysql.json b/src/plugins/sqldrivers/mysql/mysql.json index 0caaadb7ce..89f5e65fb9 100644 --- a/src/plugins/sqldrivers/mysql/mysql.json +++ b/src/plugins/sqldrivers/mysql/mysql.json @@ -1,3 +1,3 @@ { - "Keys": [ "QMYSQL3", "QMYSQL" ] + "Keys": [ "QMYSQL3", "QMYSQL", "QMARIADB" ] } diff --git a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp index febbe58506..a641935dc5 100644 --- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp +++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp @@ -65,16 +65,7 @@ Q_DECLARE_METATYPE(MYSQL_RES*) Q_DECLARE_METATYPE(MYSQL*) - -#if MYSQL_VERSION_ID >= 40108 Q_DECLARE_METATYPE(MYSQL_STMT*) -#endif - -#if MYSQL_VERSION_ID >= 40100 -# define Q_CLIENT_MULTI_STATEMENTS CLIENT_MULTI_STATEMENTS -#else -# define Q_CLIENT_MULTI_STATEMENTS 0 -#endif // MySQL above version 8 removed my_bool typedef while MariaDB kept it, // by redefining it we can regain source compatibility. @@ -87,17 +78,14 @@ class QMYSQLDriverPrivate : public QSqlDriverPrivate Q_DECLARE_PUBLIC(QMYSQLDriver) public: - QMYSQLDriverPrivate() : QSqlDriverPrivate(), mysql(0), + QMYSQLDriverPrivate() : QSqlDriverPrivate(QSqlDriver::MySqlServer) #if QT_CONFIG(textcodec) - tc(QTextCodec::codecForLocale()), -#else - tc(0), + , tc(QTextCodec::codecForLocale()) #endif - preparedQuerysEnabled(false) { dbmsType = QSqlDriver::MySqlServer; } - MYSQL *mysql; - QTextCodec *tc; - - bool preparedQuerysEnabled; + {} + MYSQL *mysql = nullptr; + QTextCodec *tc = nullptr; + bool preparedQuerysEnabled = false; }; static inline QString toUnicode(QTextCodec *tc, const char *str) @@ -199,10 +187,8 @@ protected: bool nextResult() override; void detachFromResultSet() override; -#if MYSQL_VERSION_ID >= 40108 bool prepare(const QString &stmt) override; bool exec() override; -#endif }; class QMYSQLResultPrivate: public QSqlResultPrivate @@ -212,60 +198,42 @@ class QMYSQLResultPrivate: public QSqlResultPrivate public: Q_DECLARE_SQLDRIVER_PRIVATE(QMYSQLDriver) - QMYSQLResultPrivate(QMYSQLResult *q, const QMYSQLDriver *drv) - : QSqlResultPrivate(q, drv), - result(0), - rowsAffected(0), - hasBlobs(false) -#if MYSQL_VERSION_ID >= 40108 - , stmt(0), meta(0), inBinds(0), outBinds(0) -#endif - , preparedQuery(false) - { } - - MYSQL_RES *result; - MYSQL_ROW row; - - int rowsAffected; + using QSqlResultPrivate::QSqlResultPrivate; bool bindInValues(); void bindBlobs(); - bool hasBlobs; + MYSQL_RES *result = nullptr; + MYSQL_ROW row; + struct QMyField { - QMyField() - : outField(0), nullIndicator(false), bufLength(0ul), - myField(0), type(QVariant::Invalid) - {} - char *outField; - my_bool nullIndicator; - ulong bufLength; - MYSQL_FIELD *myField; - QVariant::Type type; + char *outField = nullptr; + MYSQL_FIELD *myField = nullptr; + QMetaType::Type type = QMetaType::UnknownType; + my_bool nullIndicator = false; + ulong bufLength = 0ul; }; QVector<QMyField> fields; -#if MYSQL_VERSION_ID >= 40108 - MYSQL_STMT* stmt; - MYSQL_RES* meta; + MYSQL_STMT *stmt = nullptr; + MYSQL_RES *meta = nullptr; - MYSQL_BIND *inBinds; - MYSQL_BIND *outBinds; -#endif + MYSQL_BIND *inBinds = nullptr; + MYSQL_BIND *outBinds = nullptr; - bool preparedQuery; + int rowsAffected = 0; + bool hasBlobs = false; + bool preparedQuery = false; }; #if QT_CONFIG(textcodec) static QTextCodec* codec(MYSQL* mysql) { -#if MYSQL_VERSION_ID >= 32321 QTextCodec* heuristicCodec = QTextCodec::codecForName(mysql_character_set_name(mysql)); if (heuristicCodec) return heuristicCodec; -#endif return QTextCodec::codecForLocale(); } #endif // textcodec @@ -280,25 +248,25 @@ static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type, } -static QVariant::Type qDecodeMYSQLType(int mysqltype, uint flags) +static QMetaType::Type qDecodeMYSQLType(int mysqltype, uint flags) { - QVariant::Type type; + QMetaType::Type type; switch (mysqltype) { case FIELD_TYPE_TINY : - type = static_cast<QVariant::Type>((flags & UNSIGNED_FLAG) ? QMetaType::UChar : QMetaType::Char); + type = (flags & UNSIGNED_FLAG) ? QMetaType::UChar : QMetaType::Char; break; case FIELD_TYPE_SHORT : - type = static_cast<QVariant::Type>((flags & UNSIGNED_FLAG) ? QMetaType::UShort : QMetaType::Short); + type = (flags & UNSIGNED_FLAG) ? QMetaType::UShort : QMetaType::Short; break; case FIELD_TYPE_LONG : case FIELD_TYPE_INT24 : - type = (flags & UNSIGNED_FLAG) ? QVariant::UInt : QVariant::Int; + type = (flags & UNSIGNED_FLAG) ? QMetaType::UInt : QMetaType::Int; break; case FIELD_TYPE_YEAR : - type = QVariant::Int; + type = QMetaType::Int; break; case FIELD_TYPE_LONGLONG : - type = (flags & UNSIGNED_FLAG) ? QVariant::ULongLong : QVariant::LongLong; + type = (flags & UNSIGNED_FLAG) ? QMetaType::ULongLong : QMetaType::LongLong; break; case FIELD_TYPE_FLOAT : case FIELD_TYPE_DOUBLE : @@ -306,19 +274,19 @@ static QVariant::Type qDecodeMYSQLType(int mysqltype, uint flags) #if defined(FIELD_TYPE_NEWDECIMAL) case FIELD_TYPE_NEWDECIMAL: #endif - type = QVariant::Double; + type = QMetaType::Double; break; case FIELD_TYPE_DATE : - type = QVariant::Date; + type = QMetaType::QDate; break; case FIELD_TYPE_TIME : // A time field can be within the range '-838:59:59' to '838:59:59' so // use QString instead of QTime since QTime is limited to 24 hour clock - type = QVariant::String; + type = QMetaType::QString; break; case FIELD_TYPE_DATETIME : case FIELD_TYPE_TIMESTAMP : - type = QVariant::DateTime; + type = QMetaType::QDateTime; break; case FIELD_TYPE_STRING : case FIELD_TYPE_VAR_STRING : @@ -326,12 +294,13 @@ static QVariant::Type qDecodeMYSQLType(int mysqltype, uint flags) case FIELD_TYPE_TINY_BLOB : case FIELD_TYPE_MEDIUM_BLOB : case FIELD_TYPE_LONG_BLOB : - type = (flags & BINARY_FLAG) ? QVariant::ByteArray : QVariant::String; + case FIELD_TYPE_GEOMETRY : + type = (flags & BINARY_FLAG) ? QMetaType::QByteArray : QMetaType::QString; break; default: case FIELD_TYPE_ENUM : case FIELD_TYPE_SET : - type = QVariant::String; + type = QMetaType::QString; break; } return type; @@ -340,7 +309,7 @@ static QVariant::Type qDecodeMYSQLType(int mysqltype, uint flags) static QSqlField qToField(MYSQL_FIELD *field, QTextCodec *tc) { QSqlField f(toUnicode(tc, field->name), - qDecodeMYSQLType(int(field->type), field->flags), + QVariant::Type(qDecodeMYSQLType(int(field->type), field->flags)), toUnicode(tc, field->table)); f.setRequired(IS_NOT_NULL(field->flags)); f.setLength(field->length); @@ -350,8 +319,6 @@ static QSqlField qToField(MYSQL_FIELD *field, QTextCodec *tc) return f; } -#if MYSQL_VERSION_ID >= 40108 - static QSqlError qMakeStmtError(const QString& err, QSqlError::ErrorType type, MYSQL_STMT* stmt) { @@ -445,7 +412,6 @@ bool QMYSQLResultPrivate::bindInValues() } return true; } -#endif QMYSQLResult::QMYSQLResult(const QMYSQLDriver* db) : QSqlResult(*new QMYSQLResultPrivate(this, db)) @@ -460,11 +426,9 @@ QMYSQLResult::~QMYSQLResult() QVariant QMYSQLResult::handle() const { Q_D(const QMYSQLResult); -#if MYSQL_VERSION_ID >= 40108 if(d->preparedQuery) return d->meta ? QVariant::fromValue(d->meta) : QVariant::fromValue(d->stmt); else -#endif return QVariant::fromValue(d->result); } @@ -476,15 +440,12 @@ void QMYSQLResult::cleanup() // must iterate trough leftover result sets from multi-selects or stored procedures // if this isn't done subsequent queries will fail with "Commands out of sync" -#if MYSQL_VERSION_ID >= 40100 while (driver() && d->drv_d_func()->mysql && mysql_next_result(d->drv_d_func()->mysql) == 0) { MYSQL_RES *res = mysql_store_result(d->drv_d_func()->mysql); if (res) mysql_free_result(res); } -#endif -#if MYSQL_VERSION_ID >= 40108 if (d->stmt) { if (mysql_stmt_close(d->stmt)) qWarning("QMYSQLResult::cleanup: unable to free statement handle"); @@ -509,7 +470,6 @@ void QMYSQLResult::cleanup() delete[] d->inBinds; d->inBinds = 0; } -#endif d->hasBlobs = false; d->fields.clear(); @@ -536,7 +496,6 @@ bool QMYSQLResult::fetch(int i) if (at() == i) return true; if (d->preparedQuery) { -#if MYSQL_VERSION_ID >= 40108 mysql_stmt_data_seek(d->stmt, i); int nRC = mysql_stmt_fetch(d->stmt); @@ -550,9 +509,6 @@ bool QMYSQLResult::fetch(int i) "Unable to fetch data"), QSqlError::StatementError, d->stmt)); return false; } -#else - return false; -#endif } else { mysql_data_seek(d->result, i); d->row = mysql_fetch_row(d->result); @@ -570,7 +526,6 @@ bool QMYSQLResult::fetchNext() if (!driver()) return false; if (d->preparedQuery) { -#if MYSQL_VERSION_ID >= 40108 int nRC = mysql_stmt_fetch(d->stmt); if (nRC) { #ifdef MYSQL_DATA_TRUNCATED @@ -582,9 +537,6 @@ bool QMYSQLResult::fetchNext() "Unable to fetch data"), QSqlError::StatementError, d->stmt)); return false; } -#else - return false; -#endif } else { d->row = mysql_fetch_row(d->result); if (!d->row) @@ -607,11 +559,7 @@ bool QMYSQLResult::fetchLast() my_ulonglong numRows; if (d->preparedQuery) { -#if MYSQL_VERSION_ID >= 40108 numRows = mysql_stmt_num_rows(d->stmt); -#else - numRows = 0; -#endif } else { numRows = mysql_num_rows(d->result); } @@ -648,7 +596,7 @@ QVariant QMYSQLResult::data(int field) QString val; if (d->preparedQuery) { if (f.nullIndicator) - return QVariant(f.type); + return QVariant(QVariant::Type(f.type)); if (qIsInteger(f.type)) { QVariant variant(f.type, f.outField); @@ -660,34 +608,34 @@ QVariant QMYSQLResult::data(int field) return variant; } - if (f.type != QVariant::ByteArray) + if (f.type != QMetaType::QByteArray) val = toUnicode(d->drv_d_func()->tc, f.outField, f.bufLength); } else { if (d->row[field] == NULL) { // NULL value - return QVariant(f.type); + return QVariant(QVariant::Type(f.type)); } fieldLength = mysql_fetch_lengths(d->result)[field]; - if (f.type != QVariant::ByteArray) + if (f.type != QMetaType::QByteArray) val = toUnicode(d->drv_d_func()->tc, d->row[field], fieldLength); } switch (static_cast<int>(f.type)) { - case QVariant::LongLong: + case QMetaType::LongLong: return QVariant(val.toLongLong()); - case QVariant::ULongLong: + case QMetaType::ULongLong: return QVariant(val.toULongLong()); case QMetaType::Char: case QMetaType::Short: - case QVariant::Int: + case QMetaType::Int: return QVariant(val.toInt()); case QMetaType::UChar: case QMetaType::UShort: - case QVariant::UInt: + case QMetaType::UInt: return QVariant(val.toUInt()); - case QVariant::Double: { + case QMetaType::Double: { QVariant v; bool ok=false; double dbl = val.toDouble(&ok); @@ -711,13 +659,13 @@ QVariant QMYSQLResult::data(int field) return v; return QVariant(); } - case QVariant::Date: + case QMetaType::QDate: return qDateFromString(val); - case QVariant::Time: + case QMetaType::QTime: return qTimeFromString(val); - case QVariant::DateTime: + case QMetaType::QDateTime: return qDateTimeFromString(val); - case QVariant::ByteArray: { + case QMetaType::QByteArray: { QByteArray ba; if (d->preparedQuery) { @@ -727,7 +675,7 @@ QVariant QMYSQLResult::data(int field) } return QVariant(ba); } - case QVariant::String: + case QMetaType::QString: default: return QVariant(val); } @@ -788,11 +736,7 @@ int QMYSQLResult::size() Q_D(const QMYSQLResult); if (driver() && isSelect()) if (d->preparedQuery) -#if MYSQL_VERSION_ID >= 40108 return mysql_stmt_num_rows(d->stmt); -#else - return -1; -#endif else return int(mysql_num_rows(d->result)); else @@ -821,11 +765,9 @@ QVariant QMYSQLResult::lastInsertId() const return QVariant(); if (d->preparedQuery) { -#if MYSQL_VERSION_ID >= 40108 quint64 id = mysql_stmt_insert_id(d->stmt); if (id) return QVariant(id); -#endif } else { quint64 id = mysql_insert_id(d->drv_d_func()->mysql); if (id) @@ -842,11 +784,7 @@ QSqlRecord QMYSQLResult::record() const if (!isActive() || !isSelect() || !driver()) return info; -#if MYSQL_VERSION_ID >= 40108 res = d->preparedQuery ? d->meta : d->result; -#else - res = d->result; -#endif if (!mysql_errno(d->drv_d_func()->mysql)) { mysql_field_seek(res, 0); @@ -865,7 +803,7 @@ bool QMYSQLResult::nextResult() Q_D(QMYSQLResult); if (!driver()) return false; -#if MYSQL_VERSION_ID >= 40100 + setAt(-1); setActive(false); @@ -908,9 +846,6 @@ bool QMYSQLResult::nextResult() setActive(true); return true; -#else - return false; -#endif } void QMYSQLResult::virtual_hook(int id, void *data) @@ -918,24 +853,21 @@ void QMYSQLResult::virtual_hook(int id, void *data) QSqlResult::virtual_hook(id, data); } - -#if MYSQL_VERSION_ID >= 40108 - -static MYSQL_TIME *toMySqlDate(QDate date, QTime time, QVariant::Type type) +static MYSQL_TIME *toMySqlDate(QDate date, QTime time, int type) { - Q_ASSERT(type == QVariant::Time || type == QVariant::Date - || type == QVariant::DateTime); + Q_ASSERT(type == QMetaType::QTime || type == QMetaType::QDate + || type == QMetaType::QDateTime); MYSQL_TIME *myTime = new MYSQL_TIME; memset(myTime, 0, sizeof(MYSQL_TIME)); - if (type == QVariant::Time || type == QVariant::DateTime) { + if (type == QMetaType::QTime || type == QMetaType::QDateTime) { myTime->hour = time.hour(); myTime->minute = time.minute(); myTime->second = time.second(); myTime->second_part = time.msec() * 1000; } - if (type == QVariant::Date || type == QVariant::DateTime) { + if (type == QMetaType::QDate || type == QMetaType::QDateTime) { myTime->year = date.year(); myTime->month = date.month(); myTime->day = date.day(); @@ -949,7 +881,7 @@ bool QMYSQLResult::prepare(const QString& query) Q_D(QMYSQLResult); if (!driver()) return false; -#if MYSQL_VERSION_ID >= 40108 + cleanup(); if (!d->drv_d_func()->preparedQuerysEnabled) return QSqlResult::prepare(query); @@ -983,9 +915,6 @@ bool QMYSQLResult::prepare(const QString& query) setSelect(d->bindInValues()); d->preparedQuery = true; return true; -#else - return false; -#endif } bool QMYSQLResult::exec() @@ -1028,30 +957,30 @@ bool QMYSQLResult::exec() currBind->length = 0; currBind->is_unsigned = 0; - switch (val.type()) { - case QVariant::ByteArray: + switch (val.userType()) { + case QMetaType::QByteArray: currBind->buffer_type = MYSQL_TYPE_BLOB; currBind->buffer = const_cast<char *>(val.toByteArray().constData()); currBind->buffer_length = val.toByteArray().size(); break; - case QVariant::Time: - case QVariant::Date: - case QVariant::DateTime: { - MYSQL_TIME *myTime = toMySqlDate(val.toDate(), val.toTime(), val.type()); + case QMetaType::QTime: + case QMetaType::QDate: + case QMetaType::QDateTime: { + MYSQL_TIME *myTime = toMySqlDate(val.toDate(), val.toTime(), val.userType()); timeVector.append(myTime); currBind->buffer = myTime; - switch(val.type()) { - case QVariant::Time: + switch (val.userType()) { + case QMetaType::QTime: currBind->buffer_type = MYSQL_TYPE_TIME; myTime->time_type = MYSQL_TIMESTAMP_TIME; break; - case QVariant::Date: + case QMetaType::QDate: currBind->buffer_type = MYSQL_TYPE_DATE; myTime->time_type = MYSQL_TIMESTAMP_DATE; break; - case QVariant::DateTime: + case QMetaType::QDateTime: currBind->buffer_type = MYSQL_TYPE_DATETIME; myTime->time_type = MYSQL_TIMESTAMP_DATETIME; break; @@ -1061,32 +990,32 @@ bool QMYSQLResult::exec() currBind->buffer_length = sizeof(MYSQL_TIME); currBind->length = 0; break; } - case QVariant::UInt: - case QVariant::Int: + case QMetaType::UInt: + case QMetaType::Int: currBind->buffer_type = MYSQL_TYPE_LONG; currBind->buffer = data; currBind->buffer_length = sizeof(int); - currBind->is_unsigned = (val.type() != QVariant::Int); + currBind->is_unsigned = (val.userType() != QMetaType::Int); break; - case QVariant::Bool: + case QMetaType::Bool: currBind->buffer_type = MYSQL_TYPE_TINY; currBind->buffer = data; currBind->buffer_length = sizeof(bool); currBind->is_unsigned = false; break; - case QVariant::Double: + case QMetaType::Double: currBind->buffer_type = MYSQL_TYPE_DOUBLE; currBind->buffer = data; currBind->buffer_length = sizeof(double); break; - case QVariant::LongLong: - case QVariant::ULongLong: + case QMetaType::LongLong: + case QMetaType::ULongLong: currBind->buffer_type = MYSQL_TYPE_LONGLONG; currBind->buffer = data; currBind->buffer_length = sizeof(qint64); - currBind->is_unsigned = (val.type() == QVariant::ULongLong); + currBind->is_unsigned = (val.userType() == QMetaType::ULongLong); break; - case QVariant::String: + case QMetaType::QString: default: { QByteArray ba = fromUnicode(d->drv_d_func()->tc, val.toString()); stringVector.append(ba); @@ -1155,7 +1084,7 @@ bool QMYSQLResult::exec() setActive(true); return true; } -#endif + ///////////////////////////////////////////////////////// static int qMySqlConnectionCount = 0; @@ -1164,18 +1093,16 @@ static bool qMySqlInitHandledByUser = false; static void qLibraryInit() { #ifndef Q_NO_MYSQL_EMBEDDED -# if MYSQL_VERSION_ID >= 40000 if (qMySqlInitHandledByUser || qMySqlConnectionCount > 1) return; -# if (MYSQL_VERSION_ID >= 40110 && MYSQL_VERSION_ID < 50000) || MYSQL_VERSION_ID >= 50003 +# if MYSQL_VERSION_ID >= 50003 if (mysql_library_init(0, 0, 0)) { # else if (mysql_server_init(0, 0, 0)) { # endif qWarning("QMYSQLDriver::qServerInit: unable to start server."); } -# endif // MYSQL_VERSION_ID #endif // Q_NO_MYSQL_EMBEDDED #if defined(MARIADB_BASE_VERSION) || defined(MARIADB_VERSION_ID) @@ -1187,12 +1114,10 @@ static void qLibraryEnd() { #if !defined(MARIADB_BASE_VERSION) && !defined(MARIADB_VERSION_ID) # if !defined(Q_NO_MYSQL_EMBEDDED) -# if MYSQL_VERSION_ID > 40000 -# if (MYSQL_VERSION_ID >= 40110 && MYSQL_VERSION_ID < 50000) || MYSQL_VERSION_ID >= 50003 - mysql_library_end(); -# else - mysql_server_end(); -# endif +# if MYSQL_VERSION_ID >= 50003 + mysql_library_end(); +# else + mysql_server_end(); # endif # endif #endif @@ -1271,17 +1196,9 @@ bool QMYSQLDriver::hasFeature(DriverFeature f) const return true; case PreparedQueries: case PositionalPlaceholders: -#if MYSQL_VERSION_ID >= 40108 return d->preparedQuerysEnabled; -#else - return false; -#endif case MultipleResultSets: -#if MYSQL_VERSION_ID >= 40100 return true; -#else - return false; -#endif } return false; } @@ -1322,20 +1239,18 @@ bool QMYSQLDriver::open(const QString& db, we have to enable CLIEN_MULTI_STATEMENTS here, otherwise _any_ stored procedure call will fail. */ - unsigned int optionFlags = Q_CLIENT_MULTI_STATEMENTS; - const QStringList opts(connOpts.split(QLatin1Char(';'), QString::SkipEmptyParts)); + unsigned int optionFlags = CLIENT_MULTI_STATEMENTS; + const QStringList opts(connOpts.split(QLatin1Char(';'), Qt::SkipEmptyParts)); QString unixSocket; QString sslCert; QString sslCA; QString sslKey; QString sslCAPath; QString sslCipher; -#if MYSQL_VERSION_ID >= 50000 my_bool reconnect=false; uint connectTimeout = 0; uint readTimeout = 0; uint writeTimeout = 0; -#endif // extract the real options from the string for (int i = 0; i < opts.count(); ++i) { @@ -1346,18 +1261,15 @@ bool QMYSQLDriver::open(const QString& db, QString opt = tmp.left(idx).simplified(); if (opt == QLatin1String("UNIX_SOCKET")) unixSocket = val; -#if MYSQL_VERSION_ID >= 50000 else if (opt == QLatin1String("MYSQL_OPT_RECONNECT")) { if (val == QLatin1String("TRUE") || val == QLatin1String("1") || val.isEmpty()) reconnect = true; - } else if (opt == QLatin1String("MYSQL_OPT_CONNECT_TIMEOUT")) { + } else if (opt == QLatin1String("MYSQL_OPT_CONNECT_TIMEOUT")) connectTimeout = val.toInt(); - } else if (opt == QLatin1String("MYSQL_OPT_READ_TIMEOUT")) { + else if (opt == QLatin1String("MYSQL_OPT_READ_TIMEOUT")) readTimeout = val.toInt(); - } else if (opt == QLatin1String("MYSQL_OPT_WRITE_TIMEOUT")) { + else if (opt == QLatin1String("MYSQL_OPT_WRITE_TIMEOUT")) writeTimeout = val.toInt(); - } -#endif else if (opt == QLatin1String("SSL_KEY")) sslKey = val; else if (opt == QLatin1String("SSL_CERT")) @@ -1442,7 +1354,7 @@ bool QMYSQLDriver::open(const QString& db, return false; } -#if (MYSQL_VERSION_ID >= 40113 && MYSQL_VERSION_ID < 50000) || MYSQL_VERSION_ID >= 50007 +#if MYSQL_VERSION_ID >= 50007 if (mysql_get_client_version() >= 50503 && mysql_get_server_version(d->mysql) >= 50503) { // force the communication to be utf8mb4 (only utf8mb4 supports 4-byte characters) mysql_set_character_set(d->mysql, "utf8mb4"); @@ -1457,20 +1369,15 @@ bool QMYSQLDriver::open(const QString& db, d->tc = codec(d->mysql); #endif } -#endif +#endif // MYSQL_VERSION_ID >= 50007 -#if MYSQL_VERSION_ID >= 40108 d->preparedQuerysEnabled = mysql_get_client_version() >= 40108 && mysql_get_server_version(d->mysql) >= 40100; -#else - d->preparedQuerysEnabled = false; -#endif #if QT_CONFIG(thread) mysql_thread_init(); #endif - setOpen(true); setOpenError(false); return true; @@ -1499,46 +1406,21 @@ QStringList QMYSQLDriver::tables(QSql::TableType type) const { Q_D(const QMYSQLDriver); QStringList tl; -#if MYSQL_VERSION_ID >= 40100 - if( mysql_get_server_version(d->mysql) < 50000) - { -#endif - if (!isOpen()) - return tl; - if (!(type & QSql::Tables)) - return tl; - - MYSQL_RES* tableRes = mysql_list_tables(d->mysql, NULL); - MYSQL_ROW row; - int i = 0; - while (tableRes) { - mysql_data_seek(tableRes, i); - row = mysql_fetch_row(tableRes); - if (!row) - break; - tl.append(toUnicode(d->tc, row[0])); - i++; - } - mysql_free_result(tableRes); -#if MYSQL_VERSION_ID >= 40100 - } else { - QSqlQuery q(createResult()); - if(type & QSql::Tables) { - QString sql = QLatin1String("select table_name from information_schema.tables where table_schema = '") + QLatin1String(d->mysql->db) + QLatin1String("' and table_type = 'BASE TABLE'"); - q.exec(sql); + QSqlQuery q(createResult()); + if (type & QSql::Tables) { + QString sql = QLatin1String("select table_name from information_schema.tables where table_schema = '") + QLatin1String(d->mysql->db) + QLatin1String("' and table_type = 'BASE TABLE'"); + q.exec(sql); - while(q.next()) - tl.append(q.value(0).toString()); - } - if(type & QSql::Views) { - QString sql = QLatin1String("select table_name from information_schema.tables where table_schema = '") + QLatin1String(d->mysql->db) + QLatin1String("' and table_type = 'VIEW'"); - q.exec(sql); + while (q.next()) + tl.append(q.value(0).toString()); + } + if (type & QSql::Views) { + QString sql = QLatin1String("select table_name from information_schema.tables where table_schema = '") + QLatin1String(d->mysql->db) + QLatin1String("' and table_type = 'VIEW'"); + q.exec(sql); - while(q.next()) - tl.append(q.value(0).toString()); - } + while (q.next()) + tl.append(q.value(0).toString()); } -#endif return tl; } @@ -1652,16 +1534,16 @@ QString QMYSQLDriver::formatValue(const QSqlField &field, bool trimStrings) cons if (field.isNull()) { r = QStringLiteral("NULL"); } else { - switch(field.type()) { - case QVariant::Double: + switch (+field.type()) { + case QMetaType::Double: r = QString::number(field.value().toDouble(), 'g', field.precision()); break; - case QVariant::String: + case QMetaType::QString: // Escape '\' characters r = QSqlDriver::formatValue(field, trimStrings); r.replace(QLatin1String("\\"), QLatin1String("\\\\")); break; - case QVariant::ByteArray: + case QMetaType::QByteArray: if (isOpen()) { const QByteArray ba = field.value().toByteArray(); // buffer has to be at least length*2+1 bytes diff --git a/src/plugins/sqldrivers/mysql/qsql_mysql_p.h b/src/plugins/sqldrivers/mysql/qsql_mysql_p.h index 48b04fb1f5..9ccc8f4e4f 100644 --- a/src/plugins/sqldrivers/mysql/qsql_mysql_p.h +++ b/src/plugins/sqldrivers/mysql/qsql_mysql_p.h @@ -75,8 +75,8 @@ class Q_EXPORT_SQLDRIVER_MYSQL QMYSQLDriver : public QSqlDriver Q_DECLARE_PRIVATE(QMYSQLDriver) Q_OBJECT public: - explicit QMYSQLDriver(QObject *parent=0); - explicit QMYSQLDriver(MYSQL *con, QObject * parent=0); + explicit QMYSQLDriver(QObject *parent=nullptr); + explicit QMYSQLDriver(MYSQL *con, QObject * parent=nullptr); ~QMYSQLDriver(); bool hasFeature(DriverFeature f) const override; bool open(const QString & db, diff --git a/src/plugins/sqldrivers/oci/qsql_oci.cpp b/src/plugins/sqldrivers/oci/qsql_oci.cpp index aee8e92b36..8da9837a59 100644 --- a/src/plugins/sqldrivers/oci/qsql_oci.cpp +++ b/src/plugins/sqldrivers/oci/qsql_oci.cpp @@ -2230,7 +2230,7 @@ bool QOCIDriver::hasFeature(DriverFeature f) const static void qParseOpts(const QString &options, QOCIDriverPrivate *d) { - const QStringList opts(options.split(QLatin1Char(';'), QString::SkipEmptyParts)); + const QStringList opts(options.split(QLatin1Char(';'), Qt::SkipEmptyParts)); for (int i = 0; i < opts.count(); ++i) { const QString tmp(opts.at(i)); int idx; diff --git a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp index 7709b13cd1..88f1c74028 100644 --- a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp +++ b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp @@ -118,23 +118,19 @@ class QODBCDriverPrivate : public QSqlDriverPrivate Q_DECLARE_PUBLIC(QODBCDriver) public: - enum DefaultCase{Lower, Mixed, Upper, Sensitive}; - QODBCDriverPrivate() - : QSqlDriverPrivate(), hEnv(0), hDbc(0), unicode(false), useSchema(false), disconnectCount(0), datetime_precision(19), - isFreeTDSDriver(false), hasSQLFetchScroll(true), hasMultiResultSets(false), isQuoteInitialized(false), quote(QLatin1Char('"')) - { - } + enum DefaultCase {Lower, Mixed, Upper, Sensitive}; + using QSqlDriverPrivate::QSqlDriverPrivate; - SQLHANDLE hEnv; - SQLHANDLE hDbc; + SQLHANDLE hEnv = nullptr; + SQLHANDLE hDbc = nullptr; - bool unicode; - bool useSchema; - int disconnectCount; - int datetime_precision; - bool isFreeTDSDriver; - bool hasSQLFetchScroll; - bool hasMultiResultSets; + int disconnectCount = 0; + int datetimePrecision = 19; + bool unicode = false; + bool useSchema = false; + bool isFreeTDSDriver = false; + bool hasSQLFetchScroll = true; + bool hasMultiResultSets = false; bool checkDriver() const; void checkUnicode(); @@ -150,8 +146,8 @@ public: QString adjustCase(const QString&) const; QChar quoteChar(); private: - bool isQuoteInitialized; - QChar quote; + bool isQuoteInitialized = false; + QChar quote = QLatin1Char('"'); }; class QODBCResultPrivate; @@ -194,10 +190,7 @@ class QODBCResultPrivate: public QSqlResultPrivate public: Q_DECLARE_SQLDRIVER_PRIVATE(QODBCDriver) QODBCResultPrivate(QODBCResult *q, const QODBCDriver *db) - : QSqlResultPrivate(q, db), - hStmt(0), - useSchema(false), - hasSQLFetchScroll(true) + : QSqlResultPrivate(q, db) { unicode = drv_d_func()->unicode; useSchema = drv_d_func()->useSchema; @@ -210,16 +203,15 @@ public: SQLHANDLE dpEnv() const { return drv_d_func() ? drv_d_func()->hEnv : 0;} SQLHANDLE dpDbc() const { return drv_d_func() ? drv_d_func()->hDbc : 0;} - SQLHANDLE hStmt; - - bool unicode; - bool useSchema; + SQLHANDLE hStmt = nullptr; QSqlRecord rInf; QVector<QVariant> fieldCache; - int fieldCacheIdx; - int disconnectCount; - bool hasSQLFetchScroll; + int fieldCacheIdx = 0; + int disconnectCount = 0; + bool hasSQLFetchScroll = true; + bool unicode = false; + bool useSchema = false; bool isStmtHandleValid() const; void updateStmtHandleState(); @@ -775,7 +767,7 @@ QChar QODBCDriverPrivate::quoteChar() bool QODBCDriverPrivate::setConnectionOptions(const QString& connOpts) { // Set any connection attributes - const QStringList opts(connOpts.split(QLatin1Char(';'), QString::SkipEmptyParts)); + const QStringList opts(connOpts.split(QLatin1Char(';'), Qt::SkipEmptyParts)); SQLRETURN r = SQL_SUCCESS; for (int i = 0; i < opts.count(); ++i) { const QString tmp(opts.at(i)); @@ -1422,7 +1414,7 @@ bool QODBCResult::exec() SQLLEN *ind = &indicators[i]; if (val.isNull()) *ind = SQL_NULL_DATA; - switch (val.type()) { + switch (val.userType()) { case QVariant::Date: { QByteArray &ba = tmpStorage[i]; ba.resize(sizeof(DATE_STRUCT)); @@ -1464,20 +1456,22 @@ bool QODBCResult::exec() case QVariant::DateTime: { QByteArray &ba = tmpStorage[i]; ba.resize(sizeof(TIMESTAMP_STRUCT)); - TIMESTAMP_STRUCT * dt = (TIMESTAMP_STRUCT *)const_cast<char *>(ba.constData()); - QDateTime qdt = val.toDateTime(); - dt->year = qdt.date().year(); - dt->month = qdt.date().month(); - dt->day = qdt.date().day(); - dt->hour = qdt.time().hour(); - dt->minute = qdt.time().minute(); - dt->second = qdt.time().second(); - - int precision = d->drv_d_func()->datetime_precision - 20; // (20 includes a separating period) + TIMESTAMP_STRUCT *dt = reinterpret_cast<TIMESTAMP_STRUCT *>(const_cast<char *>(ba.constData())); + const QDateTime qdt = val.toDateTime(); + const QDate qdate = qdt.date(); + const QTime qtime = qdt.time(); + dt->year = qdate.year(); + dt->month = qdate.month(); + dt->day = qdate.day(); + dt->hour = qtime.hour(); + dt->minute = qtime.minute(); + dt->second = qtime.second(); + // (20 includes a separating period) + const int precision = d->drv_d_func()->datetimePrecision - 20; if (precision <= 0) { dt->fraction = 0; } else { - dt->fraction = qdt.time().msec() * 1000000; + dt->fraction = qtime.msec() * 1000000; // (How many leading digits do we want to keep? With SQL Server 2005, this should be 3: 123000000) int keep = (int)qPow(10.0, 9 - qMin(9, precision)); @@ -1489,7 +1483,7 @@ bool QODBCResult::exec() qParamType[bindValueType(i) & QSql::InOut], SQL_C_TIMESTAMP, SQL_TIMESTAMP, - d->drv_d_func()->datetime_precision, + d->drv_d_func()->datetimePrecision, precision, (void *) dt, 0, @@ -1694,7 +1688,7 @@ bool QODBCResult::exec() return true; for (i = 0; i < values.count(); ++i) { - switch (values.at(i).type()) { + switch (values.at(i).userType()) { case QVariant::Date: { DATE_STRUCT ds = *((DATE_STRUCT *)const_cast<char *>(tmpStorage.at(i).constData())); values[i] = QVariant(QDate(ds.year, ds.month, ds.day)); @@ -1735,7 +1729,7 @@ bool QODBCResult::exec() break; } } if (indicators[i] == SQL_NULL_DATA) - values[i] = QVariant(values[i].type()); + values[i] = QVariant(QVariant::Type(values[i].userType())); } return true; } @@ -2245,7 +2239,7 @@ void QODBCDriverPrivate::checkDateTimePrecision() if ( r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO ) { if (SQLGetData(hStmt, 3, SQL_INTEGER, &columnSize, sizeof(columnSize), 0) == SQL_SUCCESS) { - datetime_precision = (int)columnSize; + datetimePrecision = (int)columnSize; } } } @@ -2385,7 +2379,7 @@ QStringList QODBCDriver::tables(QSql::TableType type) const } while (r == SQL_SUCCESS) { - QString fieldVal = qGetStringData(hStmt, 2, -1, false); + QString fieldVal = qGetStringData(hStmt, 2, -1, d->unicode); tl.append(fieldVal); if (d->hasSQLFetchScroll) diff --git a/src/plugins/sqldrivers/psql/qsql_psql.cpp b/src/plugins/sqldrivers/psql/qsql_psql.cpp index e0f82eee73..c5895f281d 100644 --- a/src/plugins/sqldrivers/psql/qsql_psql.cpp +++ b/src/plugins/sqldrivers/psql/qsql_psql.cpp @@ -149,26 +149,17 @@ class QPSQLDriverPrivate final : public QSqlDriverPrivate { Q_DECLARE_PUBLIC(QPSQLDriver) public: - QPSQLDriverPrivate() : QSqlDriverPrivate(), - connection(nullptr), - isUtf8(false), - pro(QPSQLDriver::Version6), - sn(nullptr), - pendingNotifyCheck(false), - hasBackslashEscape(false), - stmtCount(0), - currentStmtId(InvalidStatementId) - { dbmsType = QSqlDriver::PostgreSQL; } - - PGconn *connection; - bool isUtf8; - QPSQLDriver::Protocol pro; - QSocketNotifier *sn; + QPSQLDriverPrivate() : QSqlDriverPrivate(QSqlDriver::PostgreSQL) {} + QStringList seid; - mutable bool pendingNotifyCheck; - bool hasBackslashEscape; - int stmtCount; - StatementId currentStmtId; + PGconn *connection = nullptr; + QSocketNotifier *sn = nullptr; + QPSQLDriver::Protocol pro = QPSQLDriver::Version6; + StatementId currentStmtId = InvalidStatementId; + int stmtCount = 0; + mutable bool pendingNotifyCheck = false; + bool hasBackslashEscape = false; + bool isUtf8 = false; void appendTables(QStringList &tl, QSqlQuery &t, QChar type); PGresult *exec(const char *stmt); @@ -288,7 +279,7 @@ void QPSQLDriverPrivate::checkPendingNotifications() const Q_Q(const QPSQLDriver); if (seid.size() && !pendingNotifyCheck) { pendingNotifyCheck = true; - QMetaObject::invokeMethod(const_cast<QPSQLDriver*>(q), "_q_handleNotification", Qt::QueuedConnection, Q_ARG(int,0)); + QMetaObject::invokeMethod(const_cast<QPSQLDriver*>(q), "_q_handleNotification", Qt::QueuedConnection); } } @@ -297,25 +288,18 @@ class QPSQLResultPrivate : public QSqlResultPrivate Q_DECLARE_PUBLIC(QPSQLResult) public: Q_DECLARE_SQLDRIVER_PRIVATE(QPSQLDriver) - QPSQLResultPrivate(QPSQLResult *q, const QPSQLDriver *drv) - : QSqlResultPrivate(q, drv), - result(nullptr), - stmtId(InvalidStatementId), - currentSize(-1), - canFetchMoreRows(false), - preparedQueriesEnabled(false) - { } + using QSqlResultPrivate::QSqlResultPrivate; QString fieldSerial(int i) const override { return QLatin1Char('$') + QString::number(i + 1); } void deallocatePreparedStmt(); - PGresult *result; std::queue<PGresult*> nextResultSets; QString preparedStmtId; - StatementId stmtId; - int currentSize; - bool canFetchMoreRows; - bool preparedQueriesEnabled; + PGresult *result = nullptr; + StatementId stmtId = InvalidStatementId; + int currentSize = -1; + bool canFetchMoreRows = false; + bool preparedQueriesEnabled = false; bool processResults(); }; @@ -1262,7 +1246,7 @@ void QPSQLDriver::close() d->seid.clear(); if (d->sn) { - disconnect(d->sn, SIGNAL(activated(int)), this, SLOT(_q_handleNotification(int))); + disconnect(d->sn, SIGNAL(activated(QSocketDescriptor)), this, SLOT(_q_handleNotification())); delete d->sn; d->sn = nullptr; } @@ -1619,7 +1603,7 @@ bool QPSQLDriver::subscribeToNotification(const QString &name) if (!d->sn) { d->sn = new QSocketNotifier(socket, QSocketNotifier::Read); - connect(d->sn, SIGNAL(activated(int)), this, SLOT(_q_handleNotification(int))); + connect(d->sn, SIGNAL(activated(QSocketDescriptor)), this, SLOT(_q_handleNotification())); } } else { qWarning("QPSQLDriver::subscribeToNotificationImplementation: PQsocket didn't return a valid socket to listen on"); @@ -1655,7 +1639,7 @@ bool QPSQLDriver::unsubscribeFromNotification(const QString &name) d->seid.removeAll(name); if (d->seid.isEmpty()) { - disconnect(d->sn, SIGNAL(activated(int)), this, SLOT(_q_handleNotification(int))); + disconnect(d->sn, SIGNAL(activated(QSocketDescriptor)), this, SLOT(_q_handleNotification())); delete d->sn; d->sn = nullptr; } @@ -1669,7 +1653,7 @@ QStringList QPSQLDriver::subscribedToNotifications() const return d->seid; } -void QPSQLDriver::_q_handleNotification(int) +void QPSQLDriver::_q_handleNotification() { Q_D(QPSQLDriver); d->pendingNotifyCheck = false; @@ -1684,7 +1668,12 @@ void QPSQLDriver::_q_handleNotification(int) if (notify->extra) payload = d->isUtf8 ? QString::fromUtf8(notify->extra) : QString::fromLatin1(notify->extra); #endif +#if QT_DEPRECATED_SINCE(5, 15) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED emit notification(name); +QT_WARNING_POP +#endif QSqlDriver::NotificationSource source = (notify->be_pid == PQbackendPID(d->connection)) ? QSqlDriver::SelfSource : QSqlDriver::OtherSource; emit notification(name, source, payload); } diff --git a/src/plugins/sqldrivers/psql/qsql_psql_p.h b/src/plugins/sqldrivers/psql/qsql_psql_p.h index 9ac1fb50d7..22c0761667 100644 --- a/src/plugins/sqldrivers/psql/qsql_psql_p.h +++ b/src/plugins/sqldrivers/psql/qsql_psql_p.h @@ -130,7 +130,7 @@ protected: bool rollbackTransaction() override; private Q_SLOTS: - void _q_handleNotification(int); + void _q_handleNotification(); }; QT_END_NAMESPACE diff --git a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp index 001bd673fc..5eb9e7d2f8 100644 --- a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp +++ b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp @@ -144,42 +144,33 @@ class QSQLiteDriverPrivate : public QSqlDriverPrivate Q_DECLARE_PUBLIC(QSQLiteDriver) public: - inline QSQLiteDriverPrivate() : QSqlDriverPrivate(), access(0) { dbmsType = QSqlDriver::SQLite; } - sqlite3 *access; - QList <QSQLiteResult *> results; + inline QSQLiteDriverPrivate() : QSqlDriverPrivate(QSqlDriver::SQLite) {} + sqlite3 *access = nullptr; + QVector<QSQLiteResult *> results; QStringList notificationid; }; -class QSQLiteResultPrivate: public QSqlCachedResultPrivate +class QSQLiteResultPrivate : public QSqlCachedResultPrivate { Q_DECLARE_PUBLIC(QSQLiteResult) public: Q_DECLARE_SQLDRIVER_PRIVATE(QSQLiteDriver) - QSQLiteResultPrivate(QSQLiteResult *q, const QSQLiteDriver *drv); + using QSqlCachedResultPrivate::QSqlCachedResultPrivate; void cleanup(); bool fetchNext(QSqlCachedResult::ValueCache &values, int idx, bool initialFetch); // initializes the recordInfo and the cache void initColumns(bool emptyResultset); void finalize(); - sqlite3_stmt *stmt; - - bool skippedStatus; // the status of the fetchNext() that's skipped - bool skipRow; // skip the next fetchNext()? + sqlite3_stmt *stmt = nullptr; QSqlRecord rInf; QVector<QVariant> firstRow; + bool skippedStatus = false; // the status of the fetchNext() that's skipped + bool skipRow = false; // skip the next fetchNext()? }; -QSQLiteResultPrivate::QSQLiteResultPrivate(QSQLiteResult *q, const QSQLiteDriver *drv) - : QSqlCachedResultPrivate(q, drv), - stmt(0), - skippedStatus(false), - skipRow(false) -{ -} - void QSQLiteResultPrivate::cleanup() { Q_Q(QSQLiteResult); @@ -505,7 +496,7 @@ bool QSQLiteResult::exec() if (value.isNull()) { res = sqlite3_bind_null(d->stmt, i + 1); } else { - switch (value.type()) { + switch (value.userType()) { case QVariant::ByteArray: { const QByteArray *ba = static_cast<const QByteArray*>(value.constData()); res = sqlite3_bind_blob(d->stmt, i + 1, ba->constData(), @@ -1044,7 +1035,12 @@ void QSQLiteDriver::handleNotification(const QString &tableName, qint64 rowid) { Q_D(const QSQLiteDriver); if (d->notificationid.contains(tableName)) { +#if QT_DEPRECATED_SINCE(5, 15) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED emit notification(tableName); +QT_WARNING_POP +#endif emit notification(tableName, QSqlDriver::UnknownSource, QVariant(rowid)); } } diff --git a/src/plugins/sqldrivers/sqlite2/qsql_sqlite2_p.h b/src/plugins/sqldrivers/sqlite2/qsql_sqlite2_p.h index 48c64536f1..57db0a4d47 100644 --- a/src/plugins/sqldrivers/sqlite2/qsql_sqlite2_p.h +++ b/src/plugins/sqldrivers/sqlite2/qsql_sqlite2_p.h @@ -76,8 +76,8 @@ class Q_EXPORT_SQLDRIVER_SQLITE2 QSQLite2Driver : public QSqlDriver Q_DECLARE_PRIVATE(QSQLite2Driver) Q_OBJECT public: - explicit QSQLite2Driver(QObject *parent = 0); - explicit QSQLite2Driver(sqlite *connection, QObject *parent = 0); + explicit QSQLite2Driver(QObject *parent = nullptr); + explicit QSQLite2Driver(sqlite *connection, QObject *parent = nullptr); ~QSQLite2Driver(); bool hasFeature(DriverFeature f) const override; bool open(const QString &db, diff --git a/src/plugins/sqldrivers/tds/qsql_tds_p.h b/src/plugins/sqldrivers/tds/qsql_tds_p.h index 948e3c7024..b72fababbb 100644 --- a/src/plugins/sqldrivers/tds/qsql_tds_p.h +++ b/src/plugins/sqldrivers/tds/qsql_tds_p.h @@ -85,8 +85,8 @@ class Q_EXPORT_SQLDRIVER_TDS QTDSDriver : public QSqlDriver Q_OBJECT friend class QTDSResultPrivate; public: - explicit QTDSDriver(QObject* parent = 0); - QTDSDriver(LOGINREC* rec, const QString& host, const QString &db, QObject* parent = 0); + explicit QTDSDriver(QObject* parent = nullptr); + QTDSDriver(LOGINREC* rec, const QString& host, const QString &db, QObject* parent = nullptr); ~QTDSDriver(); bool hasFeature(DriverFeature f) const override; bool open(const QString &db, diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 71eb88008e..8e4aaa19c7 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -56,6 +56,7 @@ #include <QtCore/private/qcore_mac_p.h> +#include <QtGui/qpainterpath.h> #include <QtGui/private/qcoregraphics_p.h> #include <QtGui/qpa/qplatformfontdatabase.h> #include <QtGui/qpa/qplatformtheme.h> @@ -236,6 +237,18 @@ static QLinearGradient titlebarGradientInactive() } #if QT_CONFIG(tabwidget) +/* + Since macOS 10.14 AppKit is using transparency more extensively, especially for the + dark theme. Inactive buttons, for example, are semi-transparent. And we use them to + draw tab widget's tab bar. The combination of NSBox (also a part of tab widget) + and these transparent buttons gives us an undesired side-effect: an outline of + NSBox is visible through transparent buttons. To avoid this, we have this hack below: + we clip the area where the line would be visible through the buttons. The area we + want to clip away can be described as an intersection of the option's rect and + the tab widget's tab bar rect. But some adjustments are required, since those rects + are anyway adjusted during the rendering and they are not exactly what you'll see on + the screen. Thus this switch-statement inside. +*/ static void clipTabBarFrame(const QStyleOption *option, const QMacStyle *style, CGContextRef ctx) { Q_ASSERT(option); @@ -246,7 +259,19 @@ static void clipTabBarFrame(const QStyleOption *option, const QMacStyle *style, QTabWidget *tabWidget = qobject_cast<QTabWidget *>(option->styleObject); Q_ASSERT(tabWidget); - const QRect tabBarRect = style->subElementRect(QStyle::SE_TabWidgetTabBar, option, tabWidget).adjusted(2, 2, -3, -2); + QRect tabBarRect = style->subElementRect(QStyle::SE_TabWidgetTabBar, option, tabWidget).adjusted(2, 0, -3, 0); + switch (tabWidget->tabPosition()) { + case QTabWidget::South: + tabBarRect.setY(tabBarRect.y() + tabBarRect.height() / 2); + break; + case QTabWidget::North: + case QTabWidget::West: + tabBarRect = tabBarRect.adjusted(0, 2, 0, -2); + break; + case QTabWidget::East: + tabBarRect = tabBarRect.adjusted(tabBarRect.width() / 2, 2, tabBarRect.width() / 2, -2); + } + const QRegion clipPath = QRegion(option->rect) - tabBarRect; QVarLengthArray<CGRect, 3> cgRects; for (const QRect &qtRect : clipPath) @@ -1388,14 +1413,22 @@ void QMacStylePrivate::tabLayout(const QStyleOptionTab *opt, const QWidget *widg // High-dpi icons do not need adjustment; make sure tabIconSize is not larger than iconSize tabIconSize = QSize(qMin(tabIconSize.width(), iconSize.width()), qMin(tabIconSize.height(), iconSize.height())); - *iconRect = QRect(tr.left(), tr.center().y() - tabIconSize.height() / 2, - tabIconSize.width(), tabIconSize.height()); + const int stylePadding = proxyStyle->pixelMetric(QStyle::PM_TabBarTabHSpace, opt, widget) / 2 - hpadding; + + if (opt->documentMode) { + // documents show the icon as part of the the text + const int textWidth = + opt->fontMetrics.boundingRect(tr, Qt::AlignCenter | Qt::TextShowMnemonic, opt->text).width(); + *iconRect = QRect(tr.center().x() - textWidth / 2 - stylePadding - tabIconSize.width(), + tr.center().y() - tabIconSize.height() / 2, + tabIconSize.width(), tabIconSize.height()); + } else { + *iconRect = QRect(tr.left() + stylePadding, tr.center().y() - tabIconSize.height() / 2, + tabIconSize.width(), tabIconSize.height()); + } if (!verticalTabs) *iconRect = proxyStyle->visualRect(opt->direction, opt->rect, *iconRect); - int stylePadding = proxyStyle->pixelMetric(QStyle::PM_TabBarTabHSpace, opt, widget) / 2; - stylePadding -= hpadding; - tr.setLeft(tr.left() + stylePadding + tabIconSize.width() + 4); tr.setRight(tr.right() - stylePadding - tabIconSize.width() - 4); } @@ -2553,7 +2586,7 @@ QPalette QMacStyle::standardPalette() const auto platformTheme = QGuiApplicationPrivate::platformTheme(); auto styleNames = platformTheme->themeHint(QPlatformTheme::StyleNames); if (styleNames.toStringList().contains("macintosh")) - return *platformTheme->palette(); + return QPalette(); // Inherit everything from theme else return QStyle::standardPalette(); } @@ -2873,7 +2906,7 @@ int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w ret = false; break; case SH_Table_GridLineColor: - ret = int(qt_mac_toQColor(NSColor.gridColor).rgb()); + ret = int(qt_mac_toQColor(NSColor.gridColor).rgba()); break; default: ret = QCommonStyle::styleHint(sh, opt, w, hret); @@ -3064,13 +3097,18 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai bool needTranslation = false; if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave && !qt_mac_applicationIsInDarkMode()) { - // Another surprise from AppKit (SDK 10.14) - -displayRectIgnoringOpacity: - // is different from drawRect: for some Apple-known reason box is smaller - // in height than we need, resulting in tab buttons sitting too high/not - // centered. Attempts to play with insets etc did not work - the same wrong - // height. Simple translation is not working (too much space "at bottom"), - // so we make it bigger and translate (otherwise it's clipped at bottom btw). - adjustedRect.adjust(0, 0, 0, 3); + // In Aqua theme we have to use the 'default' NSBox (as opposite + // to the 'custom' QDarkNSBox we use in dark theme). Since -drawRect: + // does nothing in default NSBox, we call -displayRectIgnoringOpaticty:. + // Unfortunately, the resulting box is smaller then the actual rect we + // wanted. This can be seen, e.g. because tabs (buttons) are misaligned + // vertically and even worse, if QTabWidget has autoFillBackground + // set, this background overpaints NSBox making it to disappear. + // We trick our NSBox to render in a larger rectangle, so that + // the actuall result (which is again smaller than requested), + // more or less is what we really want. We'll have to adjust CTM + // and translate accordingly. + adjustedRect.adjust(0, 0, 6, 6); needTranslation = true; } d->drawNSViewInRect(box, adjustedRect, p, ^(CGContextRef ctx, const CGRect &rect) { @@ -3085,7 +3123,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai [box drawRect:rect]; } else { if (needTranslation) - CGContextTranslateCTM(ctx, 0.0, 4.0); + CGContextTranslateCTM(ctx, -3.0, 5.0); [box displayRectIgnoringOpacity:box.bounds inContext:NSGraphicsContext.currentContext]; } }); @@ -4594,6 +4632,7 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, case SE_ToolBoxTabContents: rect = QCommonStyle::subElementRect(sr, opt, widget); break; + case SE_PushButtonBevel: case SE_PushButtonContents: if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) { // Comment from the old HITheme days: @@ -4607,9 +4646,20 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, const auto ct = cocoaControlType(btn, widget); const auto cs = d->effectiveAquaSizeConstrain(btn, widget); const auto cw = QMacStylePrivate::CocoaControl(ct, cs); - const auto frameRect = cw.adjustedControlFrame(btn->rect); - const auto titleMargins = cw.titleMargins(); - rect = (frameRect - titleMargins).toRect(); + auto frameRect = cw.adjustedControlFrame(btn->rect); + if (sr == SE_PushButtonContents) { + frameRect -= cw.titleMargins(); + } else { + auto *pb = static_cast<NSButton *>(d->cocoaControl(cw)); + if (cw.type != QMacStylePrivate::Button_SquareButton) { + frameRect = QRectF::fromCGRect([pb alignmentRectForFrame:pb.frame]); + if (cw.type == QMacStylePrivate::Button_PushButton) + frameRect -= pushButtonShadowMargins[cw.size]; + else if (cw.type == QMacStylePrivate::Button_PullDown) + frameRect -= pullDownButtonShadowMargins[cw.size]; + } + } + rect = frameRect.toRect(); } break; case SE_HeaderLabel: { diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h index d6af18f01f..274936bd79 100644 --- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h +++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h @@ -284,7 +284,7 @@ public: CocoaControlType windowButtonCocoaControl(QStyle::SubControl sc) const; #if QT_CONFIG(tabbar) - void tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const; + void tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const override; static Direction tabDirection(QTabBar::Shape shape); static bool verticalTabs(QMacStylePrivate::Direction tabDirection); #endif diff --git a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp index f9d26c49ae..30b3786a80 100644 --- a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp +++ b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp @@ -1365,6 +1365,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption QWindowsStyle::drawControl(element, ©Opt, painter, widget); } break; +#if QT_CONFIG(dockwidget) case CE_DockWidgetTitle: if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) { const QDockWidget *dockWidget = qobject_cast<const QDockWidget *>(widget); @@ -1431,6 +1432,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption } } break; +#endif // QT_CONFIG(dockwidget) #if QT_CONFIG(itemviews) case CE_ItemViewItem: { @@ -2110,7 +2112,7 @@ int QWindowsVistaStyle::styleHint(StyleHint hint, const QStyleOption *option, co break; case SH_Table_GridLineColor: if (option) - ret = int(option->palette.color(QPalette::Base).darker(118).rgb()); + ret = int(option->palette.color(QPalette::Base).darker(118).rgba()); else ret = -1; break; @@ -2311,11 +2313,13 @@ void QWindowsVistaStyle::polish(QWidget *widget) #endif // QT_CONFIG(lineedit) if (qobject_cast<QGroupBox*>(widget)) widget->setAttribute(Qt::WA_Hover); +#if QT_CONFIG(commandlinkbutton) else if (qobject_cast<QCommandLinkButton*>(widget)) { QFont buttonFont = widget->font(); buttonFont.setFamily(QLatin1String("Segoe UI")); widget->setFont(buttonFont); } +#endif // QT_CONFIG(commandlinkbutton) else if (widget->inherits("QTipLabel")){ //note that since tooltips are not reused //we do not have to care about unpolishing @@ -2392,12 +2396,15 @@ void QWindowsVistaStyle::unpolish(QWidget *widget) #endif // QT_CONFIG(inputdialog) else if (QTreeView *tree = qobject_cast<QTreeView *> (widget)) { tree->viewport()->setAttribute(Qt::WA_Hover, false); - } else if (qobject_cast<QCommandLinkButton*>(widget)) { + } +#if QT_CONFIG(commandlinkbutton) + else if (qobject_cast<QCommandLinkButton*>(widget)) { QFont font = QApplication::font("QCommandLinkButton"); QFont widgetFont = widget->font(); widgetFont.setFamily(font.family()); //Only family set by polish widget->setFont(widgetFont); } +#endif // QT_CONFIG(commandlinkbutton) } diff --git a/src/plugins/styles/windowsvista/qwindowsvistastyle_p_p.h b/src/plugins/styles/windowsvista/qwindowsvistastyle_p_p.h index 8fef9f9927..c1d764a60e 100644 --- a/src/plugins/styles/windowsvista/qwindowsvistastyle_p_p.h +++ b/src/plugins/styles/windowsvista/qwindowsvistastyle_p_p.h @@ -106,7 +106,9 @@ #include <qtableview.h> #endif #include <qdatetime.h> +#if QT_CONFIG(commandlinkbutton) #include <qcommandlinkbutton.h> +#endif QT_BEGIN_NAMESPACE diff --git a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp index ba590b3eca..e43746e79f 100644 --- a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp +++ b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp @@ -225,9 +225,11 @@ static HRGN qt_hrgn_from_qregion(const QRegion ®ion) */ bool QWindowsXPStylePrivate::useXP(bool update) { - if (!update) - return use_xp; - return use_xp = IsThemeActive() && (IsAppThemed() || !QCoreApplication::instance()); + if (update) { + use_xp = IsThemeActive() && (IsAppThemed() || !QCoreApplication::instance()) + && !QWindowsStylePrivate::isDarkMode(); + } + return use_xp; } /* \internal @@ -663,7 +665,7 @@ static inline bool isFullyOpaque(const XPThemeData &themeData) \note drawBackgroundThruNativeBuffer() can return false for large sizes due to buffer()/CreateDIBSection() failing. */ -bool QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData) +bool QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData, qreal correctionFactor) { if (themeData.rect.isEmpty()) return true; @@ -708,9 +710,9 @@ bool QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData) } const HDC dc = canDrawDirectly ? hdcForWidgetBackingStore(themeData.widget) : nullptr; - const bool result = dc + const bool result = dc && qFuzzyCompare(correctionFactor, qreal(1)) ? drawBackgroundDirectly(dc, themeData, aditionalDevicePixelRatio) - : drawBackgroundThruNativeBuffer(themeData, aditionalDevicePixelRatio); + : drawBackgroundThruNativeBuffer(themeData, aditionalDevicePixelRatio, correctionFactor); painter->restore(); return result; } @@ -784,9 +786,14 @@ bool QWindowsXPStylePrivate::drawBackgroundDirectly(HDC dc, XPThemeData &themeDa other pixmaps etc), or when special transformations are needed (e.g. flips (horizonal mirroring only, vertical are handled by the theme engine). + + \a correctionFactor is an additional factor used to scale up controls + that are too small on High DPI screens, as has been observed for + WP_MDICLOSEBUTTON, WP_MDIRESTOREBUTTON, WP_MDIMINBUTTON (QTBUG-75927). */ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeData, - qreal additionalDevicePixelRatio) + qreal additionalDevicePixelRatio, + qreal correctionFactor) { QPainter *painter = themeData.painter; QRectF rectF = scaleRect(QRectF(themeData.rect), additionalDevicePixelRatio); @@ -795,7 +802,11 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa rectF = QRectF(0, 0, rectF.height(), rectF.width()); } rectF.moveTo(0, 0); + + const bool hasCorrectionFactor = !qFuzzyCompare(correctionFactor, qreal(1)); QRect rect = rectF.toRect(); + QRect drawRect = hasCorrectionFactor + ? QRectF(rectF.topLeft() / correctionFactor, rectF.size() / correctionFactor).toRect() : rect; int partId = themeData.partId; int stateId = themeData.stateId; int w = rect.width(); @@ -824,6 +835,10 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa pixmapCacheKey.append(QLatin1Char('h')); pixmapCacheKey.append(QString::number(additionalDevicePixelRatio)); pixmapCacheKey.append(QLatin1Char('d')); + if (hasCorrectionFactor) { + pixmapCacheKey.append(QLatin1Char('c')); + pixmapCacheKey.append(QString::number(correctionFactor)); + } QPixmap cachedPixmap; ThemeMapKey key(themeData); @@ -882,7 +897,7 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa // and DTGB_OMITCONTENT bool addBorderContentClipping = false; QRegion extraClip; - QRect area = rect; + QRect area = drawRect; if (themeData.noBorder || themeData.noContent) { extraClip = area; // We are running on a system where the uxtheme.dll does not have @@ -913,19 +928,19 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa QImage img; if (!haveCachedPixmap) { // If the pixmap is not cached, generate it! ------------------------- - if (!buffer(w, h)) // Ensure a buffer of at least (w, h) in size + if (!buffer(drawRect.width(), drawRect.height())) // Ensure a buffer of at least (w, h) in size return false; HDC dc = bufferHDC(); // Clear the buffer if (alphaType != NoAlpha) { // Consider have separate "memset" function for small chunks for more speedup - memset(bufferPixels, 0x00, bufferW * h * 4); + memset(bufferPixels, 0x00, bufferW * drawRect.height() * 4); } // Difference between area and rect - int dx = area.x() - rect.x(); - int dy = area.y() - rect.y(); + int dx = area.x() - drawRect.x(); + int dy = area.y() - drawRect.y(); // Adjust so painting rect starts from Origo rect.moveTo(0,0); @@ -955,7 +970,7 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa if (!hasAlpha && partIsTransparent) potentialInvalidAlpha = true; #if defined(DEBUG_XP_STYLE) && 1 - dumpNativeDIB(w, h); + dumpNativeDIB(drawRect.width(), drawRect.height()); #endif } @@ -983,6 +998,8 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa printf("Image format is: %s\n", alphaType == RealAlpha ? "Real Alpha" : alphaType == MaskAlpha ? "Masked Alpha" : "No Alpha"); #endif img = QImage(bufferPixels, bufferW, bufferH, format); + if (hasCorrectionFactor) + img = img.scaled(w, h, Qt::KeepAspectRatio, Qt::SmoothTransformation); img.setDevicePixelRatio(additionalDevicePixelRatio); } @@ -1023,7 +1040,7 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa imgCopy = cachedPixmap.toImage(); if (themeData.rotate) { - QMatrix rotMatrix; + QTransform rotMatrix; rotMatrix.rotate(themeData.rotate); imgCopy = imgCopy.transformed(rotMatrix); } @@ -2461,6 +2478,61 @@ QRect QWindowsXPStylePrivate::scrollBarGripperBounds(QStyle::State flags, const return sufficientSpace ? QRect(theme->rect.topLeft() + QPoint(hSpace, vSpace) / 2, size) : QRect(); } +#if QT_CONFIG(mdiarea) +// Helper for drawing MDI buttons into the corner widget of QMenuBar in case a +// QMdiSubWindow is maximized. +static void populateMdiButtonTheme(const QStyle *proxy, const QWidget *widget, + const QStyleOptionComplex *option, + QStyle::SubControl subControl, int part, + XPThemeData *theme) +{ + theme->partId = part; + theme->rect = proxy->subControlRect(QStyle::CC_MdiControls, option, subControl, widget); + if (!option->state.testFlag(QStyle::State_Enabled)) + theme->stateId = CBS_INACTIVE; + else if (option->state.testFlag(QStyle::State_Sunken) && option->activeSubControls.testFlag(subControl)) + theme->stateId = CBS_PUSHED; + else if (option->state.testFlag(QStyle::State_MouseOver) && option->activeSubControls.testFlag(subControl)) + theme->stateId = CBS_HOT; + else + theme->stateId = CBS_NORMAL; +} + +// Calculate an small (max 2), empirical correction factor for scaling up +// WP_MDICLOSEBUTTON, WP_MDIRESTOREBUTTON, WP_MDIMINBUTTON, which are too +// small on High DPI screens (QTBUG-75927). +qreal mdiButtonCorrectionFactor(XPThemeData &theme, const QPaintDevice *pd = nullptr) +{ + const auto dpr = pd ? pd->devicePixelRatioF() : qApp->devicePixelRatio(); + const QSizeF nativeSize = QSizeF(theme.size()) / dpr; + const QSizeF requestedSize(theme.rect.size()); + const auto rawFactor = qMin(requestedSize.width() / nativeSize.width(), + requestedSize.height() / nativeSize.height()); + const auto factor = rawFactor >= qreal(2) ? qreal(2) : qreal(1); + return factor; +} +#endif // QT_CONFIG(mdiarea) + +static void populateTitleBarButtonTheme(const QStyle *proxy, const QWidget *widget, + const QStyleOptionComplex *option, + QStyle::SubControl subControl, + bool isTitleBarActive, int part, + XPThemeData *theme) +{ + theme->rect = proxy->subControlRect(QStyle::CC_TitleBar, option, subControl, widget); + theme->partId = part; + if (widget && !widget->isEnabled()) + theme->stateId = RBS_DISABLED; + else if (option->activeSubControls == subControl && option->state.testFlag(QStyle::State_Sunken)) + theme->stateId = RBS_PUSHED; + else if (option->activeSubControls == subControl && option->state.testFlag(QStyle::State_MouseOver)) + theme->stateId = RBS_HOT; + else if (!isTitleBarActive) + theme->stateId = RBS_INACTIVE; + else + theme->stateId = RBS_NORMAL; +} + /*! \reimp */ @@ -3022,56 +3094,17 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo if (sub & SC_TitleBarMinButton && tb->titleBarFlags & Qt::WindowMinimizeButtonHint && !(tb->titleBarState & Qt::WindowMinimized)) { - theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarMinButton, widget); - partId = WP_MINBUTTON; - if (widget && !widget->isEnabled()) - stateId = MINBS_DISABLED; - else if (option->activeSubControls == SC_TitleBarMinButton && (option->state & State_Sunken)) - stateId = MINBS_PUSHED; - else if (option->activeSubControls == SC_TitleBarMinButton && (option->state & State_MouseOver)) - stateId = MINBS_HOT; - else if (!isActive) - stateId = MINBS_INACTIVE; - else - stateId = MINBS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; + populateTitleBarButtonTheme(proxy(), widget, option, SC_TitleBarMinButton, isActive, WP_MINBUTTON, &theme); d->drawBackground(theme); } if (sub & SC_TitleBarMaxButton && tb->titleBarFlags & Qt::WindowMaximizeButtonHint && !(tb->titleBarState & Qt::WindowMaximized)) { - theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarMaxButton, widget); - partId = WP_MAXBUTTON; - if (widget && !widget->isEnabled()) - stateId = MAXBS_DISABLED; - else if (option->activeSubControls == SC_TitleBarMaxButton && (option->state & State_Sunken)) - stateId = MAXBS_PUSHED; - else if (option->activeSubControls == SC_TitleBarMaxButton && (option->state & State_MouseOver)) - stateId = MAXBS_HOT; - else if (!isActive) - stateId = MAXBS_INACTIVE; - else - stateId = MAXBS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; + populateTitleBarButtonTheme(proxy(), widget, option, SC_TitleBarMaxButton, isActive, WP_MAXBUTTON, &theme); d->drawBackground(theme); } if (sub & SC_TitleBarContextHelpButton && tb->titleBarFlags & Qt::WindowContextHelpButtonHint) { - theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarContextHelpButton, widget); - partId = WP_HELPBUTTON; - if (widget && !widget->isEnabled()) - stateId = MINBS_DISABLED; - else if (option->activeSubControls == SC_TitleBarContextHelpButton && (option->state & State_Sunken)) - stateId = MINBS_PUSHED; - else if (option->activeSubControls == SC_TitleBarContextHelpButton && (option->state & State_MouseOver)) - stateId = MINBS_HOT; - else if (!isActive) - stateId = MINBS_INACTIVE; - else - stateId = MINBS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; + populateTitleBarButtonTheme(proxy(), widget, option, SC_TitleBarContextHelpButton, isActive, WP_HELPBUTTON, &theme); d->drawBackground(theme); } bool drawNormalButton = (sub & SC_TitleBarNormalButton) @@ -3080,74 +3113,21 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo || ((tb->titleBarFlags & Qt::WindowMaximizeButtonHint) && (tb->titleBarState & Qt::WindowMaximized))); if (drawNormalButton) { - theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarNormalButton, widget); - partId = WP_RESTOREBUTTON; - if (widget && !widget->isEnabled()) - stateId = RBS_DISABLED; - else if (option->activeSubControls == SC_TitleBarNormalButton && (option->state & State_Sunken)) - stateId = RBS_PUSHED; - else if (option->activeSubControls == SC_TitleBarNormalButton && (option->state & State_MouseOver)) - stateId = RBS_HOT; - else if (!isActive) - stateId = RBS_INACTIVE; - else - stateId = RBS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; + populateTitleBarButtonTheme(proxy(), widget, option, SC_TitleBarNormalButton, isActive, WP_RESTOREBUTTON, &theme); d->drawBackground(theme); } if (sub & SC_TitleBarShadeButton && tb->titleBarFlags & Qt::WindowShadeButtonHint && !(tb->titleBarState & Qt::WindowMinimized)) { - theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarShadeButton, widget); - partId = WP_MINBUTTON; - if (widget && !widget->isEnabled()) - stateId = MINBS_DISABLED; - else if (option->activeSubControls == SC_TitleBarShadeButton && (option->state & State_Sunken)) - stateId = MINBS_PUSHED; - else if (option->activeSubControls == SC_TitleBarShadeButton && (option->state & State_MouseOver)) - stateId = MINBS_HOT; - else if (!isActive) - stateId = MINBS_INACTIVE; - else - stateId = MINBS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; + populateTitleBarButtonTheme(proxy(), widget, option, SC_TitleBarShadeButton, isActive, WP_MINBUTTON, &theme); d->drawBackground(theme); } if (sub & SC_TitleBarUnshadeButton && tb->titleBarFlags & Qt::WindowShadeButtonHint && tb->titleBarState & Qt::WindowMinimized) { - theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarUnshadeButton, widget); - partId = WP_RESTOREBUTTON; - if (widget && !widget->isEnabled()) - stateId = RBS_DISABLED; - else if (option->activeSubControls == SC_TitleBarUnshadeButton && (option->state & State_Sunken)) - stateId = RBS_PUSHED; - else if (option->activeSubControls == SC_TitleBarUnshadeButton && (option->state & State_MouseOver)) - stateId = RBS_HOT; - else if (!isActive) - stateId = RBS_INACTIVE; - else - stateId = RBS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; + populateTitleBarButtonTheme(proxy(), widget, option, SC_TitleBarUnshadeButton, isActive, WP_RESTOREBUTTON, &theme); d->drawBackground(theme); } if (sub & SC_TitleBarCloseButton && tb->titleBarFlags & Qt::WindowSystemMenuHint) { - theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarCloseButton, widget); - //partId = titlebar->testWFlags(Qt::WA_WState_Tool) ? WP_SMALLCLOSEBUTTON : WP_CLOSEBUTTON; - partId = WP_CLOSEBUTTON; - if (widget && !widget->isEnabled()) - stateId = CBS_DISABLED; - else if (option->activeSubControls == SC_TitleBarCloseButton && (option->state & State_Sunken)) - stateId = CBS_PUSHED; - else if (option->activeSubControls == SC_TitleBarCloseButton && (option->state & State_MouseOver)) - stateId = CBS_HOT; - else if (!isActive) - stateId = CBS_INACTIVE; - else - stateId = CBS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; + populateTitleBarButtonTheme(proxy(), widget, option, SC_TitleBarCloseButton, isActive, WP_CLOSEBUTTON, &theme); d->drawBackground(theme); } } @@ -3157,56 +3137,21 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo #if QT_CONFIG(mdiarea) case CC_MdiControls: { - QRect buttonRect; XPThemeData theme(widget, p, QWindowsXPStylePrivate::WindowTheme, WP_MDICLOSEBUTTON, CBS_NORMAL); + if (Q_UNLIKELY(!theme.isValid())) + return; - if (option->subControls & SC_MdiCloseButton) { - buttonRect = proxy()->subControlRect(CC_MdiControls, option, SC_MdiCloseButton, widget); - if (theme.isValid()) { - theme.partId = WP_MDICLOSEBUTTON; - theme.rect = buttonRect; - if (!(flags & State_Enabled)) - theme.stateId = CBS_INACTIVE; - else if (flags & State_Sunken && (option->activeSubControls & SC_MdiCloseButton)) - theme.stateId = CBS_PUSHED; - else if (flags & State_MouseOver && (option->activeSubControls & SC_MdiCloseButton)) - theme.stateId = CBS_HOT; - else - theme.stateId = CBS_NORMAL; - d->drawBackground(theme); - } + if (option->subControls.testFlag(SC_MdiCloseButton)) { + populateMdiButtonTheme(proxy(), widget, option, SC_MdiCloseButton, WP_MDICLOSEBUTTON, &theme); + d->drawBackground(theme, mdiButtonCorrectionFactor(theme, widget)); } - if (option->subControls & SC_MdiNormalButton) { - buttonRect = proxy()->subControlRect(CC_MdiControls, option, SC_MdiNormalButton, widget); - if (theme.isValid()) { - theme.partId = WP_MDIRESTOREBUTTON; - theme.rect = buttonRect; - if (!(flags & State_Enabled)) - theme.stateId = CBS_INACTIVE; - else if (flags & State_Sunken && (option->activeSubControls & SC_MdiNormalButton)) - theme.stateId = CBS_PUSHED; - else if (flags & State_MouseOver && (option->activeSubControls & SC_MdiNormalButton)) - theme.stateId = CBS_HOT; - else - theme.stateId = CBS_NORMAL; - d->drawBackground(theme); - } + if (option->subControls.testFlag(SC_MdiNormalButton)) { + populateMdiButtonTheme(proxy(), widget, option, SC_MdiNormalButton, WP_MDIRESTOREBUTTON, &theme); + d->drawBackground(theme, mdiButtonCorrectionFactor(theme, widget)); } - if (option->subControls & QStyle::SC_MdiMinButton) { - buttonRect = proxy()->subControlRect(CC_MdiControls, option, SC_MdiMinButton, widget); - if (theme.isValid()) { - theme.partId = WP_MDIMINBUTTON; - theme.rect = buttonRect; - if (!(flags & State_Enabled)) - theme.stateId = CBS_INACTIVE; - else if (flags & State_Sunken && (option->activeSubControls & SC_MdiMinButton)) - theme.stateId = CBS_PUSHED; - else if (flags & State_MouseOver && (option->activeSubControls & SC_MdiMinButton)) - theme.stateId = CBS_HOT; - else - theme.stateId = CBS_NORMAL; - d->drawBackground(theme); - } + if (option->subControls.testFlag(QStyle::SC_MdiMinButton)) { + populateMdiButtonTheme(proxy(), widget, option, SC_MdiMinButton, WP_MDIMINBUTTON, &theme); + d->drawBackground(theme, mdiButtonCorrectionFactor(theme, widget)); } } break; @@ -3668,19 +3613,20 @@ QSize QWindowsXPStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt sz = QWindowsStyle::sizeFromContents(ct, option, sz, widget); break; - case CT_MdiControls: + case CT_MdiControls: { + sz.setHeight(int(QStyleHelper::dpiScaled(19, option))); + int width = 54; if (const QStyleOptionComplex *styleOpt = qstyleoption_cast<const QStyleOptionComplex *>(option)) { - int width = 0; + width = 0; if (styleOpt->subControls & SC_MdiMinButton) width += 17 + 1; if (styleOpt->subControls & SC_MdiNormalButton) width += 17 + 1; if (styleOpt->subControls & SC_MdiCloseButton) width += 17 + 1; - sz = QSize(width, 19); - } else { - sz = QSize(54, 19); } + sz.setWidth(int(QStyleHelper::dpiScaled(width, option))); + } break; default: @@ -3774,8 +3720,7 @@ int QWindowsXPStyle::styleHint(StyleHint hint, const QStyleOption *option, const /*! \reimp */ QPalette QWindowsXPStyle::standardPalette() const { - return QWindowsXPStylePrivate::useXP() && QApplicationPrivate::sys_pal - ? *QApplicationPrivate::sys_pal : QWindowsStyle::standardPalette(); + return QWindowsXPStylePrivate::useXP() ? QPalette() : QWindowsStyle::standardPalette(); } /*! diff --git a/src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h b/src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h index ad7754e3d4..06b37a6e5c 100644 --- a/src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h +++ b/src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h @@ -241,8 +241,8 @@ public: bool isTransparent(XPThemeData &themeData); QRegion region(XPThemeData &themeData); - bool drawBackground(XPThemeData &themeData); - bool drawBackgroundThruNativeBuffer(XPThemeData &themeData, qreal aditionalDevicePixelRatio); + bool drawBackground(XPThemeData &themeData, qreal correctionFactor = 1); + bool drawBackgroundThruNativeBuffer(XPThemeData &themeData, qreal aditionalDevicePixelRatio, qreal correctionFactor); bool drawBackgroundDirectly(HDC dc, XPThemeData &themeData, qreal aditionalDevicePixelRatio); bool hasAlphaChannel(const QRect &rect); diff --git a/src/plugins/styles/windowsvista/windowsvista.pro b/src/plugins/styles/windowsvista/windowsvista.pro index c08db7f533..483914c13d 100644 --- a/src/plugins/styles/windowsvista/windowsvista.pro +++ b/src/plugins/styles/windowsvista/windowsvista.pro @@ -11,9 +11,7 @@ HEADERS += qwindowsxpstyle_p.h qwindowsxpstyle_p_p.h SOURCES += qwindowsxpstyle.cpp QMAKE_USE_PRIVATE += user32 gdi32 - -# DEFINES/LIBS needed for qwizard_win.cpp and the styles -include(../../../widgets/kernel/win.pri) +LIBS_PRIVATE *= -luxtheme DISTFILES += windowsvistastyle.json |