diff options
Diffstat (limited to 'src/plugins')
16 files changed, 205 insertions, 114 deletions
diff --git a/src/plugins/bearer/generic/qgenericengine.cpp b/src/plugins/bearer/generic/qgenericengine.cpp index 7472758418..b1f28849a7 100644 --- a/src/plugins/bearer/generic/qgenericengine.cpp +++ b/src/plugins/bearer/generic/qgenericengine.cpp @@ -300,7 +300,7 @@ void QGenericEngine::doRequestUpdate() if (interface.flags() & QNetworkInterface::IsLoopBack) continue; -#ifndef Q_OS_WINRT +#ifndef Q_OS_WIN // ignore WLAN interface handled in separate engine if (qGetInterfaceType(interface.name()) == QNetworkConfiguration::BearerWLAN) continue; diff --git a/src/plugins/platforms/cocoa/qnsview_drawing.mm b/src/plugins/platforms/cocoa/qnsview_drawing.mm index 0cebc8d98d..3690d6ebb4 100644 --- a/src/plugins/platforms/cocoa/qnsview_drawing.mm +++ b/src/plugins/platforms/cocoa/qnsview_drawing.mm @@ -154,6 +154,7 @@ << "due to being" << ([self layerExplicitlyRequested] ? "explicitly requested" : [self shouldUseMetalLayer] ? "needed by surface type" : "enabled by macOS"); [super setLayer:layer]; + layer.delegate = self; } - (NSViewLayerContentsRedrawPolicy)layerContentsRedrawPolicy @@ -163,12 +164,14 @@ return NSViewLayerContentsRedrawDuringViewResize; } +#if 0 // Disabled until we enable lazy backingstore resizing - (NSViewLayerContentsPlacement)layerContentsPlacement { // Always place the layer at top left without any automatic scaling, // so that we can re-use larger layers when resizing a window down. return NSViewLayerContentsPlacementTopLeft; } +#endif - (void)updateMetalLayerDrawableSize:(CAMetalLayer *)layer { diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp index 48469b0f8c..c8a1ddf9b9 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp @@ -199,6 +199,10 @@ QPlatformWindow *QEglFSIntegration::createPlatformWindow(QWindow *window) const QEglFSWindow *w = qt_egl_device_integration()->createWindow(window); w->create(); + const auto showWithoutActivating = window->property("_q_showWithoutActivating"); + if (showWithoutActivating.isValid() && showWithoutActivating.toBool()) + return w; + // Activate only the window for the primary screen to make input work if (window->type() != Qt::ToolTip && window->screen() == QGuiApplication::primaryScreen()) w->requestActivateWindow(); diff --git a/src/plugins/platforms/eglfs/api/qeglfswindow.cpp b/src/plugins/platforms/eglfs/api/qeglfswindow.cpp index 98e9ee4728..c1d5af47aa 100644 --- a/src/plugins/platforms/eglfs/api/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfswindow.cpp @@ -167,6 +167,9 @@ void QEglFSWindow::create() void QEglFSWindow::destroy() { + if (!m_flags.testFlag(Created)) + return; // already destroyed + #ifndef QT_NO_OPENGL QOpenGLCompositor::instance()->removeWindow(this); #endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h index a19cf7e8bc..ee4b7978f1 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h @@ -55,6 +55,9 @@ public: : QEglFSWindow(w), m_integration(integration) { } + + ~QEglFSKmsGbmWindow() { destroy(); } + void resetSurface() override; void invalidateSurface() override; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp index ecdfb352ab..3e78196227 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp @@ -116,6 +116,8 @@ public: , m_egl_stream(EGL_NO_STREAM_KHR) { } + ~QEglFSKmsEglDeviceWindow() { destroy(); } + void invalidateSurface() override; void resetSurface() override; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp index 0d9b6b6290..d1250ec9bf 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp @@ -205,6 +205,9 @@ public: : QEglFSWindow(w) , m_integration(integration) {} + + ~QEglFSKmsVsp2Window() { destroy(); } + void resetSurface() override; void invalidateSurface() override; const QEglFSKmsVsp2Integration *m_integration; diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index 6da7265cfd..9de3268fc8 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -569,12 +569,10 @@ public: bool isFileSystem() const { return (m_attributes & SFGAO_FILESYSTEM) != 0; } bool isDir() const { return (m_attributes & SFGAO_FOLDER) != 0; } - // Copy using IFileOperation - bool canCopy() const { return (m_attributes & SFGAO_CANCOPY) != 0; } // Supports IStream bool canStream() const { return (m_attributes & SFGAO_STREAM) != 0; } - bool copyData(QIODevice *out); + bool copyData(QIODevice *out, QString *errorMessage); static IShellItems itemsFromItemArray(IShellItemArray *items); @@ -666,14 +664,19 @@ QWindowsShellItem::IShellItems QWindowsShellItem::itemsFromItemArray(IShellItemA return result; } -bool QWindowsShellItem::copyData(QIODevice *out) +bool QWindowsShellItem::copyData(QIODevice *out, QString *errorMessage) { - if (!canCopy() || !canStream()) + if (!canStream()) { + *errorMessage = QLatin1String("Item not streamable"); return false; + } IStream *istream = nullptr; HRESULT hr = m_item->BindToHandler(nullptr, BHID_Stream, IID_PPV_ARGS(&istream)); - if (FAILED(hr)) + if (FAILED(hr)) { + *errorMessage = QLatin1String("BindToHandler() failed: ") + + QLatin1String(QWindowsContext::comErrorString(hr)); return false; + } enum : ULONG { bufSize = 102400 }; char buffer[bufSize]; ULONG bytesRead; @@ -686,7 +689,12 @@ bool QWindowsShellItem::copyData(QIODevice *out) break; } istream->Release(); - return hr == S_OK || hr == S_FALSE; + if (hr != S_OK && hr != S_FALSE) { + *errorMessage = QLatin1String("Read() failed: ") + + QLatin1String(QWindowsContext::comErrorString(hr)); + return false; + } + return true; } // Helper for "Libraries": collections of folders appearing from Windows 7 @@ -735,8 +743,6 @@ void QWindowsShellItem::format(QDebug &d) const d << " [dir]"; if (canStream()) d << " [stream]"; - if (canCopy()) - d << " [copyable]"; d << ", normalDisplay=\"" << normalDisplay() << "\", desktopAbsoluteParsing=\"" << desktopAbsoluteParsing() << "\", urlString=\"" << urlString() << "\", fileSysPath=\"" << fileSysPath() << '"'; @@ -967,7 +973,9 @@ void QWindowsNativeFileDialogBase::doExec(HWND owner) const HRESULT hr = m_fileDialog->Show(owner); QWindowsDialogs::eatMouseMove(); qCDebug(lcQpaDialogs) << '<' << __FUNCTION__ << " returns " << hex << hr; - if (hr == S_OK) { + // Emit accepted() only if there is a result as otherwise UI hangs occur. + // For example, typing in invalid URLs results in empty result lists. + if (hr == S_OK && !m_data.selectedFiles().isEmpty()) { emit accepted(); } else { emit rejected(); @@ -1393,21 +1401,50 @@ static void cleanupTemporaryItemCopies() QFile::remove(file); } -static QString createTemporaryItemCopy(QWindowsShellItem &qItem) +// Determine temporary file pattern from a shell item's display +// name. This can be a URL. + +static bool validFileNameCharacter(QChar c) +{ + return c.isLetterOrNumber() || c == QLatin1Char('_') || c == QLatin1Char('-'); +} + +QString tempFilePattern(QString name) { - if (!qItem.canCopy() || !qItem.canStream()) + const int lastSlash = qMax(name.lastIndexOf(QLatin1Char('/')), + name.lastIndexOf(QLatin1Char('\\'))); + if (lastSlash != -1) + name.remove(0, lastSlash + 1); + + int lastDot = name.lastIndexOf(QLatin1Char('.')); + 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.prepend(QDir::tempPath() + QLatin1Char('/')); + return name; +} + +static QString createTemporaryItemCopy(QWindowsShellItem &qItem, QString *errorMessage) +{ + if (!qItem.canStream()) { + *errorMessage = QLatin1String("Item not streamable"); return QString(); - QString pattern = qItem.normalDisplay(); - const int lastDot = pattern.lastIndexOf(QLatin1Char('.')); - const QString placeHolder = QStringLiteral("_XXXXXX"); - if (lastDot >= 0) - pattern.insert(lastDot, placeHolder); - else - pattern.append(placeHolder); - - QTemporaryFile targetFile(QDir::tempPath() + QLatin1Char('/') + pattern); + } + + QTemporaryFile targetFile(tempFilePattern(qItem.normalDisplay())); targetFile.setAutoRemove(false); - if (!targetFile.open() || !qItem.copyData(&targetFile)) + if (!targetFile.open()) { + *errorMessage = QLatin1String("Cannot create temporary file: ") + + targetFile.errorString(); + return QString(); + } + if (!qItem.copyData(&targetFile, errorMessage)) return QString(); const QString result = targetFile.fileName(); if (temporaryItemCopies()->isEmpty()) @@ -1416,23 +1453,41 @@ static QString createTemporaryItemCopy(QWindowsShellItem &qItem) return result; } +static QUrl itemToDialogUrl(QWindowsShellItem &qItem, QString *errorMessage) +{ + QUrl url = qItem.url(); + if (url.isLocalFile() || url.scheme().startsWith(QLatin1String("http"))) + return url; + const QString path = qItem.path(); + if (path.isEmpty() && !qItem.isDir() && qItem.canStream()) { + const QString temporaryCopy = createTemporaryItemCopy(qItem, errorMessage); + if (temporaryCopy.isEmpty()) { + QDebug(errorMessage).noquote() << "Unable to create a local copy of" + << qItem << ": " << errorMessage; + return QUrl(); + } + return QUrl::fromLocalFile(temporaryCopy); + } + if (!url.isValid()) + QDebug(errorMessage).noquote() << "Invalid URL obtained from" << qItem; + return url; +} + QList<QUrl> QWindowsNativeOpenFileDialog::dialogResult() const { QList<QUrl> result; IShellItemArray *items = nullptr; if (SUCCEEDED(openFileDialog()->GetResults(&items)) && items) { + QString errorMessage; for (IShellItem *item : QWindowsShellItem::itemsFromItemArray(items)) { QWindowsShellItem qItem(item); - const QString path = qItem.path(); - if (path.isEmpty() && !qItem.isDir()) { - const QString temporaryCopy = createTemporaryItemCopy(qItem); - if (temporaryCopy.isEmpty()) - qWarning() << "Unable to create a local copy of" << qItem; - else - result.append(QUrl::fromLocalFile(temporaryCopy)); - } else { - result.append(qItem.url()); + const QUrl url = itemToDialogUrl(qItem, &errorMessage); + if (!url.isValid()) { + qWarning("%s", qPrintable(errorMessage)); + result.clear(); + break; } + result.append(url); } } return result; diff --git a/src/plugins/platforms/windows/qwindowsdropdataobject.cpp b/src/plugins/platforms/windows/qwindowsdropdataobject.cpp index 229ff92894..e1a41c0ede 100644 --- a/src/plugins/platforms/windows/qwindowsdropdataobject.cpp +++ b/src/plugins/platforms/windows/qwindowsdropdataobject.cpp @@ -41,6 +41,7 @@ #include <QtCore/qurl.h> #include <QtCore/qmimedata.h> +#include "qwindowsmime.h" QT_BEGIN_NAMESPACE @@ -48,8 +49,9 @@ QT_BEGIN_NAMESPACE \class QWindowsDropDataObject \brief QWindowsOleDataObject subclass specialized for handling Drag&Drop. - Only allows "text/uri-list" data to be exported as CF_HDROP, to allow dropped - files to be attached to Office applications (instead of adding an URL link). + Prevents "text/uri-list" data for local files from being exported as text + or URLs, to allow dropped files to be attached to Office applications + (instead of creating local hyperlinks). \internal \ingroup qt-lighthouse-win @@ -80,14 +82,22 @@ QWindowsDropDataObject::QueryGetData(LPFORMATETC pformatetc) return QWindowsOleDataObject::QueryGetData(pformatetc); } -// If the data is text/uri-list for local files, tell we can only export it as CF_HDROP. +// If the data is "text/uri-list" only, and all URIs are for local files, +// we prevent it from being exported as text or URLs, to make target applications +// like MS Office attach or open the files instead of creating local hyperlinks. bool QWindowsDropDataObject::shouldIgnore(LPFORMATETC pformatetc) const { QMimeData *dropData = mimeData(); - if (dropData && dropData->hasFormat(QStringLiteral("text/uri-list")) && (pformatetc->cfFormat != CF_HDROP)) { - QList<QUrl> urls = dropData->urls(); - return std::any_of(urls.cbegin(), urls.cend(), [] (const QUrl &u) { return u.isLocalFile(); }); + if (dropData && dropData->formats().size() == 1 && dropData->hasUrls()) { + QString formatName = QWindowsMimeConverter::clipboardFormatName(pformatetc->cfFormat); + if (pformatetc->cfFormat == CF_UNICODETEXT + || pformatetc->cfFormat == CF_TEXT + || formatName == QStringLiteral("UniformResourceLocator") + || formatName == QStringLiteral("UniformResourceLocatorW")) { + QList<QUrl> urls = dropData->urls(); + return std::all_of(urls.cbegin(), urls.cend(), [] (const QUrl &u) { return u.isLocalFile(); }); + } } return false; diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp index 96e34fb44c..030d8d1e0f 100644 --- a/src/plugins/platforms/windows/qwindowsmime.cpp +++ b/src/plugins/platforms/windows/qwindowsmime.cpp @@ -1087,7 +1087,10 @@ bool QWindowsMimeImage::canConvertFromMime(const FORMATETC &formatetc, const QMi const QImage image = qvariant_cast<QImage>(mimeData->imageData()); if (image.isNull()) return false; - return cf == CF_DIBV5 || (cf == CF_DIB) || cf == int(CF_PNG); + // QTBUG-64322: Use PNG only for transparent images as otherwise MS PowerPoint + // cannot handle it. + return cf == CF_DIBV5 || cf == CF_DIB + || (cf == int(CF_PNG) && image.hasAlphaChannel()); } bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp index 85a931e015..c7c0deab3f 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp @@ -113,6 +113,9 @@ void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event case QAccessible::ValueChanged: QWindowsUiaMainProvider::notifyValueChange(static_cast<QAccessibleValueChangeEvent *>(event)); break; + case QAccessible::SelectionAdd: + QWindowsUiaMainProvider::notifySelectionChange(event); + break; case QAccessible::TextAttributeChanged: case QAccessible::TextColumnChanged: case QAccessible::TextInserted: diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp index fad83fb165..44328492a6 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp @@ -146,9 +146,33 @@ void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *eve void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *event) { if (QAccessibleInterface *accessible = event->accessibleInterface()) { - if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) { - // Notifies changes in values of controls supporting the value interface. + if (accessible->role() == QAccessible::ComboBox && accessible->childCount() > 0) { + QAccessibleInterface *listacc = accessible->child(0); + if (listacc && listacc->role() == QAccessible::List) { + int count = listacc->childCount(); + for (int i = 0; i < count; ++i) { + QAccessibleInterface *item = listacc->child(i); + if (item && item->text(QAccessible::Name) == event->value()) { + if (!item->state().selected) { + if (QAccessibleActionInterface *actionInterface = item->actionInterface()) + actionInterface->doAction(QAccessibleActionInterface::toggleAction()); + } + break; + } + } + } + } + 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); + } + } else if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) { if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { + // Notifies changes in values of controls supporting the value interface. VARIANT oldVal, newVal; clearVariant(&oldVal); setVariantDouble(valueInterface->currentValue().toDouble(), &newVal); @@ -158,6 +182,15 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve } } +void QWindowsUiaMainProvider::notifySelectionChange(QAccessibleEvent *event) +{ + if (QAccessibleInterface *accessible = event->accessibleInterface()) { + if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { + QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_SelectionItem_ElementSelectedEventId); + } + } +} + // Notifies changes in text content and selection state of text controls. void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event) { diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h index 325d5b3de4..df0d60f9c9 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h @@ -68,6 +68,7 @@ public: static void notifyFocusChange(QAccessibleEvent *event); static void notifyStateChange(QAccessibleStateChangeEvent *event); static void notifyValueChange(QAccessibleValueChangeEvent *event); + static void notifySelectionChange(QAccessibleEvent *event); static void notifyTextChange(QAccessibleEvent *event); // IUnknown 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 476de6d1e5..4adf662152 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -270,7 +270,9 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share) // ES does not support any format option m_format.setOptions(QSurfaceFormat::FormatOptions()); } - + // Robustness must match that of the shared context. + if (share && share->format().testOption(QSurfaceFormat::ResetNotification)) + m_format.setOption(QSurfaceFormat::ResetNotification); Q_ASSERT(glVersions.count() > 0); for (int i = 0; !m_context && i < glVersions.count(); i++) { diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 04ddd3c98c..91fd612cde 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -1208,6 +1208,11 @@ bool QXcbConnection::xi2HandleTabletEvent(const void *event, TabletData *tabletD return handled; } +inline qreal scaleOneValuator(qreal normValue, qreal screenMin, qreal screenSize) +{ + return screenMin + normValue * screenSize; +} + void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletData) { auto *ev = reinterpret_cast<const qt_xcb_input_device_event_t *>(event); @@ -1220,6 +1225,17 @@ void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletD QPointF global(fixed1616ToReal(ev->root_x), fixed1616ToReal(ev->root_y)); double pressure = 0, rotation = 0, tangentialPressure = 0; int xTilt = 0, yTilt = 0; + static const bool useValuators = !qEnvironmentVariableIsSet("QT_XCB_TABLET_LEGACY_COORDINATES"); + + // Valuators' values are relative to the physical size of the current virtual + // screen. Therefore we cannot use QScreen/QWindow geometry and should use + // QPlatformWindow/QPlatformScreen instead. + QRect physicalScreenArea; + if (Q_LIKELY(useValuators)) { + const QList<QPlatformScreen *> siblings = window->screen()->handle()->virtualSiblings(); + for (const QPlatformScreen *screen : siblings) + physicalScreenArea |= screen->geometry(); + } for (QHash<int, TabletData::ValuatorClassInfo>::iterator it = tabletData->valuatorInfo.begin(), ite = tabletData->valuatorInfo.end(); it != ite; ++it) { @@ -1228,6 +1244,20 @@ void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletD xi2GetValuatorValueIfSet(event, classInfo.number, &classInfo.curVal); double normalizedValue = (classInfo.curVal - classInfo.minVal) / (classInfo.maxVal - classInfo.minVal); switch (valuator) { + case QXcbAtom::AbsX: + if (Q_LIKELY(useValuators)) { + const qreal value = scaleOneValuator(normalizedValue, physicalScreenArea.x(), physicalScreenArea.width()); + global.setX(value); + local.setX(value - window->handle()->geometry().x()); + } + break; + case QXcbAtom::AbsY: + if (Q_LIKELY(useValuators)) { + qreal value = scaleOneValuator(normalizedValue, physicalScreenArea.y(), physicalScreenArea.height()); + global.setY(value); + local.setY(value - window->handle()->geometry().y()); + } + break; case QXcbAtom::AbsPressure: pressure = normalizedValue; break; diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 9a11c4d818..847b1a6034 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -1156,66 +1156,6 @@ static QStyleHelper::WidgetSizePolicy qt_aqua_guess_size(const QWidget *widg, QS } #endif -static NSColor *qt_convertColorForContext(CGContextRef context, NSColor *color) -{ - Q_ASSERT(color); - Q_ASSERT(context); - - CGColorSpaceRef targetCGColorSpace = CGBitmapContextGetColorSpace(context); - NSColorSpace *targetNSColorSpace = [[NSColorSpace alloc] initWithCGColorSpace:targetCGColorSpace]; - NSColor *adjusted = [color colorUsingColorSpace:targetNSColorSpace]; - [targetNSColorSpace release]; - - return adjusted; -} - -static NSColor *qt_colorForContext(CGContextRef context, const CGFloat (&rgba)[4]) -{ - Q_ASSERT(context); - - auto colorSpace = CGBitmapContextGetColorSpace(context); - if (!colorSpace) - return nil; - - return qt_convertColorForContext(context, [NSColor colorWithSRGBRed:rgba[0] green:rgba[1] blue:rgba[2] alpha:rgba[3]]); -} - -static void qt_drawDisclosureButton(CGContextRef context, NSInteger state, bool selected, CGRect rect) -{ - Q_ASSERT(context); - - static const CGFloat gray[] = {0.55, 0.55, 0.55, 0.97}; - static const CGFloat white[] = {1.0, 1.0, 1.0, 0.9}; - - NSColor *fillColor = qt_colorForContext(context, selected ? white : gray); - [fillColor setFill]; - - if (state == NSOffState) { - static NSBezierPath *triangle = [[NSBezierPath alloc] init]; - [triangle removeAllPoints]; - // In off state, a disclosure button is an equilateral triangle - // ('pointing' to the right) with a bound rect that can be described - // as NSMakeRect(0, 0, 8, 9). Inside the 'rect' it's translated by - // (2, 4). - [triangle moveToPoint:NSMakePoint(rect.origin.x + 2, rect.origin.y + 4)]; - [triangle lineToPoint:NSMakePoint(rect.origin.x + 2, rect.origin.y + 4 + 9)]; - [triangle lineToPoint:NSMakePoint(rect.origin.x + 2 + 8, rect.origin.y + 4 + 4.5)]; - [triangle closePath]; - [triangle fill]; - } else { - static NSBezierPath *openTriangle = [[NSBezierPath alloc] init]; - [openTriangle removeAllPoints]; - // In 'on' state, the button is an equilateral triangle (looking down) - // with the bounding rect NSMakeRect(0, 0, 9, 8). Inside the 'rect' - // it's translated by (1, 4). - [openTriangle moveToPoint:NSMakePoint(rect.origin.x + 1, rect.origin.y + 4 + 8)]; - [openTriangle lineToPoint:NSMakePoint(rect.origin.x + 1 + 9, rect.origin.y + 4 + 8)]; - [openTriangle lineToPoint:NSMakePoint(rect.origin.x + 1 + 4.5, rect.origin.y + 4)]; - [openTriangle closePath]; - [openTriangle fill]; - } -} - void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const { QPainterPath focusRingPath; @@ -3301,15 +3241,8 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai CGContextScaleCTM(cg, 1, -1); CGContextTranslateCTM(cg, -rect.origin.x, -rect.origin.y); - if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave && !qt_mac_applicationIsInDarkMode()) { - // When the real system theme is one of the 'Dark' themes, and an application forces the 'Aqua' theme, - // under some conditions (see QTBUG-74515 for more details) NSButtonCell seems to select the 'Dark' - // code path and is becoming transparent, thus 'invisible' on the white background. To workaround this, - // we draw the disclose triangle manually: - qt_drawDisclosureButton(cg, triangleCell.state, (opt->state & State_Selected) && viewHasFocus, rect); - } else { - [triangleCell drawBezelWithFrame:NSRectFromCGRect(rect) inView:[triangleCell controlView]]; - } + [triangleCell drawBezelWithFrame:NSRectFromCGRect(rect) inView:[triangleCell controlView]]; + d->restoreNSGraphicsContext(cg); break; } @@ -3411,18 +3344,20 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai case PE_IndicatorTabClose: { // Make close button visible only on the hovered tab. QTabBar *tabBar = qobject_cast<QTabBar*>(w->parentWidget()); + const QWidget *closeBtn = w; if (!tabBar) { // QStyleSheetStyle instead of CloseButton (which has // a QTabBar as a parent widget) uses the QTabBar itself: tabBar = qobject_cast<QTabBar *>(const_cast<QWidget*>(w)); + closeBtn = decltype(closeBtn)(property("_q_styleSheetRealCloseButton").value<void *>()); } if (tabBar) { const bool documentMode = tabBar->documentMode(); const QTabBarPrivate *tabBarPrivate = static_cast<QTabBarPrivate *>(QObjectPrivate::get(tabBar)); const int hoveredTabIndex = tabBarPrivate->hoveredTabIndex(); if (!documentMode || - (hoveredTabIndex != -1 && ((w == tabBar->tabButton(hoveredTabIndex, QTabBar::LeftSide)) || - (w == tabBar->tabButton(hoveredTabIndex, QTabBar::RightSide))))) { + (hoveredTabIndex != -1 && ((closeBtn == tabBar->tabButton(hoveredTabIndex, QTabBar::LeftSide)) || + (closeBtn == tabBar->tabButton(hoveredTabIndex, QTabBar::RightSide))))) { const bool hover = (opt->state & State_MouseOver); const bool selected = (opt->state & State_Selected); const bool pressed = (opt->state & State_Sunken); @@ -4323,7 +4258,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter d->setupNSGraphicsContext(cgCtx, YES); [s.toNSString() drawInRect:textRect - withAttributes:@{ NSFontAttributeName:f, NSForegroundColorAttributeName:c }]; + withAttributes:@{ NSFontAttributeName:f, NSForegroundColorAttributeName:c, + NSObliquenessAttributeName: [NSNumber numberWithDouble: myFont.italic() ? 0.3 : 0.0]}]; d->restoreNSGraphicsContext(cgCtx); } else { |