summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/imageformats/gif/qgifhandler.cpp4
-rw-r--r--src/plugins/imageformats/ico/qicohandler.cpp2
-rw-r--r--src/plugins/platforminputcontexts/compose/compose.pro7
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.cpp7
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm5
-rw-r--r--src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm1
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm25
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoascreen.mm94
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm46
-rw-r--r--src/plugins/platforms/cocoa/qmacclipboard.mm28
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm75
-rw-r--r--src/plugins/platforms/cocoa/qnsview_complextext.mm4
-rw-r--r--src/plugins/platforms/cocoa/qnswindow.mm10
-rw-r--r--src/plugins/platforms/cocoa/qnswindowdelegate.h3
-rw-r--r--src/plugins/platforms/cocoa/qnswindowdelegate.mm44
-rw-r--r--src/plugins/platforms/cocoa/qpaintengine_mac.mm3
-rw-r--r--src/plugins/platforms/mirclient/mirclient.pro7
-rw-r--r--src/plugins/platforms/wasm/wasm.pro2
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp7
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp7
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.cpp9
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp105
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.cpp3
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp197
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.h41
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp13
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_screens.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.cpp3
-rw-r--r--src/plugins/platforms/xcb/qxcbeventdispatcher.h3
-rw-r--r--src/plugins/platforms/xcb/qxcbeventqueue.cpp5
-rw-r--r--src/plugins/platforms/xcb/qxcbmime.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp267
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h12
-rw-r--r--src/plugins/platforms/xcb/xcb_qpa_lib.pro14
-rw-r--r--src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp4
-rw-r--r--src/plugins/printsupport/cups/qcupsprintersupport.cpp5
-rw-r--r--src/plugins/printsupport/cups/qcupsprintersupport_p.h2
-rw-r--r--src/plugins/printsupport/cups/qppdprintdevice.cpp9
-rw-r--r--src/plugins/sqldrivers/configure.pri50
-rw-r--r--src/plugins/sqldrivers/mysql/qsql_mysql.cpp20
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm13
45 files changed, 607 insertions, 562 deletions
diff --git a/src/plugins/imageformats/gif/qgifhandler.cpp b/src/plugins/imageformats/gif/qgifhandler.cpp
index ebe5964664..1aef1a24d2 100644
--- a/src/plugins/imageformats/gif/qgifhandler.cpp
+++ b/src/plugins/imageformats/gif/qgifhandler.cpp
@@ -213,7 +213,7 @@ void QGIFFormat::disposePrevious(QImage *image)
case RestoreImage: {
if (frame >= 0) {
for (int ln=t; ln<=b; ln++) {
- memcpy(image->scanLine(ln)+l,
+ memcpy(image->scanLine(ln)+l*sizeof(QRgb),
backingstore.constScanLine(ln-t),
(r-l+1)*sizeof(QRgb));
}
@@ -426,7 +426,7 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
unsigned char *dest_data = backingstore.bits();
for (int ln=0; ln<h; ln++) {
memcpy(FAST_SCAN_LINE(dest_data, dest_bpl, ln),
- FAST_SCAN_LINE(bits, bpl, t+ln) + l, w*sizeof(QRgb));
+ FAST_SCAN_LINE(bits, bpl, t+ln) + l*sizeof(QRgb), w*sizeof(QRgb));
}
}
diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp
index e61173db30..30935cacda 100644
--- a/src/plugins/imageformats/ico/qicohandler.cpp
+++ b/src/plugins/imageformats/ico/qicohandler.cpp
@@ -506,6 +506,8 @@ QImage ICOReader::iconAt(int index)
icoAttrib.h = iconEntry.bHeight;
if (icoAttrib.h == 0) // means 256 pixels
icoAttrib.h = header.biHeight/2;
+ if (icoAttrib.w > 256 || icoAttrib.h > 256) // Max ico size
+ return img;
QImage::Format format = QImage::Format_ARGB32;
if (icoAttrib.nbits == 24)
diff --git a/src/plugins/platforminputcontexts/compose/compose.pro b/src/plugins/platforminputcontexts/compose/compose.pro
index 2f53c5b416..68bc2c3466 100644
--- a/src/plugins/platforminputcontexts/compose/compose.pro
+++ b/src/plugins/platforminputcontexts/compose/compose.pro
@@ -9,12 +9,7 @@ SOURCES += $$PWD/qcomposeplatforminputcontextmain.cpp \
HEADERS += $$PWD/qcomposeplatforminputcontext.h \
$$PWD/generator/qtablegenerator.h \
-# libxkbcommon
-!qtConfig(xkbcommon-system) {
- include(../../../3rdparty/xkbcommon.pri)
-} else {
- QMAKE_USE += xkbcommon
-}
+QMAKE_USE_PRIVATE += xkbcommon
include($$OUT_PWD/../../../gui/qtgui-config.pri)
diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp
index c5cd0b92d9..7b3546f9bb 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.cpp
+++ b/src/plugins/platforms/android/qandroidinputcontext.cpp
@@ -99,9 +99,13 @@ static jfieldID m_selectionStartFieldID = 0;
static jfieldID m_startOffsetFieldID = 0;
static jfieldID m_textFieldID = 0;
+Q_DECLARE_METATYPE(std::function<void()>)
+
static void runOnQtThread(const std::function<void()> &func)
{
- QMetaObject::invokeMethod(m_androidInputContext, "safeCall", Qt::BlockingQueuedConnection, Q_ARG(std::function<void()>, func));
+ const bool block = QGuiApplication::applicationState() >= Qt::ApplicationInactive;
+ QMetaObject::invokeMethod(m_androidInputContext, "safeCall",
+ block ? Qt::BlockingQueuedConnection : Qt::QueuedConnection, Q_ARG(std::function<void()>, func));
}
static jboolean beginBatchEdit(JNIEnv */*env*/, jobject /*thiz*/)
@@ -512,6 +516,7 @@ QAndroidInputContext::QAndroidInputContext()
m_handleMode = Hidden;
updateSelectionHandles();
});
+ qRegisterMetaType<std::function<void()>>();
}
QAndroidInputContext::~QAndroidInputContext()
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
index 03dc895ffb..a1176da33f 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
@@ -345,8 +345,9 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
return [NSValue valueWithRange: NSMakeRange(0, 0)];
} else if ([attribute isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute]) {
// FIXME This is not correct and may impact performance for big texts
- return [NSValue valueWithRange: NSMakeRange(0, iface->textInterface()->characterCount())];
-
+ if (QAccessibleTextInterface *text = iface->textInterface())
+ return [NSValue valueWithRange: NSMakeRange(0, text->characterCount())];
+ return [NSValue valueWithRange: NSMakeRange(0, iface->text(QAccessible::Name).length())];
} else if ([attribute isEqualToString:NSAccessibilityInsertionPointLineNumberAttribute]) {
if (QAccessibleTextInterface *text = iface->textInterface()) {
int line = 0; // true for all single line edits
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
index e7243ec250..d1695ea860 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
@@ -55,7 +55,6 @@
#include <qbuffer.h>
#include <qdebug.h>
#include <qstringlist.h>
-#include <qtextcodec.h>
#include <qvarlengtharray.h>
#include <stdlib.h>
#include <qabstracteventdispatcher.h>
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index 36841c77ab..d86e935788 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -402,23 +402,30 @@ QOperatingSystemVersion QMacVersion::currentRuntime()
QMacVersion::VersionTuple QMacVersion::versionsForImage(const mach_header *machHeader)
{
+ static auto makeVersionTuple = [](uint32_t dt, uint32_t sdk) {
+ return qMakePair(
+ QOperatingSystemVersion(QOperatingSystemVersion::MacOS,
+ dt >> 16 & 0xffff, dt >> 8 & 0xff, dt & 0xff),
+ QOperatingSystemVersion(QOperatingSystemVersion::MacOS,
+ sdk >> 16 & 0xffff, sdk >> 8 & 0xff, sdk & 0xff)
+ );
+ };
+
auto commandCursor = uintptr_t(machHeader) + sizeof(mach_header_64);
for (uint32_t i = 0; i < machHeader->ncmds; ++i) {
load_command *loadCommand = reinterpret_cast<load_command *>(commandCursor);
if (loadCommand->cmd == LC_VERSION_MIN_MACOSX) {
auto versionCommand = reinterpret_cast<version_min_command *>(loadCommand);
- uint32_t dt = versionCommand->version; // Deployment target
- uint32_t sdk = versionCommand->sdk; // Build SDK
- return qMakePair(
- QOperatingSystemVersion(QOperatingSystemVersion::MacOS,
- dt >> 16 & 0xffff, dt >> 8 & 0xff, dt & 0xff),
- QOperatingSystemVersion(QOperatingSystemVersion::MacOS,
- sdk >> 16 & 0xffff, sdk >> 8 & 0xff, sdk & 0xff)
- );
+ return makeVersionTuple(versionCommand->version, versionCommand->sdk);
+#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13)
+ } else if (loadCommand->cmd == LC_BUILD_VERSION) {
+ auto versionCommand = reinterpret_cast<build_version_command *>(loadCommand);
+ return makeVersionTuple(versionCommand->minos, versionCommand->sdk);
+#endif
}
commandCursor += loadCommand->cmdsize;
}
- Q_ASSERT_X(false, "QCocoaIntegration", "Could not find version-min load command");
+ Q_ASSERT_X(false, "QCocoaIntegration", "Could not find any version load command");
Q_UNREACHABLE();
}
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 1bd1029863..f6a49dd74f 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -63,6 +63,8 @@
#include <QtGui/private/qcoregraphics_p.h>
+#include <QtFontDatabaseSupport/private/qfontengine_coretext_p.h>
+
#ifdef QT_WIDGETS_LIB
#include <QtWidgets/qtwidgetsglobal.h>
#if QT_CONFIG(filedialog)
@@ -477,7 +479,7 @@ QCocoaServices *QCocoaIntegration::services() const
QVariant QCocoaIntegration::styleHint(StyleHint hint) const
{
if (hint == QPlatformIntegration::FontSmoothingGamma)
- return 2.0;
+ return QCoreTextFontEngine::fontSmoothingGamma();
return QPlatformIntegration::styleHint(hint);
}
diff --git a/src/plugins/platforms/cocoa/qcocoascreen.mm b/src/plugins/platforms/cocoa/qcocoascreen.mm
index f82ef202b1..afe14e623c 100644
--- a/src/plugins/platforms/cocoa/qcocoascreen.mm
+++ b/src/plugins/platforms/cocoa/qcocoascreen.mm
@@ -428,65 +428,71 @@ QWindow *QCocoaScreen::topLevelAt(const QPoint &point) const
return window;
}
-QPixmap QCocoaScreen::grabWindow(WId window, int x, int y, int width, int height) const
+QPixmap QCocoaScreen::grabWindow(WId view, int x, int y, int width, int height) const
{
- // TODO window should be handled
- Q_UNUSED(window)
-
- const int maxDisplays = 128; // 128 displays should be enough for everyone.
+ // Determine the grab rect. FIXME: The rect should be bounded by the view's
+ // geometry, but note that for the pixeltool use case that window will be the
+ // desktop widgets's view, which currently gets resized to fit one screen
+ // only, since its NSWindow has the NSWindowStyleMaskTitled flag set.
+ Q_UNUSED(view);
+ QRect grabRect = QRect(x, y, width, height);
+ qCDebug(lcQpaScreen) << "input grab rect" << grabRect;
+
+ // Find which displays to grab from, or all of them if the grab size is unspecified
+ const int maxDisplays = 128;
CGDirectDisplayID displays[maxDisplays];
CGDisplayCount displayCount;
- CGRect cgRect;
-
- if (width < 0 || height < 0) {
- // get all displays
- cgRect = CGRectInfinite;
- } else {
- cgRect = CGRectMake(x, y, width, height);
- }
+ CGRect cgRect = (width < 0 || height < 0) ? CGRectInfinite : grabRect.toCGRect();
const CGDisplayErr err = CGGetDisplaysWithRect(cgRect, maxDisplays, displays, &displayCount);
-
- if (err && displayCount == 0)
+ if (err || displayCount == 0)
return QPixmap();
- // calculate pixmap size
- QSize windowSize(width, height);
+ // If the grab size is not specified, set it to be the bounding box of all screens,
if (width < 0 || height < 0) {
QRect windowRect;
for (uint i = 0; i < displayCount; ++i) {
- const CGRect cgRect = CGDisplayBounds(displays[i]);
- QRect qRect(cgRect.origin.x, cgRect.origin.y, cgRect.size.width, cgRect.size.height);
- windowRect = windowRect.united(qRect);
+ QRect displayBounds = QRectF::fromCGRect(CGDisplayBounds(displays[i])).toRect();
+ windowRect = windowRect.united(displayBounds);
}
- if (width < 0)
- windowSize.setWidth(windowRect.width());
- if (height < 0)
- windowSize.setHeight(windowRect.height());
+ if (grabRect.width() < 0)
+ grabRect.setWidth(windowRect.width());
+ if (grabRect.height() < 0)
+ grabRect.setHeight(windowRect.height());
}
- const qreal dpr = devicePixelRatio();
- QPixmap windowPixmap(windowSize * dpr);
- windowPixmap.fill(Qt::transparent);
+ qCDebug(lcQpaScreen) << "final grab rect" << grabRect << "from" << displayCount << "displays";
+ // Grab images from each display
+ QVector<QImage> images;
+ QVector<QRect> destinations;
for (uint i = 0; i < displayCount; ++i) {
- const CGRect bounds = CGDisplayBounds(displays[i]);
-
- // Calculate the position and size of the requested area
- QPoint pos(qAbs(bounds.origin.x - x), qAbs(bounds.origin.y - y));
- QSize size(qMin(pos.x() + width, qRound(bounds.size.width)),
- qMin(pos.y() + height, qRound(bounds.size.height)));
- pos *= dpr;
- size *= dpr;
-
- // Take the whole screen and crop it afterwards, because CGDisplayCreateImageForRect
- // has a strange behavior when mixing highDPI and non-highDPI displays
- QCFType<CGImageRef> cgImage = CGDisplayCreateImage(displays[i]);
- const QImage image = qt_mac_toQImage(cgImage);
-
- // Draw into windowPixmap only the requested size
- QPainter painter(&windowPixmap);
- painter.drawImage(windowPixmap.rect(), image, QRect(pos, size));
+ auto display = displays[i];
+ QRect displayBounds = QRectF::fromCGRect(CGDisplayBounds(display)).toRect();
+ QRect grabBounds = displayBounds.intersected(grabRect);
+ QRect displayLocalGrabBounds = QRect(QPoint(grabBounds.topLeft() - displayBounds.topLeft()), grabBounds.size());
+ QImage displayImage = qt_mac_toQImage(QCFType<CGImageRef>(CGDisplayCreateImageForRect(display, displayLocalGrabBounds.toCGRect())));
+ displayImage.setDevicePixelRatio(displayImage.size().width() / displayLocalGrabBounds.size().width());
+ images.append(displayImage);
+ QRect destBounds = QRect(QPoint(grabBounds.topLeft() - grabRect.topLeft()), grabBounds.size());
+ destinations.append(destBounds);
+ qCDebug(lcQpaScreen) << "grab display" << i << "global" << grabBounds << "local" << displayLocalGrabBounds
+ << "grab image size" << displayImage.size() << "devicePixelRatio" << displayImage.devicePixelRatio();
}
+
+ // Determine the highest dpr, which becomes the dpr for the returned pixmap.
+ qreal dpr = 1.0;
+ for (uint i = 0; i < displayCount; ++i)
+ dpr = qMax(dpr, images.at(i).devicePixelRatio());
+
+ // Alocate target pixmap and draw each screen's content
+ qCDebug(lcQpaScreen) << "Create grap pixmap" << grabRect.size() << "at devicePixelRatio" << dpr;
+ QPixmap windowPixmap(grabRect.size() * dpr);
+ windowPixmap.setDevicePixelRatio(dpr);
+ windowPixmap.fill(Qt::transparent);
+ QPainter painter(&windowPixmap);
+ for (uint i = 0; i < displayCount; ++i)
+ painter.drawImage(destinations.at(i), images.at(i));
+
return windowPixmap;
}
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 1ce671941d..df1ad82592 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -897,34 +897,36 @@ void QCocoaWindow::raise()
qCDebug(lcQpaWindow) << "QCocoaWindow::raise" << window();
// ### handle spaces (see Qt 4 raise_sys in qwidget_mac.mm)
- if (!isContentView())
- return;
-
- if (m_view.window.visible) {
- {
- // Clean up autoreleased temp objects from orderFront immediately.
- // Failure to do so has been observed to cause leaks also beyond any outer
- // autorelease pool (for example around a complete QWindow
- // construct-show-raise-hide-delete cyle), counter to expected autoreleasepool
- // behavior.
- QMacAutoReleasePool pool;
- [m_view.window orderFront:m_view.window];
- }
- static bool raiseProcess = qt_mac_resolveOption(true, "QT_MAC_SET_RAISE_PROCESS");
- if (raiseProcess) {
- [NSApp activateIgnoringOtherApps:YES];
+ if (isContentView()) {
+ if (m_view.window.visible) {
+ {
+ // Clean up auto-released temp objects from orderFront immediately.
+ // Failure to do so has been observed to cause leaks also beyond any outer
+ // autorelease pool (for example around a complete QWindow
+ // construct-show-raise-hide-delete cycle), counter to expected autoreleasepool
+ // behavior.
+ QMacAutoReleasePool pool;
+ [m_view.window orderFront:m_view.window];
+ }
+ static bool raiseProcess = qt_mac_resolveOption(true, "QT_MAC_SET_RAISE_PROCESS");
+ if (raiseProcess)
+ [NSApp activateIgnoringOtherApps:YES];
}
+ } else {
+ [m_view.superview addSubview:m_view positioned:NSWindowAbove relativeTo:nil];
}
}
void QCocoaWindow::lower()
{
qCDebug(lcQpaWindow) << "QCocoaWindow::lower" << window();
- if (!isContentView())
- return;
- if (m_view.window.visible)
- [m_view.window orderBack:m_view.window];
+ if (isContentView()) {
+ if (m_view.window.visible)
+ [m_view.window orderBack:m_view.window];
+ } else {
+ [m_view.superview addSubview:m_view positioned:NSWindowBelow relativeTo:nil];
+ }
}
bool QCocoaWindow::isExposed() const
@@ -1548,7 +1550,9 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel)
QWindowSystemInterface::SynchronousDelivery>(window(), targetScreen);
}
- nsWindow.delegate = [[QNSWindowDelegate alloc] initWithQCocoaWindow:this];
+ static QSharedPointer<QNSWindowDelegate> sharedDelegate([[QNSWindowDelegate alloc] init],
+ [](QNSWindowDelegate *delegate) { [delegate release]; });
+ nsWindow.delegate = sharedDelegate.get();
// Prevent Cocoa from releasing the window on close. Qt
// handles the close event asynchronously and we want to
diff --git a/src/plugins/platforms/cocoa/qmacclipboard.mm b/src/plugins/platforms/cocoa/qmacclipboard.mm
index 5939003c64..ba6cfca219 100644
--- a/src/plugins/platforms/cocoa/qmacclipboard.mm
+++ b/src/plugins/platforms/cocoa/qmacclipboard.mm
@@ -49,6 +49,7 @@
#include <stdlib.h>
#include <string.h>
#include "qcocoahelpers.h"
+#include <type_traits>
QT_BEGIN_NAMESPACE
@@ -61,6 +62,23 @@ QT_BEGIN_NAMESPACE
QMacPasteboard code
*****************************************************************************/
+namespace
+{
+OSStatus PasteboardGetItemCountSafe(PasteboardRef paste, ItemCount *cnt)
+{
+ Q_ASSERT(paste);
+ Q_ASSERT(cnt);
+ const OSStatus result = PasteboardGetItemCount(paste, cnt);
+ // Despite being declared unsigned, this API can return -1
+ if (std::make_signed<ItemCount>::type(*cnt) < 0)
+ *cnt = 0;
+ return result;
+}
+} // namespace
+
+// Ensure we don't call the broken one later on
+#define PasteboardGetItemCount
+
class QMacMimeData : public QMimeData
{
public:
@@ -210,7 +228,7 @@ QMacPasteboard::hasOSType(int c_flavor) const
sync();
ItemCount cnt = 0;
- if (PasteboardGetItemCount(paste, &cnt) || !cnt)
+ if (PasteboardGetItemCountSafe(paste, &cnt) || !cnt)
return false;
#ifdef DEBUG_PASTEBOARD
@@ -257,7 +275,7 @@ QMacPasteboard::hasFlavor(QString c_flavor) const
sync();
ItemCount cnt = 0;
- if (PasteboardGetItemCount(paste, &cnt) || !cnt)
+ if (PasteboardGetItemCountSafe(paste, &cnt) || !cnt)
return false;
#ifdef DEBUG_PASTEBOARD
@@ -374,7 +392,7 @@ QMacPasteboard::formats() const
QStringList ret;
ItemCount cnt = 0;
- if (PasteboardGetItemCount(paste, &cnt) || !cnt)
+ if (PasteboardGetItemCountSafe(paste, &cnt) || !cnt)
return ret;
#ifdef DEBUG_PASTEBOARD
@@ -417,7 +435,7 @@ QMacPasteboard::hasFormat(const QString &format) const
sync();
ItemCount cnt = 0;
- if (PasteboardGetItemCount(paste, &cnt) || !cnt)
+ if (PasteboardGetItemCountSafe(paste, &cnt) || !cnt)
return false;
#ifdef DEBUG_PASTEBOARD
@@ -460,7 +478,7 @@ QMacPasteboard::retrieveData(const QString &format, QVariant::Type) const
sync();
ItemCount cnt = 0;
- if (PasteboardGetItemCount(paste, &cnt) || !cnt)
+ if (PasteboardGetItemCountSafe(paste, &cnt) || !cnt)
return QByteArray();
#ifdef DEBUG_PASTEBOARD
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 540f701d43..7f826942f3 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -68,6 +68,8 @@
// Private interface
@interface QT_MANGLE_NAMESPACE(QNSView) ()
- (BOOL)isTransparentForUserInput;
+@property (assign) NSView* previousSuperview;
+@property (assign) NSWindow* previousWindow;
@end
@interface QT_MANGLE_NAMESPACE(QNSView) (Drawing) <CALayerDelegate>
@@ -153,6 +155,9 @@
self.focusRingType = NSFocusRingTypeNone;
self.cursor = nil;
+ self.previousSuperview = nil;
+ self.previousWindow = nil;
+
[self initDrawing];
[self registerDragTypes];
@@ -166,6 +171,8 @@
- (void)dealloc
{
+ qCDebug(lcQpaWindow) << "Deallocating" << self;
+
if (m_trackingArea) {
[self removeTrackingArea:m_trackingArea];
[m_trackingArea release];
@@ -193,8 +200,40 @@
return description;
}
+// ----------------------------- Re-parenting ---------------------------------
+
+- (void)removeFromSuperview
+{
+ QMacAutoReleasePool pool;
+ [super removeFromSuperview];
+}
+
+- (void)viewWillMoveToSuperview:(NSView *)newSuperview
+{
+ Q_ASSERT(!self.previousSuperview);
+ self.previousSuperview = self.superview;
+
+ if (newSuperview == self.superview)
+ qCDebug(lcQpaWindow) << "Re-ordering" << self << "inside" << self.superview;
+ else
+ qCDebug(lcQpaWindow) << "Re-parenting" << self << "from" << self.superview << "to" << newSuperview;
+}
+
- (void)viewDidMoveToSuperview
{
+ auto cleanup = qScopeGuard([&] { self.previousSuperview = nil; });
+
+ if (self.superview == self.previousSuperview) {
+ qCDebug(lcQpaWindow) << "Done re-ordering" << self << "new index:"
+ << [self.superview.subviews indexOfObject:self];
+ return;
+ }
+
+ qCDebug(lcQpaWindow) << "Done re-parenting" << self << "into" << self.superview;
+
+ // Note: at this point the view's window property hasn't been updated to match the window
+ // of the new superview. We have to wait for viewDidMoveToWindow for that to be reflected.
+
if (!m_platformWindow)
return;
@@ -208,6 +247,36 @@
}
}
+- (void)viewWillMoveToWindow:(NSWindow *)newWindow
+{
+ Q_ASSERT(!self.previousWindow);
+ self.previousWindow = self.window;
+
+ // This callback is documented to be called also when a view is just moved between
+ // subviews in the same NSWindow, so we're not necessarily moving between NSWindows.
+ if (newWindow == self.window)
+ return;
+
+ qCDebug(lcQpaWindow) << "Moving" << self << "from" << self.window << "to" << newWindow;
+
+ // Note: at this point the superview has already been updated, so we know which view inside
+ // the new window the view will be a child of.
+}
+
+- (void)viewDidMoveToWindow
+{
+ auto cleanup = qScopeGuard([&] { self.previousWindow = nil; });
+
+ // This callback is documented to be called also when a view is just moved between
+ // subviews in the same NSWindow, so we're not necessarily moving between NSWindows.
+ if (self.window == self.previousWindow)
+ return;
+
+ qCDebug(lcQpaWindow) << "Done moving" << self << "to" << self.window;
+}
+
+// ----------------------------------------------------------------------------
+
- (QWindow *)topLevelWindow
{
if (!m_platformWindow)
@@ -237,12 +306,6 @@
// viewDidUnhide so no reason to override it here.
}
-- (void)removeFromSuperview
-{
- QMacAutoReleasePool pool;
- [super removeFromSuperview];
-}
-
- (BOOL)isTransparentForUserInput
{
return m_platformWindow->window() &&
diff --git a/src/plugins/platforms/cocoa/qnsview_complextext.mm b/src/plugins/platforms/cocoa/qnsview_complextext.mm
index d357082d33..6ff9b26ca4 100644
--- a/src/plugins/platforms/cocoa/qnsview_complextext.mm
+++ b/src/plugins/platforms/cocoa/qnsview_complextext.mm
@@ -307,8 +307,8 @@
{
Q_UNUSED(textInputContextKeyboardSelectionDidChangeNotification)
if (([NSApp keyWindow] == self.window) && self.window.firstResponder == self) {
- QCocoaInputContext *ic = qobject_cast<QCocoaInputContext *>(QCocoaIntegration::instance()->inputContext());
- ic->updateLocale();
+ if (QCocoaInputContext *ic = qobject_cast<QCocoaInputContext *>(QCocoaIntegration::instance()->inputContext()))
+ ic->updateLocale();
}
}
diff --git a/src/plugins/platforms/cocoa/qnswindow.mm b/src/plugins/platforms/cocoa/qnswindow.mm
index 1b9dd95cbc..c17ad47aba 100644
--- a/src/plugins/platforms/cocoa/qnswindow.mm
+++ b/src/plugins/platforms/cocoa/qnswindow.mm
@@ -238,11 +238,7 @@ static bool isMouseEvent(NSEvent *ev)
- (void)closeAndRelease
{
- qCDebug(lcQpaWindow) << "closeAndRelease" << self;
-
- [self.delegate release];
- self.delegate = nil;
-
+ qCDebug(lcQpaWindow) << "Closing and releasing" << self;
[self close];
[self release];
}
@@ -251,7 +247,9 @@ static bool isMouseEvent(NSEvent *ev)
#pragma clang diagnostic ignored "-Wobjc-missing-super-calls"
- (void)dealloc
{
- qCDebug(lcQpaWindow) << "dealloc" << self;
+ qCDebug(lcQpaWindow) << "Deallocating" << self;
+ self.delegate = nil;
+
qt_objcDynamicSuper();
}
#pragma clang diagnostic pop
diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.h b/src/plugins/platforms/cocoa/qnswindowdelegate.h
index e71afcbb2a..be870deb3a 100644
--- a/src/plugins/platforms/cocoa/qnswindowdelegate.h
+++ b/src/plugins/platforms/cocoa/qnswindowdelegate.h
@@ -48,9 +48,6 @@ class QCocoaWindow;
QT_END_NAMESPACE
@interface QT_MANGLE_NAMESPACE(QNSWindowDelegate) : NSObject <NSWindowDelegate>
-
-- (instancetype)initWithQCocoaWindow:(QT_PREPEND_NAMESPACE(QCocoaWindow) *)cocoaWindow;
-
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSWindowDelegate);
diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.mm b/src/plugins/platforms/cocoa/qnswindowdelegate.mm
index 97309ea990..14f1ca0114 100644
--- a/src/plugins/platforms/cocoa/qnswindowdelegate.mm
+++ b/src/plugins/platforms/cocoa/qnswindowdelegate.mm
@@ -49,23 +49,17 @@
static QRegExp whitespaceRegex = QRegExp(QStringLiteral("\\s*"));
-@implementation QNSWindowDelegate {
- QCocoaWindow *m_cocoaWindow;
-}
-
-- (instancetype)initWithQCocoaWindow:(QCocoaWindow *)cocoaWindow
+static QCocoaWindow *toPlatformWindow(NSWindow *window)
{
- if ((self = [self init]))
- m_cocoaWindow = cocoaWindow;
- return self;
+ return qnsview_cast(window.contentView).platformWindow;
}
-- (BOOL)windowShouldClose:(NSNotification *)notification
+@implementation QNSWindowDelegate
+
+- (BOOL)windowShouldClose:(NSWindow *)window
{
- Q_UNUSED(notification);
- if (m_cocoaWindow) {
- return m_cocoaWindow->windowShouldClose();
- }
+ if (QCocoaWindow *platformWindow = toPlatformWindow(window))
+ return platformWindow->windowShouldClose();
return YES;
}
@@ -79,14 +73,16 @@ static QRegExp whitespaceRegex = QRegExp(QStringLiteral("\\s*"));
- (NSRect)windowWillUseStandardFrame:(NSWindow *)window defaultFrame:(NSRect)proposedFrame
{
Q_UNUSED(proposedFrame);
- Q_ASSERT(window == m_cocoaWindow->nativeWindow());
- const QWindow *w = m_cocoaWindow->window();
+
+ QCocoaWindow *platformWindow = toPlatformWindow(window);
+ Q_ASSERT(platformWindow);
+ const QWindow *w = platformWindow->window();
// maximumSize() refers to the client size, but AppKit expects the full frame size
QSizeF maximumSize = w->maximumSize() + QSize(0, w->frameMargins().top());
// The window should never be larger than the current screen geometry
- const QRectF screenGeometry = m_cocoaWindow->screen()->geometry();
+ const QRectF screenGeometry = platformWindow->screen()->geometry();
maximumSize = maximumSize.boundedTo(screenGeometry.size());
// Use the current frame position for the initial maximized frame,
@@ -113,6 +109,8 @@ static QRegExp whitespaceRegex = QRegExp(QStringLiteral("\\s*"));
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)frameSize
{
+ Q_ASSERT(toPlatformWindow(window));
+
qCDebug(lcQpaWindow) << window << "will resize to" << QSizeF::fromCGSize(frameSize)
<< "- disabling screen updates temporarily";
@@ -131,6 +129,8 @@ static QRegExp whitespaceRegex = QRegExp(QStringLiteral("\\s*"));
- (void)windowDidResize:(NSNotification *)notification
{
NSWindow *window = notification.object;
+ Q_ASSERT(toPlatformWindow(window));
+
qCDebug(lcQpaWindow) << window << "was resized - re-enabling screen updates";
NSEnableScreenUpdates();
}
@@ -138,23 +138,27 @@ static QRegExp whitespaceRegex = QRegExp(QStringLiteral("\\s*"));
- (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu
{
- Q_UNUSED(window);
Q_UNUSED(menu);
+ QCocoaWindow *platformWindow = toPlatformWindow(window);
+ Q_ASSERT(platformWindow);
+
// Only pop up document path if the filename is non-empty. We allow whitespace, to
// allow faking a window icon by setting the file path to a single space character.
- return !whitespaceRegex.exactMatch(m_cocoaWindow->window()->filePath());
+ return !whitespaceRegex.exactMatch(platformWindow->window()->filePath());
}
- (BOOL)window:(NSWindow *)window shouldDragDocumentWithEvent:(NSEvent *)event from:(NSPoint)dragImageLocation withPasteboard:(NSPasteboard *)pasteboard
{
- Q_UNUSED(window);
Q_UNUSED(event);
Q_UNUSED(dragImageLocation);
Q_UNUSED(pasteboard);
+ QCocoaWindow *platformWindow = toPlatformWindow(window);
+ Q_ASSERT(platformWindow);
+
// Only allow drag if the filename is non-empty. We allow whitespace, to
// allow faking a window icon by setting the file path to a single space.
- return !whitespaceRegex.exactMatch(m_cocoaWindow->window()->filePath());
+ return !whitespaceRegex.exactMatch(platformWindow->window()->filePath());
}
@end
diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm
index 96506c67fa..3677877538 100644
--- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm
+++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm
@@ -47,7 +47,6 @@
#include <private/qpaintengine_raster_p.h>
#include <qprinter.h>
#include <qstack.h>
-#include <qtextcodec.h>
#include <qwidget.h>
#include <qvarlengtharray.h>
#include <qdebug.h>
@@ -314,7 +313,6 @@ static void qt_mac_draw_pattern(void *info, CGContextRef c)
}
pat->image = qt_mac_create_imagemask(pm, pm.rect());
CGImageRelease(swatch);
- CGContextRelease(pm_ctx);
w *= QMACPATTERN_MASK_MULTIPLIER;
h *= QMACPATTERN_MASK_MULTIPLIER;
#endif
@@ -916,7 +914,6 @@ void QCoreGraphicsPaintEngine::drawTextItem(const QPointF &pos, const QTextItem
QFontEngine *fe = ti.fontEngine;
const bool textAA = ((state->renderHints() & QPainter::TextAntialiasing)
- && (fe->fontDef.pointSize > QCoreTextFontEngine::antialiasingThreshold)
&& !(fe->fontDef.styleStrategy & QFont::NoAntialias));
const bool lineAA = state->renderHints() & QPainter::Antialiasing;
if (textAA != lineAA)
diff --git a/src/plugins/platforms/mirclient/mirclient.pro b/src/plugins/platforms/mirclient/mirclient.pro
index d2da7e6ca0..d9eb069200 100644
--- a/src/plugins/platforms/mirclient/mirclient.pro
+++ b/src/plugins/platforms/mirclient/mirclient.pro
@@ -53,12 +53,7 @@ HEADERS = \
qmirclienttheme.h \
qmirclientwindow.h
-# libxkbcommon
-!qtConfig(xkbcommon-system) {
- include(../../../3rdparty/xkbcommon.pri)
-} else {
- QMAKE_USE += xkbcommon
-}
+QMAKE_USE_PRIVATE += xkbcommon
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = MirServerIntegrationPlugin
diff --git a/src/plugins/platforms/wasm/wasm.pro b/src/plugins/platforms/wasm/wasm.pro
index f1205702ef..eaaba53aa2 100644
--- a/src/plugins/platforms/wasm/wasm.pro
+++ b/src/plugins/platforms/wasm/wasm.pro
@@ -1,4 +1,4 @@
-TARGET = wasm
+TARGET = qwasm
CONFIG += static plugin
QT += \
core-private gui-private \
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index 681b35eb7c..b629cc00a3 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -558,6 +558,10 @@ public:
SFGAOF attributes() const { return m_attributes; }
QString normalDisplay() const // base name, usually
{ return displayName(m_item, SIGDN_NORMALDISPLAY); }
+ QString urlString() const
+ { return displayName(m_item, SIGDN_URL); }
+ QString fileSysPath() const
+ { return displayName(m_item, SIGDN_FILESYSPATH); }
QString desktopAbsoluteParsing() const
{ return displayName(m_item, SIGDN_DESKTOPABSOLUTEPARSING); }
QString path() const; // Only set for 'FileSystem' (SFGAO_FILESYSTEM) items
@@ -734,7 +738,8 @@ void QWindowsShellItem::format(QDebug &d) const
if (canCopy())
d << " [copyable]";
d << ", normalDisplay=\"" << normalDisplay()
- << "\", desktopAbsoluteParsing=\"" << desktopAbsoluteParsing() << '"';
+ << "\", desktopAbsoluteParsing=\"" << desktopAbsoluteParsing()
+ << "\", urlString=\"" << urlString() << "\", fileSysPath=\"" << fileSysPath() << '"';
const QString pathS = path();
if (!pathS.isEmpty())
d << ", path=\"" << pathS << '"';
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 9e03d09607..cae1452885 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -312,7 +312,7 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co
case AllGLFunctionsQueryable:
return true;
case SwitchableWidgetComposition:
- return true;
+ return false; // QTBUG-68329 QTBUG-53515 QTBUG-54734
default:
return QPlatformIntegration::hasCapability(cap);
}
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index 9e6101b758..96abfdb9d7 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -1263,6 +1263,13 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
}
#endif // !QT_NO_SHORTCUT
key_recorder.storeKey(int(msg.wParam), a, state, text);
+
+ // QTBUG-71210
+ // VK_PACKET specifies multiple characters. The system only sends the first
+ // character of this sequence for each.
+ if (msg.wParam == VK_PACKET)
+ code = asciiToKeycode(char(uch.cell()), state);
+
QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyPress, code,
modifiers, scancode, quint32(msg.wParam), nModifiers, text, false);
result =true;
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
index b3bc6e6d7b..c94dc2d3df 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
@@ -632,6 +632,7 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et,
MSG msg, PVOID vPenInfo)
{
+#if QT_CONFIG(tabletevent)
if (et & QtWindows::NonClientEventFlag)
return false; // Let DefWindowProc() handle Non Client messages.
@@ -726,6 +727,14 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
}
}
return true;
+#else
+ Q_UNUSED(window);
+ Q_UNUSED(hwnd);
+ Q_UNUSED(et);
+ Q_UNUSED(msg);
+ Q_UNUSED(vPenInfo);
+ return false;
+#endif
}
// Process old-style mouse messages here.
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 741885e321..ddb8f45188 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
@@ -38,9 +38,6 @@
****************************************************************************/
#include <QDebug>
-#if QT_CONFIG(library)
-#include <QLibrary>
-#endif
#include "qxcbwindow.h"
#include "qxcbscreen.h"
@@ -51,6 +48,7 @@
#undef register
#include <GL/glx.h>
+#include <QtCore/QRegularExpression>
#include <QtGui/QOpenGLContext>
#include <QtGui/QOffscreenSurface>
@@ -60,10 +58,6 @@
#include "qxcbglintegration.h"
-#if !defined(QT_STATIC) && QT_CONFIG(dlopen)
-#include <dlfcn.h>
-#endif
-
QT_BEGIN_NAMESPACE
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
@@ -626,43 +620,7 @@ void QGLXContext::swapBuffers(QPlatformSurface *surface)
QFunctionPointer QGLXContext::getProcAddress(const char *procName)
{
-#ifdef QT_STATIC
- return glXGetProcAddressARB(reinterpret_cast<const GLubyte *>(procName));
-#else
- typedef void *(*qt_glXGetProcAddressARB)(const GLubyte *);
- static qt_glXGetProcAddressARB glXGetProcAddressARB = 0;
- static bool resolved = false;
-
- if (resolved && !glXGetProcAddressARB)
- return 0;
- if (!glXGetProcAddressARB) {
- QList<QByteArray> glxExt = QByteArray(glXGetClientString(m_display, GLX_EXTENSIONS)).split(' ');
- if (glxExt.contains("GLX_ARB_get_proc_address")) {
-#if QT_CONFIG(dlopen)
- void *handle = dlopen(NULL, RTLD_LAZY);
- if (handle) {
- glXGetProcAddressARB = (qt_glXGetProcAddressARB) dlsym(handle, "glXGetProcAddressARB");
- dlclose(handle);
- }
- if (!glXGetProcAddressARB)
-#endif
- {
-#if QT_CONFIG(library)
- extern const QString qt_gl_library_name();
-// QLibrary lib(qt_gl_library_name());
- QLibrary lib(QLatin1String("GL"));
- if (!lib.load())
- lib.setFileNameAndVersion(QLatin1String("GL"), 1);
- glXGetProcAddressARB = (qt_glXGetProcAddressARB) lib.resolve("glXGetProcAddressARB");
-#endif
- }
- }
- resolved = true;
- }
- if (!glXGetProcAddressARB)
- return 0;
- return (void (*)())glXGetProcAddressARB(reinterpret_cast<const GLubyte *>(procName));
-#endif
+ return glXGetProcAddress(reinterpret_cast<const GLubyte *>(procName));
}
QSurfaceFormat QGLXContext::format() const
@@ -692,32 +650,6 @@ static const char *qglx_threadedgl_blacklist_renderer[] = {
0
};
-// This disables threaded rendering on anything using mesa, e.g.
-// - nvidia/nouveau
-// - amd/gallium
-// - intel
-// - some software opengl implementations
-//
-// The client glx vendor string is used to identify those setups as that seems to show the least
-// variance between the bad configurations. It's always "Mesa Project and SGI". There are some
-// configurations which don't use mesa and which can do threaded rendering (amd and nvidia chips
-// with their own proprietary drivers).
-//
-// This, of course, is very broad and disables threaded rendering on a lot of devices which would
-// be able to use it. However, the bugs listed below don't follow any easily recognizable pattern
-// and we should rather be safe.
-//
-// http://cgit.freedesktop.org/xcb/libxcb/commit/?id=be0fe56c3bcad5124dcc6c47a2fad01acd16f71a will
-// fix some of the issues. Basically, the proprietary drivers seem to have a way of working around
-// a fundamental flaw with multithreaded access to xcb, but mesa doesn't. The blacklist should be
-// reevaluated once that patch is released in some version of xcb.
-static const char *qglx_threadedgl_blacklist_vendor[] = {
- "Mesa Project and SGI", // QTCREATORBUG-10875 (crash in creator)
- // QTBUG-34492 (flickering in fullscreen)
- // QTBUG-38221
- 0
-};
-
void QGLXContext::queryDummyContext()
{
if (m_queriedDummyContext)
@@ -777,18 +709,33 @@ void QGLXContext::queryDummyContext()
}
}
- if (glxvendor) {
- for (int i = 0; qglx_threadedgl_blacklist_vendor[i]; ++i) {
- if (strstr(glxvendor, qglx_threadedgl_blacklist_vendor[i]) != 0) {
- qCDebug(lcQpaGl).nospace() << "Multithreaded OpenGL disabled: "
- "blacklisted vendor \""
- << qglx_threadedgl_blacklist_vendor[i]
- << "\"";
+ if (glxvendor && m_supportsThreading) {
+ // 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) {
+ mesaVersionStr = (const char *) glGetString(GL_VERSION);
+ m_supportsThreading = false;
+ }
- m_supportsThreading = false;
- break;
+ if (mesaVersionStr) {
+ // The issue was fixed in Xcb 1.11, but we can't check for that
+ // at runtime, so instead assume it fixed with recent Mesa versions
+ // released several years after the Xcb fix.
+ QRegularExpression versionTest(QStringLiteral("Mesa (\\d+)"));
+ QRegularExpressionMatch result = versionTest.match(QString::fromLatin1(mesaVersionStr));
+ int versionNr = 0;
+ if (result.hasMatch())
+ versionNr = result.captured(1).toInt();
+ if (versionNr >= 17) {
+ // White-listed
+ m_supportsThreading = true;
}
}
+ if (!m_supportsThreading) {
+ qCDebug(lcQpaGl).nospace() << "Multithreaded OpenGL disabled: "
+ "blacklisted vendor \"Mesa Project\"";
+ }
}
context.doneCurrent();
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
index c8c806749f..ba9a3e68ee 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
@@ -837,6 +837,9 @@ void QXcbBackingStore::endPaint()
QImage QXcbBackingStore::toImage() const
{
+ // If the backingstore is rgbSwapped, return the internal image type here.
+ if (!m_rgbImage.isNull())
+ return m_rgbImage;
return m_image && m_image->image() ? *m_image->image() : QImage();
}
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp
index 3fd14a659e..bc92f82d5f 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp
@@ -153,114 +153,71 @@ private:
QByteArray format_atoms;
};
-namespace {
-class INCRTransaction;
-typedef QMap<xcb_window_t,INCRTransaction*> TransactionMap;
-static TransactionMap *transactions = 0;
+QXcbClipboardTransaction::QXcbClipboardTransaction(QXcbClipboard *clipboard, xcb_window_t w,
+ xcb_atom_t p, QByteArray d, xcb_atom_t t, int f)
+ : m_clipboard(clipboard), m_window(w), m_property(p), m_data(d), m_target(t), m_format(f)
+{
+ const quint32 values[] = { XCB_EVENT_MASK_PROPERTY_CHANGE };
+ xcb_change_window_attributes(m_clipboard->xcb_connection(), m_window,
+ XCB_CW_EVENT_MASK, values);
-//#define INCR_DEBUG
+ m_abortTimerId = startTimer(m_clipboard->clipboardTimeout());
+}
-class INCRTransaction : public QObject
+QXcbClipboardTransaction::~QXcbClipboardTransaction()
{
- Q_OBJECT
-public:
- INCRTransaction(QXcbConnection *c, xcb_window_t w, xcb_atom_t p,
- QByteArray d, uint i, xcb_atom_t t, int f, int to) :
- conn(c), win(w), property(p), data(d), increment(i),
- target(t), format(f), timeout(to), offset(0)
- {
- const quint32 values[] = { XCB_EVENT_MASK_PROPERTY_CHANGE };
- xcb_change_window_attributes(conn->xcb_connection(), win,
- XCB_CW_EVENT_MASK, values);
- if (!transactions) {
-#ifdef INCR_DEBUG
- qDebug("INCRTransaction: creating the TransactionMap");
-#endif
- transactions = new TransactionMap;
- conn->clipboard()->setProcessIncr(true);
- }
- transactions->insert(win, this);
- abort_timer = startTimer(timeout);
- }
+ if (m_abortTimerId)
+ killTimer(m_abortTimerId);
+ m_abortTimerId = 0;
+ m_clipboard->removeTransaction(m_window);
+}
- ~INCRTransaction()
- {
- if (abort_timer)
- killTimer(abort_timer);
- abort_timer = 0;
- transactions->remove(win);
- if (transactions->isEmpty()) {
-#ifdef INCR_DEBUG
- qDebug("INCRTransaction: no more INCR transactions left in the TransactionMap");
-#endif
- delete transactions;
- transactions = 0;
- conn->clipboard()->setProcessIncr(false);
- }
- }
+bool QXcbClipboardTransaction::updateIncrementalProperty(const xcb_property_notify_event_t *event)
+{
+ if (event->atom != m_property || event->state != XCB_PROPERTY_DELETE)
+ return false;
- void updateIncrProperty(xcb_property_notify_event_t *event, bool &accepted)
- {
- xcb_connection_t *c = conn->xcb_connection();
- if (event->atom == property && event->state == XCB_PROPERTY_DELETE) {
- accepted = true;
- // restart the timer
- if (abort_timer)
- killTimer(abort_timer);
- abort_timer = startTimer(timeout);
-
- unsigned int bytes_left = data.size() - offset;
- if (bytes_left > 0) {
- unsigned int bytes_to_send = qMin(increment, bytes_left);
-#ifdef INCR_DEBUG
- qDebug("INCRTransaction: sending %d bytes, %d remaining (INCR transaction %p)",
- bytes_to_send, bytes_left - bytes_to_send, this);
-#endif
- int dataSize = bytes_to_send / (format / 8);
- xcb_change_property(c, XCB_PROP_MODE_REPLACE, win, property,
- target, format, dataSize, data.constData() + offset);
- offset += bytes_to_send;
- } else {
-#ifdef INCR_DEBUG
- qDebug("INCRTransaction: INCR transaction %p completed", this);
-#endif
- xcb_change_property(c, XCB_PROP_MODE_REPLACE, win, property,
- target, format, 0, (const void *)0);
- const quint32 values[] = { XCB_EVENT_MASK_NO_EVENT };
- xcb_change_window_attributes(conn->xcb_connection(), win,
- XCB_CW_EVENT_MASK, values);
- // self destroy
- delete this;
- }
- }
- }
+ // restart the timer
+ if (m_abortTimerId)
+ killTimer(m_abortTimerId);
+ m_abortTimerId = startTimer(m_clipboard->clipboardTimeout());
-protected:
- void timerEvent(QTimerEvent *ev) override
- {
- if (ev->timerId() == abort_timer) {
- // this can happen when the X client we are sending data
- // to decides to exit (normally or abnormally)
-#ifdef INCR_DEBUG
- qDebug("INCRTransaction: Timed out while sending data to %p", this);
-#endif
- delete this;
- }
+ uint bytes_left = uint(m_data.size()) - m_offset;
+ if (bytes_left > 0) {
+ int increment = m_clipboard->increment();
+ uint bytes_to_send = qMin(uint(increment), bytes_left);
+
+ qCDebug(lcQpaClipboard, "sending %d bytes, %d remaining, transaction: %p)",
+ bytes_to_send, bytes_left - bytes_to_send, this);
+
+ uint32_t dataSize = bytes_to_send / (m_format / 8);
+ xcb_change_property(m_clipboard->xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
+ m_property, m_target, m_format, dataSize, m_data.constData() + m_offset);
+ m_offset += bytes_to_send;
+ } else {
+ qCDebug(lcQpaClipboard, "transaction %p completed", this);
+
+ xcb_change_property(m_clipboard->xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
+ m_property, m_target, m_format, 0, nullptr);
+
+ const quint32 values[] = { XCB_EVENT_MASK_NO_EVENT };
+ xcb_change_window_attributes(m_clipboard->xcb_connection(), m_window,
+ XCB_CW_EVENT_MASK, values);
+ delete this; // self destroy
}
+ return true;
+}
-private:
- QXcbConnection *conn;
- xcb_window_t win;
- xcb_atom_t property;
- QByteArray data;
- uint increment;
- xcb_atom_t target;
- int format;
- int timeout;
- uint offset;
- int abort_timer;
-};
-} // unnamed namespace
+
+void QXcbClipboardTransaction::timerEvent(QTimerEvent *ev)
+{
+ if (ev->timerId() == m_abortTimerId) {
+ // this can happen when the X client we are sending data
+ // to decides to exit (normally or abnormally)
+ qCDebug(lcQpaClipboard, "timed out while sending data to %p", this);
+ delete this; // self destroy
+ }
+}
const int QXcbClipboard::clipboard_timeout = 5000;
@@ -282,6 +239,9 @@ QXcbClipboard::QXcbClipboard(QXcbConnection *c)
xcb_xfixes_select_selection_input_checked(xcb_connection(), m_owner, XCB_ATOM_PRIMARY, mask);
xcb_xfixes_select_selection_input_checked(xcb_connection(), m_owner, atom(QXcbAtom::CLIPBOARD), mask);
}
+
+ // change property protocol request is 24 bytes
+ m_increment = (xcb_get_maximum_request_length(xcb_connection()) * 4) - 24;
}
QXcbClipboard::~QXcbClipboard()
@@ -301,7 +261,9 @@ QXcbClipboard::~QXcbClipboard()
connection()->sync();
// waiting until the clipboard manager fetches the content.
- if (!waitForClipboardEvent(m_owner, XCB_SELECTION_NOTIFY, true)) {
+ if (auto event = waitForClipboardEvent(m_owner, XCB_SELECTION_NOTIFY, true)) {
+ free(event);
+ } else {
qWarning("QXcbClipboard: Unable to receive an event from the "
"clipboard manager in a reasonable time");
}
@@ -313,16 +275,17 @@ QXcbClipboard::~QXcbClipboard()
delete m_clientClipboard[QClipboard::Selection];
}
-void QXcbClipboard::incrTransactionPeeker(xcb_generic_event_t *ge, bool &accepted)
+bool QXcbClipboard::handlePropertyNotify(const xcb_generic_event_t *event)
{
- uint response_type = ge->response_type & ~0x80;
- if (response_type == XCB_PROPERTY_NOTIFY) {
- xcb_property_notify_event_t *event = (xcb_property_notify_event_t *)ge;
- TransactionMap::Iterator it = transactions->find(event->window);
- if (it != transactions->end()) {
- (*it)->updateIncrProperty(event, accepted);
- }
- }
+ if (m_transactions.isEmpty() || event->response_type != XCB_PROPERTY_NOTIFY)
+ return false;
+
+ auto propertyNotify = reinterpret_cast<const xcb_property_notify_event_t *>(event);
+ TransactionMap::Iterator it = m_transactions.find(propertyNotify->window);
+ if (it == m_transactions.constEnd())
+ return false;
+
+ return (*it)->updateIncrementalProperty(propertyNotify);
}
xcb_window_t QXcbClipboard::getSelectionOwner(xcb_atom_t atom) const
@@ -522,19 +485,18 @@ xcb_atom_t QXcbClipboard::sendSelection(QMimeData *d, xcb_atom_t target, xcb_win
// This 'bool' can be removed once there is a proper fix for QTBUG-32853
if (m_clipboard_closing)
allow_incr = false;
- // X_ChangeProperty protocol request is 24 bytes
- const int increment = (xcb_get_maximum_request_length(xcb_connection()) * 4) - 24;
- if (data.size() > increment && allow_incr) {
+
+ if (data.size() > m_increment && allow_incr) {
long bytes = data.size();
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, window, property,
atom(QXcbAtom::INCR), 32, 1, (const void *)&bytes);
- new INCRTransaction(connection(), window, property, data, increment,
- atomFormat, dataFormat, clipboard_timeout);
+ auto transaction = new QXcbClipboardTransaction(this, window, property, data, atomFormat, dataFormat);
+ m_transactions.insert(window, transaction);
return property;
}
// make sure we can perform the XChangeProperty in a single request
- if (data.size() > increment)
+ if (data.size() > m_increment)
return XCB_NONE; // ### perhaps use several XChangeProperty calls w/ PropModeAppend?
int dataSize = data.size() / (dataFormat / 8);
// use a single request to transfer data
@@ -878,6 +840,7 @@ QByteArray QXcbClipboard::clipboardReadIncrementalProperty(xcb_window_t win, xcb
if (!ge)
break;
xcb_property_notify_event_t *event = (xcb_property_notify_event_t *)ge;
+ QScopedPointer<xcb_property_notify_event_t, QScopedPointerPodDeleter> guard(event);
if (event->atom != property
|| event->state != XCB_PROPERTY_NEW_VALUE
@@ -909,8 +872,6 @@ QByteArray QXcbClipboard::clipboardReadIncrementalProperty(xcb_window_t win, xcb
} else {
break;
}
-
- free(ge);
}
// timed out ... create a new requestor window, otherwise the requestor
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.h b/src/plugins/platforms/xcb/qxcbclipboard.h
index abab42a613..26d3b3b395 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.h
+++ b/src/plugins/platforms/xcb/qxcbclipboard.h
@@ -45,14 +45,41 @@
#include <xcb/xcb.h>
#include <xcb/xfixes.h>
+#include <QtCore/QObject>
+
QT_BEGIN_NAMESPACE
#ifndef QT_NO_CLIPBOARD
class QXcbConnection;
class QXcbScreen;
+class QXcbClipboard;
class QXcbClipboardMime;
+class QXcbClipboardTransaction : public QObject
+{
+ Q_OBJECT
+public:
+ QXcbClipboardTransaction(QXcbClipboard *clipboard, xcb_window_t w, xcb_atom_t p,
+ QByteArray d, xcb_atom_t t, int f);
+ ~QXcbClipboardTransaction();
+
+ bool updateIncrementalProperty(const xcb_property_notify_event_t *event);
+
+protected:
+ void timerEvent(QTimerEvent *ev) override;
+
+private:
+ QXcbClipboard *m_clipboard;
+ xcb_window_t m_window;
+ xcb_atom_t m_property;
+ QByteArray m_data;
+ xcb_atom_t m_target;
+ uint8_t m_format;
+ uint m_offset = 0;
+ int m_abortTimerId = 0;
+};
+
class QXcbClipboard : public QXcbObject, public QPlatformClipboard
{
public:
@@ -81,13 +108,16 @@ public:
QByteArray getDataInFormat(xcb_atom_t modeAtom, xcb_atom_t fmtatom);
- void setProcessIncr(bool process) { m_incr_active = process; }
- bool processIncr() { return m_incr_active; }
- void incrTransactionPeeker(xcb_generic_event_t *ge, bool &accepted);
+ bool handlePropertyNotify(const xcb_generic_event_t *event);
xcb_window_t getSelectionOwner(xcb_atom_t atom) const;
QByteArray getSelection(xcb_atom_t selection, xcb_atom_t target, xcb_atom_t property, xcb_timestamp_t t = 0);
+ int increment() const { return m_increment; }
+ int clipboardTimeout() const { return clipboard_timeout; }
+
+ void removeTransaction(xcb_window_t window) { m_transactions.remove(window); }
+
private:
xcb_generic_event_t *waitForClipboardEvent(xcb_window_t window, int type, bool checkManager = false);
@@ -107,9 +137,12 @@ private:
static const int clipboard_timeout;
- bool m_incr_active = false;
+ int m_increment = 0;
bool m_clipboard_closing = false;
xcb_timestamp_t m_incr_receive_time = 0;
+
+ using TransactionMap = QMap<xcb_window_t, QXcbClipboardTransaction *>;
+ TransactionMap m_transactions;
};
#endif // QT_NO_CLIPBOARD
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 45f096a13a..37ee980924 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -84,6 +84,7 @@ Q_LOGGING_CATEGORY(lcQpaEvents, "qt.qpa.events")
Q_LOGGING_CATEGORY(lcQpaEventReader, "qt.qpa.events.reader")
Q_LOGGING_CATEGORY(lcQpaPeeker, "qt.qpa.peeker")
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,
@@ -651,6 +652,10 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
break;
case XCB_PROPERTY_NOTIFY:
{
+#ifndef QT_NO_CLIPBOARD
+ if (m_clipboard->handlePropertyNotify(event))
+ break;
+#endif
auto propertyNotify = reinterpret_cast<xcb_property_notify_event_t *>(event);
if (propertyNotify->atom == atom(QXcbAtom::_NET_WORKAREA)) {
QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(propertyNotify->window);
@@ -1010,14 +1015,6 @@ void QXcbConnection::processXcbEvents(QEventLoop::ProcessEventsFlags flags)
if (compressEvent(event))
continue;
-#ifndef QT_NO_CLIPBOARD
- bool accepted = false;
- if (clipboard()->processIncr())
- clipboard()->incrTransactionPeeker(event, accepted);
- if (accepted)
- continue;
-#endif
-
auto isWaitingFor = [=](PeekFunc peekFunc) {
// These callbacks return true if the event is what they were
// waiting for, remove them from the list in that case.
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 5d53b97d37..47036ca257 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -68,6 +68,7 @@ Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen)
Q_DECLARE_LOGGING_CATEGORY(lcQpaEvents)
Q_DECLARE_LOGGING_CATEGORY(lcQpaPeeker)
Q_DECLARE_LOGGING_CATEGORY(lcQpaKeyboard)
+Q_DECLARE_LOGGING_CATEGORY(lcQpaClipboard)
Q_DECLARE_LOGGING_CATEGORY(lcQpaXDnd)
Q_DECLARE_LOGGING_CATEGORY(lcQpaEventReader)
diff --git a/src/plugins/platforms/xcb/qxcbconnection_screens.cpp b/src/plugins/platforms/xcb/qxcbconnection_screens.cpp
index fe9e0be86d..9aba996bb9 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_screens.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_screens.cpp
@@ -384,7 +384,7 @@ void QXcbConnection::initializeScreens()
}
siblings << screen;
}
- virtualDesktop->setScreens(siblings);
+ virtualDesktop->setScreens(std::move(siblings));
xcb_screen_next(&it);
++xcbScreenNumber;
} // for each xcb screen
diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp
index 57629ac03a..7831671d42 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.cpp
+++ b/src/plugins/platforms/xcb/qxcbcursor.cpp
@@ -255,6 +255,7 @@ static const uint8_t * const cursor_bits20[] = {
forbidden_bits, forbiddenm_bits
};
+// ### FIXME This mapping is incomplete - QTBUG-71423
static const std::vector<const char *> cursorNames[] = {
{ "left_ptr", "default", "top_left_arrow", "left_arrow" },
{ "up_arrow" },
@@ -273,7 +274,7 @@ static const std::vector<const char *> cursorNames[] = {
{ "forbidden", "not-allowed", "crossed_circle", "circle", "03b6e0fcb3499374a867c041f52298f0" },
{ "whats_this", "help", "question_arrow", "5c6cd98b3f3ebcb1f9c7f1c204630408", "d9ce0ab605698f320427677b458ad60b" },
{ "left_ptr_watch", "half-busy", "progress", "00000000000000020006000e7e9ffc3f", "08e8e1c95fe2fc01f976f1e063a24ccd" },
- { "openhand", "fleur", "5aca4d189052212118709018842178c0", "9d800788f1b08800ae810202380a0822" },
+ { "openhand", "grab", "fleur", "5aca4d189052212118709018842178c0", "9d800788f1b08800ae810202380a0822" },
{ "closedhand", "grabbing", "208530c400c041818281048008011002" },
{ "dnd-copy", "copy" },
{ "dnd-move", "move" },
diff --git a/src/plugins/platforms/xcb/qxcbeventdispatcher.h b/src/plugins/platforms/xcb/qxcbeventdispatcher.h
index 6aadd63a70..ddf448cf87 100644
--- a/src/plugins/platforms/xcb/qxcbeventdispatcher.h
+++ b/src/plugins/platforms/xcb/qxcbeventdispatcher.h
@@ -107,9 +107,6 @@ class QXcbEventDispatcher
{
public:
static QAbstractEventDispatcher *createEventDispatcher(QXcbConnection *connection);
-
-private:
- QXcbConnection *m_connection;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbeventqueue.cpp b/src/plugins/platforms/xcb/qxcbeventqueue.cpp
index 862f68764b..f6158d3127 100644
--- a/src/plugins/platforms/xcb/qxcbeventqueue.cpp
+++ b/src/plugins/platforms/xcb/qxcbeventqueue.cpp
@@ -105,7 +105,8 @@ QXcbEventQueue::~QXcbEventQueue()
wait();
}
- while (xcb_generic_event_t *event = takeFirst())
+ flushBufferedEvents();
+ while (xcb_generic_event_t *event = takeFirst(QEventLoop::AllEvents))
free(event);
if (m_head && m_head->fromHeap)
@@ -219,6 +220,8 @@ void QXcbEventQueue::run()
tail->next = qXcbEventNodeFactory(event);
tail = tail->next;
m_tail.store(tail, std::memory_order_release);
+ } else {
+ free(event);
}
};
diff --git a/src/plugins/platforms/xcb/qxcbmime.cpp b/src/plugins/platforms/xcb/qxcbmime.cpp
index 7170d259fd..d611f86a9c 100644
--- a/src/plugins/platforms/xcb/qxcbmime.cpp
+++ b/src/plugins/platforms/xcb/qxcbmime.cpp
@@ -168,7 +168,7 @@ QVariant QXcbMime::mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a,
if (!encoding.isEmpty()
&& atomName == format + QLatin1String(";charset=") + QLatin1String(encoding)) {
-#ifndef QT_NO_TEXTCODEC
+#if QT_CONFIG(textcodec)
if (requestedType == QVariant::String) {
QTextCodec *codec = QTextCodec::codecForName(encoding);
if (codec)
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index 7f22a8e4db..be6c45e415 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -79,7 +79,7 @@ public:
QXcbScreen *screenAt(const QPoint &pos) const;
QList<QPlatformScreen *> screens() const { return m_screens; }
- void setScreens(QList<QPlatformScreen *> sl) { m_screens = sl; }
+ void setScreens(QList<QPlatformScreen *> &&sl) { m_screens = std::move(sl); }
void removeScreen(QPlatformScreen *s) { m_screens.removeOne(s); }
void addScreen(QPlatformScreen *s);
void setPrimaryScreen(QPlatformScreen *s);
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 70aab77a51..3bfcbf2adb 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -64,38 +64,13 @@
#include <algorithm>
-// FIXME This workaround can be removed for xcb-icccm > 3.8
-#define class class_name
#include <xcb/xcb_icccm.h>
-#undef class
#include <xcb/xfixes.h>
#include <xcb/shape.h>
#if QT_CONFIG(xcb_xinput)
#include <xcb/xinput.h>
#endif
-// xcb-icccm 3.8 support
-#ifdef XCB_ICCCM_NUM_WM_SIZE_HINTS_ELEMENTS
-#define xcb_get_wm_hints_reply xcb_icccm_get_wm_hints_reply
-#define xcb_get_wm_hints xcb_icccm_get_wm_hints
-#define xcb_get_wm_hints_unchecked xcb_icccm_get_wm_hints_unchecked
-#define xcb_set_wm_hints xcb_icccm_set_wm_hints
-#define xcb_set_wm_normal_hints xcb_icccm_set_wm_normal_hints
-#define xcb_size_hints_set_base_size xcb_icccm_size_hints_set_base_size
-#define xcb_size_hints_set_max_size xcb_icccm_size_hints_set_max_size
-#define xcb_size_hints_set_min_size xcb_icccm_size_hints_set_min_size
-#define xcb_size_hints_set_position xcb_icccm_size_hints_set_position
-#define xcb_size_hints_set_resize_inc xcb_icccm_size_hints_set_resize_inc
-#define xcb_size_hints_set_size xcb_icccm_size_hints_set_size
-#define xcb_size_hints_set_win_gravity xcb_icccm_size_hints_set_win_gravity
-#define xcb_wm_hints_set_iconic xcb_icccm_wm_hints_set_iconic
-#define xcb_wm_hints_set_normal xcb_icccm_wm_hints_set_normal
-#define xcb_wm_hints_set_input xcb_icccm_wm_hints_set_input
-#define xcb_wm_hints_t xcb_icccm_wm_hints_t
-#define XCB_WM_STATE_ICONIC XCB_ICCCM_WM_STATE_ICONIC
-#define XCB_WM_STATE_WITHDRAWN XCB_ICCCM_WM_STATE_WITHDRAWN
-#endif
-
#include <private/qguiapplication_p.h>
#include <private/qwindow_p.h>
@@ -497,11 +472,13 @@ void QXcbWindow::create()
clientMachine.size(), clientMachine.constData());
}
- // Create WM_HINTS property on the window, so we can xcb_get_wm_hints*()
+ // Create WM_HINTS property on the window, so we can xcb_icccm_get_wm_hints*()
// from various setter functions for adjusting the hints.
- xcb_wm_hints_t hints;
+ xcb_icccm_wm_hints_t hints;
memset(&hints, 0, sizeof(hints));
- xcb_set_wm_hints(xcb_connection(), m_window, &hints);
+ hints.flags = XCB_ICCCM_WM_HINT_WINDOW_GROUP;
+ hints.window_group = connection()->clientLeader();
+ xcb_icccm_set_wm_hints(xcb_connection(), m_window, &hints);
xcb_window_t leader = connection()->clientLeader();
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
@@ -755,7 +732,7 @@ void QXcbWindow::show()
xcb_delete_property(xcb_connection(), m_window, XCB_ATOM_WM_TRANSIENT_FOR);
// update _NET_WM_STATE
- updateNetWmStateBeforeMap();
+ setNetWmStateOnUnmappedWindow();
}
// QWidget-attribute Qt::WA_ShowWithoutActivating.
@@ -963,46 +940,6 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates()
return result;
}
-void QXcbWindow::setNetWmStates(NetWmStates states)
-{
- QVector<xcb_atom_t> atoms;
-
- auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(),
- 0, m_window, atom(QXcbAtom::_NET_WM_STATE),
- XCB_ATOM_ATOM, 0, 1024);
- if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM && reply->value_len > 0) {
- const xcb_atom_t *data = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply.get()));
- atoms.resize(reply->value_len);
- memcpy((void *)&atoms.first(), (void *)data, reply->value_len * sizeof(xcb_atom_t));
- }
-
- if (states & NetWmStateAbove && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_ABOVE)))
- atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_ABOVE));
- if (states & NetWmStateBelow && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_BELOW)))
- atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_BELOW));
- if (states & NetWmStateFullScreen && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)))
- atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
- if (states & NetWmStateMaximizedHorz && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ)))
- atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ));
- if (states & NetWmStateMaximizedVert && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT)))
- atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
- if (states & NetWmStateModal && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MODAL)))
- atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MODAL));
- if (states & NetWmStateStaysOnTop && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP)))
- atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP));
- if (states & NetWmStateDemandsAttention && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION)))
- atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION));
-
- if (atoms.isEmpty()) {
- xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_STATE));
- } else {
- xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
- atom(QXcbAtom::_NET_WM_STATE), XCB_ATOM_ATOM, 32,
- atoms.count(), atoms.constData());
- }
- xcb_flush(xcb_connection());
-}
-
void QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
{
Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
@@ -1029,7 +966,7 @@ void QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
}
setWmWindowType(wmWindowTypes, flags);
- setNetWmStateWindowFlags(flags);
+ setNetWmState(flags);
setMotifWmHints(flags);
setTransparentForMouseEvents(flags & Qt::WindowTransparentForInput);
@@ -1113,7 +1050,7 @@ void QXcbWindow::setMotifWmHints(Qt::WindowFlags flags)
}
}
-void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two)
+void QXcbWindow::setNetWmState(bool set, xcb_atom_t one, xcb_atom_t two)
{
xcb_client_message_event_t event;
@@ -1133,6 +1070,96 @@ void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two)
(const char *)&event);
}
+void QXcbWindow::setNetWmState(Qt::WindowStates state)
+{
+ if ((m_windowState ^ state) & Qt::WindowMaximized) {
+ setNetWmState(state & Qt::WindowMaximized,
+ atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ),
+ atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
+ }
+
+ if ((m_windowState ^ state) & Qt::WindowFullScreen)
+ setNetWmState(state & Qt::WindowFullScreen, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
+}
+
+void QXcbWindow::setNetWmState(Qt::WindowFlags flags)
+{
+ setNetWmState(flags & Qt::WindowStaysOnTopHint,
+ atom(QXcbAtom::_NET_WM_STATE_ABOVE),
+ atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP));
+ setNetWmState(flags & Qt::WindowStaysOnBottomHint, atom(QXcbAtom::_NET_WM_STATE_BELOW));
+}
+
+void QXcbWindow::setNetWmStateOnUnmappedWindow()
+{
+ if (Q_UNLIKELY(m_mapped))
+ qCWarning(lcQpaXcb()) << "internal error: " << Q_FUNC_INFO << "called on mapped window";
+
+ NetWmStates states(0);
+ const Qt::WindowFlags flags = window()->flags();
+ if (flags & Qt::WindowStaysOnTopHint) {
+ states |= NetWmStateAbove;
+ states |= NetWmStateStaysOnTop;
+ } else if (flags & Qt::WindowStaysOnBottomHint) {
+ states |= NetWmStateBelow;
+ }
+
+ if (window()->windowStates() & Qt::WindowFullScreen)
+ states |= NetWmStateFullScreen;
+
+ if (window()->windowStates() & Qt::WindowMaximized) {
+ states |= NetWmStateMaximizedHorz;
+ states |= NetWmStateMaximizedVert;
+ }
+
+ if (window()->modality() != Qt::NonModal)
+ states |= NetWmStateModal;
+
+ // According to EWMH:
+ // "The Window Manager should remove _NET_WM_STATE whenever a window is withdrawn".
+ // Which means that we don't have to read this property before changing it on a withdrawn
+ // window. But there are situations where users want to adjust this property as well
+ // (e4cea305ed2ba3c9f580bf9d16c59a1048af0e8a), so instead of overwriting the property
+ // we first read it and then merge our hints with the existing values, allowing a user
+ // to set custom hints.
+
+ QVector<xcb_atom_t> atoms;
+ auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(),
+ 0, m_window, atom(QXcbAtom::_NET_WM_STATE),
+ XCB_ATOM_ATOM, 0, 1024);
+ if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM && reply->value_len > 0) {
+ const xcb_atom_t *data = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply.get()));
+ atoms.resize(reply->value_len);
+ memcpy((void *)&atoms.first(), (void *)data, reply->value_len * sizeof(xcb_atom_t));
+ }
+
+ if (states & NetWmStateAbove && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_ABOVE)))
+ atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_ABOVE));
+ if (states & NetWmStateBelow && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_BELOW)))
+ atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_BELOW));
+ if (states & NetWmStateFullScreen && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)))
+ atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
+ if (states & NetWmStateMaximizedHorz && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ)))
+ atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ));
+ if (states & NetWmStateMaximizedVert && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT)))
+ atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
+ if (states & NetWmStateModal && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MODAL)))
+ atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MODAL));
+ if (states & NetWmStateStaysOnTop && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP)))
+ atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP));
+ if (states & NetWmStateDemandsAttention && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION)))
+ atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION));
+
+ if (atoms.isEmpty()) {
+ xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_STATE));
+ } else {
+ xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
+ atom(QXcbAtom::_NET_WM_STATE), XCB_ATOM_ATOM, 32,
+ atoms.count(), atoms.constData());
+ }
+ xcb_flush(xcb_connection());
+}
+
void QXcbWindow::setWindowState(Qt::WindowStates state)
{
if (state == m_windowState)
@@ -1148,7 +1175,7 @@ void QXcbWindow::setWindowState(Qt::WindowStates state)
event.sequence = 0;
event.window = m_window;
event.type = atom(QXcbAtom::WM_CHANGE_STATE);
- event.data.data32[0] = XCB_WM_STATE_ICONIC;
+ event.data.data32[0] = XCB_ICCCM_WM_STATE_ICONIC;
event.data.data32[1] = 0;
event.data.data32[2] = 0;
event.data.data32[3] = 0;
@@ -1160,64 +1187,22 @@ void QXcbWindow::setWindowState(Qt::WindowStates state)
m_minimized = true;
}
- if ((m_windowState ^ state) & Qt::WindowMaximized) {
- changeNetWmState(state & Qt::WindowMaximized, atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ),
- atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
- }
-
- if ((m_windowState ^ state) & Qt::WindowFullScreen) {
- changeNetWmState(state & Qt::WindowFullScreen, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
- }
+ setNetWmState(state);
- xcb_get_property_cookie_t cookie = xcb_get_wm_hints_unchecked(xcb_connection(), m_window);
- xcb_wm_hints_t hints;
- if (xcb_get_wm_hints_reply(xcb_connection(), cookie, &hints, nullptr)) {
+ xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_hints_unchecked(xcb_connection(), m_window);
+ xcb_icccm_wm_hints_t hints;
+ if (xcb_icccm_get_wm_hints_reply(xcb_connection(), cookie, &hints, nullptr)) {
if (state & Qt::WindowMinimized)
- xcb_wm_hints_set_iconic(&hints);
+ xcb_icccm_wm_hints_set_iconic(&hints);
else
- xcb_wm_hints_set_normal(&hints);
- xcb_set_wm_hints(xcb_connection(), m_window, &hints);
+ xcb_icccm_wm_hints_set_normal(&hints);
+ xcb_icccm_set_wm_hints(xcb_connection(), m_window, &hints);
}
connection()->sync();
m_windowState = state;
}
-void QXcbWindow::updateNetWmStateBeforeMap()
-{
- NetWmStates states(0);
-
- const Qt::WindowFlags flags = window()->flags();
- if (flags & Qt::WindowStaysOnTopHint) {
- states |= NetWmStateAbove;
- states |= NetWmStateStaysOnTop;
- } else if (flags & Qt::WindowStaysOnBottomHint) {
- states |= NetWmStateBelow;
- }
-
- if (window()->windowStates() & Qt::WindowFullScreen)
- states |= NetWmStateFullScreen;
-
- if (window()->windowStates() & Qt::WindowMaximized) {
- states |= NetWmStateMaximizedHorz;
- states |= NetWmStateMaximizedVert;
- }
-
- if (window()->modality() != Qt::NonModal)
- states |= NetWmStateModal;
-
- setNetWmStates(states);
-}
-
-void QXcbWindow::setNetWmStateWindowFlags(Qt::WindowFlags flags)
-{
- changeNetWmState(flags & Qt::WindowStaysOnTopHint,
- atom(QXcbAtom::_NET_WM_STATE_ABOVE),
- atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP));
- changeNetWmState(flags & Qt::WindowStaysOnBottomHint,
- atom(QXcbAtom::_NET_WM_STATE_BELOW));
-}
-
void QXcbWindow::updateNetWmUserTime(xcb_timestamp_t timestamp)
{
xcb_window_t wid = m_window;
@@ -1292,14 +1277,14 @@ void QXcbWindow::setTransparentForMouseEvents(bool transparent)
void QXcbWindow::updateDoesNotAcceptFocus(bool doesNotAcceptFocus)
{
- xcb_get_property_cookie_t cookie = xcb_get_wm_hints_unchecked(xcb_connection(), m_window);
+ xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_hints_unchecked(xcb_connection(), m_window);
- xcb_wm_hints_t hints;
- if (!xcb_get_wm_hints_reply(xcb_connection(), cookie, &hints, nullptr))
+ xcb_icccm_wm_hints_t hints;
+ if (!xcb_icccm_get_wm_hints_reply(xcb_connection(), cookie, &hints, nullptr))
return;
- xcb_wm_hints_set_input(&hints, !doesNotAcceptFocus);
- xcb_set_wm_hints(xcb_connection(), m_window, &hints);
+ xcb_icccm_wm_hints_set_input(&hints, !doesNotAcceptFocus);
+ xcb_icccm_set_wm_hints(xcb_connection(), m_window, &hints);
}
WId QXcbWindow::winId() const
@@ -1407,9 +1392,9 @@ void QXcbWindow::propagateSizeHints()
QWindowPrivate *win = qt_window_private(window());
if (!win->positionAutomatic)
- xcb_size_hints_set_position(&hints, true, rect.x(), rect.y());
+ xcb_icccm_size_hints_set_position(&hints, true, rect.x(), rect.y());
if (rect.width() < QWINDOWSIZE_MAX || rect.height() < QWINDOWSIZE_MAX)
- xcb_size_hints_set_size(&hints, true, rect.width(), rect.height());
+ xcb_icccm_size_hints_set_size(&hints, true, rect.width(), rect.height());
/* Gravity describes how to interpret x and y values the next time
window needs to be positioned on a screen.
@@ -1418,7 +1403,7 @@ void QXcbWindow::propagateSizeHints()
auto gravity = win->positionPolicy == QWindowPrivate::WindowFrameInclusive
? XCB_GRAVITY_NORTH_WEST : XCB_GRAVITY_STATIC;
- xcb_size_hints_set_win_gravity(&hints, gravity);
+ xcb_icccm_size_hints_set_win_gravity(&hints, gravity);
QSize minimumSize = windowMinimumSize();
QSize maximumSize = windowMaximumSize();
@@ -1426,21 +1411,21 @@ void QXcbWindow::propagateSizeHints()
QSize sizeIncrement = windowSizeIncrement();
if (minimumSize.width() > 0 || minimumSize.height() > 0)
- xcb_size_hints_set_min_size(&hints,
- qMin(XCOORD_MAX,minimumSize.width()),
- qMin(XCOORD_MAX,minimumSize.height()));
+ xcb_icccm_size_hints_set_min_size(&hints,
+ qMin(XCOORD_MAX,minimumSize.width()),
+ qMin(XCOORD_MAX,minimumSize.height()));
if (maximumSize.width() < QWINDOWSIZE_MAX || maximumSize.height() < QWINDOWSIZE_MAX)
- xcb_size_hints_set_max_size(&hints,
- qMin(XCOORD_MAX, maximumSize.width()),
- qMin(XCOORD_MAX, maximumSize.height()));
+ xcb_icccm_size_hints_set_max_size(&hints,
+ qMin(XCOORD_MAX, maximumSize.width()),
+ qMin(XCOORD_MAX, maximumSize.height()));
if (sizeIncrement.width() > 0 || sizeIncrement.height() > 0) {
- xcb_size_hints_set_base_size(&hints, baseSize.width(), baseSize.height());
- xcb_size_hints_set_resize_inc(&hints, sizeIncrement.width(), sizeIncrement.height());
+ xcb_icccm_size_hints_set_base_size(&hints, baseSize.width(), baseSize.height());
+ xcb_icccm_size_hints_set_resize_inc(&hints, sizeIncrement.width(), sizeIncrement.height());
}
- xcb_set_wm_normal_hints(xcb_connection(), m_window, &hints);
+ xcb_icccm_set_wm_normal_hints(xcb_connection(), m_window, &hints);
}
void QXcbWindow::requestActivateWindow()
@@ -2247,8 +2232,8 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
if (reply && reply->format == 32 && reply->type == atom(QXcbAtom::WM_STATE)) {
const quint32 *data = (const quint32 *)xcb_get_property_value(reply.get());
if (reply->length != 0)
- m_minimized = (data[0] == XCB_WM_STATE_ICONIC
- || (data[0] == XCB_WM_STATE_WITHDRAWN && m_minimized));
+ m_minimized = (data[0] == XCB_ICCCM_WM_STATE_ICONIC
+ || (data[0] == XCB_ICCCM_WM_STATE_WITHDRAWN && m_minimized));
}
}
if (m_minimized)
@@ -2590,7 +2575,7 @@ void QXcbWindow::setAlertState(bool enabled)
m_alertState = enabled;
- changeNetWmState(enabled, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION));
+ setNetWmState(enabled, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION));
}
uint QXcbWindow::visualId() const
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index 6667f45343..f98cd8a74d 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -193,21 +193,19 @@ protected:
void setImageFormatForVisual(const xcb_visualtype_t *visual);
QXcbScreen *parentScreen();
-
QXcbScreen *initialScreen() const;
- void changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two = 0);
+
+ void setNetWmState(bool set, xcb_atom_t one, xcb_atom_t two = 0);
+ void setNetWmState(Qt::WindowFlags flags);
+ void setNetWmState(Qt::WindowStates state);
+ void setNetWmStateOnUnmappedWindow();
NetWmStates netWmStates();
- void setNetWmStates(NetWmStates);
void setMotifWmHints(Qt::WindowFlags flags);
- void setNetWmStateWindowFlags(Qt::WindowFlags flags);
- void updateNetWmStateBeforeMap();
-
void setTransparentForMouseEvents(bool transparent);
void updateDoesNotAcceptFocus(bool doesNotAcceptFocus);
- QRect windowToWmGeometry(QRect r) const;
void sendXEmbedMessage(xcb_window_t window, quint32 message,
quint32 detail = 0, quint32 data1 = 0, quint32 data2 = 0);
void handleXEmbedMessage(const xcb_client_message_event_t *event);
diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
index c65b145fb6..9883617ab6 100644
--- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro
+++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
@@ -97,21 +97,15 @@ qtConfig(vulkan) {
!qtConfig(system-xcb) {
QMAKE_USE += xcb-static xcb
} else {
- qtConfig(xkb): QMAKE_USE += xcb_xkb
qtConfig(xcb-render): QMAKE_USE += xcb_render
qtConfig(xcb-xinput): QMAKE_USE += xcb_xinput
QMAKE_USE += xcb_syslibs
}
-# libxkbcommon
-!qtConfig(xkbcommon-system) {
- qtConfig(xkb) {
- include(../../../3rdparty/xkbcommon-x11.pri)
- } else {
- include(../../../3rdparty/xkbcommon.pri)
- }
-} else {
- QMAKE_USE += xkbcommon
+QMAKE_USE += xkbcommon
+qtConfig(xkb) {
+ QMAKE_USE += xkbcommon_x11
+ qtConfig(system-xcb): QMAKE_USE += xcb_xkb
}
qtConfig(dlopen): QMAKE_USE += libdl
diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp
index cda267d24b..5e94d1558e 100644
--- a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp
+++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp
@@ -181,10 +181,10 @@ void QXdgDesktopPortalFileDialog::openPortal()
if (d->saveFile) {
if (!d->directory.isEmpty())
- options.insert(QLatin1String("current_folder"), d->directory.toLatin1());
+ options.insert(QLatin1String("current_folder"), d->directory.toLatin1().append('\0'));
if (!d->selectedFiles.isEmpty())
- options.insert(QLatin1String("current_file"), d->selectedFiles.first().toLatin1());
+ options.insert(QLatin1String("current_file"), d->selectedFiles.first().toLatin1().append('\0'));
}
// Insert filters
diff --git a/src/plugins/printsupport/cups/qcupsprintersupport.cpp b/src/plugins/printsupport/cups/qcupsprintersupport.cpp
index 19e1df31f6..42a7a821f2 100644
--- a/src/plugins/printsupport/cups/qcupsprintersupport.cpp
+++ b/src/plugins/printsupport/cups/qcupsprintersupport.cpp
@@ -175,6 +175,11 @@ QStringList QCupsPrinterSupport::availablePrintDeviceIds() const
QString QCupsPrinterSupport::defaultPrintDeviceId() const
{
+ return staticDefaultPrintDeviceId();
+}
+
+QString QCupsPrinterSupport::staticDefaultPrintDeviceId()
+{
QString printerId;
cups_dest_t *dests;
int count = cupsGetDests(&dests);
diff --git a/src/plugins/printsupport/cups/qcupsprintersupport_p.h b/src/plugins/printsupport/cups/qcupsprintersupport_p.h
index 42de28aec0..c2b4895c7f 100644
--- a/src/plugins/printsupport/cups/qcupsprintersupport_p.h
+++ b/src/plugins/printsupport/cups/qcupsprintersupport_p.h
@@ -71,6 +71,8 @@ public:
QStringList availablePrintDeviceIds() const override;
QString defaultPrintDeviceId() const override;
+ static QString staticDefaultPrintDeviceId();
+
private:
QString cupsOption(int i, const QString &key) const;
};
diff --git a/src/plugins/printsupport/cups/qppdprintdevice.cpp b/src/plugins/printsupport/cups/qppdprintdevice.cpp
index 51b93a0016..ea6336c4d1 100644
--- a/src/plugins/printsupport/cups/qppdprintdevice.cpp
+++ b/src/plugins/printsupport/cups/qppdprintdevice.cpp
@@ -39,6 +39,8 @@
#include "qppdprintdevice.h"
+#include "qcupsprintersupport_p.h"
+
#include <QtCore/QMimeDatabase>
#include <qdebug.h>
@@ -118,7 +120,12 @@ bool QPpdPrintDevice::isValid() const
bool QPpdPrintDevice::isDefault() const
{
- return printerTypeFlags() & CUPS_PRINTER_DEFAULT;
+ // There seems to be a bug in cups in which printerTypeFlags
+ // returns CUPS_PRINTER_DEFAULT based only on system values, ignoring user lpoptions
+ // so we can't use that. And also there seems to be a bug in which dests returned
+ // by cupsGetNamedDest don't have is_default set at all so we can't use that either
+ // so go the long route and compare our id against the defaultPrintDeviceId
+ return id() == QCupsPrinterSupport::staticDefaultPrintDeviceId();
}
QPrint::DeviceState QPpdPrintDevice::state() const
diff --git a/src/plugins/sqldrivers/configure.pri b/src/plugins/sqldrivers/configure.pri
index 24954e9514..747a47e7b8 100644
--- a/src/plugins/sqldrivers/configure.pri
+++ b/src/plugins/sqldrivers/configure.pri
@@ -1,29 +1,16 @@
# custom tests
-defineReplace(filterLibraryPath) {
- str = $${1}
- for (l, QMAKE_DEFAULT_LIBDIRS): \
- str -= "-L$$l"
-
- return($$str)
-}
-
defineTest(qtConfLibrary_psqlConfig) {
pg_config = $$config.input.psql_config
isEmpty(pg_config): \
pg_config = $$qtConfFindInPath("pg_config")
!win32:!isEmpty(pg_config) {
qtRunLoggedCommand("$$pg_config --libdir", libdir)|return(false)
+ !qtConfResolvePathLibs($${1}.libs, $$libdir, -lpq): \
+ return(false)
qtRunLoggedCommand("$$pg_config --includedir", includedir)|return(false)
- libdir -= $$QMAKE_DEFAULT_LIBDIRS
- libs =
- !isEmpty(libdir): libs += "-L$$libdir"
- libs += "-lpq"
- $${1}.libs = $$libs
- includedir -= $$QMAKE_DEFAULT_INCDIRS
- $${1}.includedir = $$includedir
- export($${1}.libs)
- export($${1}.includedir)
+ !qtConfResolvePathIncs($${1}.includedir, $$includedir): \
+ return(false)
return(true)
}
qtLog("pg_config not found.")
@@ -34,8 +21,9 @@ defineTest(qtConfLibrary_psqlEnv) {
# Respect PSQL_LIBS if set
PSQL_LIBS = $$getenv(PSQL_LIBS)
!isEmpty(PSQL_LIBS) {
- eval($${1}.libs = $$PSQL_LIBS)
- export($${1}.libs)
+ eval(libs = $$PSQL_LIBS)
+ !qtConfResolveLibs($${1}.libs, $$libs): \
+ return(false)
} else {
!qtConfLibrary_inline($$1, $$2): \
return(false)
@@ -58,7 +46,6 @@ defineTest(qtConfLibrary_mysqlConfig) {
qtRunLoggedCommand("$$mysql_config $$query", libs)|return(false)
qtRunLoggedCommand("$$mysql_config --include", includedir)|return(false)
eval(libs = $$libs)
- libs = $$filterLibraryPath($$libs)
# -rdynamic should not be returned by mysql_config, but is on RHEL 6.6
libs -= -rdynamic
equals($${1}.cleanlibs, true) {
@@ -69,16 +56,15 @@ defineTest(qtConfLibrary_mysqlConfig) {
}
libs = $$cleanlibs
}
- $${1}.libs = $$libs
+ !qtConfResolveLibs($${1}.libs, $$libs): \
+ return(false)
eval(rawincludedir = $$includedir)
rawincludedir ~= s/^-I//g
includedir =
for (id, rawincludedir): \
includedir += $$clean_path($$id)
- includedir -= $$QMAKE_DEFAULT_INCDIRS
- $${1}.includedir = $$includedir
- export($${1}.libs)
- export($${1}.includedir)
+ !qtConfResolvePathIncs($${1}.includedir, $$includedir): \
+ return(false)
return(true)
}
qtLog("mysql_config not found.")
@@ -86,14 +72,14 @@ defineTest(qtConfLibrary_mysqlConfig) {
}
defineTest(qtConfLibrary_sybaseEnv) {
- libs =
+ libdir =
sybase = $$getenv(SYBASE)
!isEmpty(sybase): \
- libs += "-L$${sybase}/lib"
- eval(libs += $$getenv(SYBASE_LIBS))
- !isEmpty(libs) {
- $${1}.libs = $$libs
- export($${1}.libs)
- }
+ libdir += $${sybase}/lib
+ eval(libs = $$getenv(SYBASE_LIBS))
+ isEmpty(libs): \
+ libs = $$eval($${1}.libs)
+ !qtConfResolvePathLibs($${1}.libs, $$libdir, $$libs): \
+ return(false)
return(true)
}
diff --git a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
index 58da2a3c51..f2ae3fbc47 100644
--- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
+++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
@@ -48,7 +48,9 @@
#include <qsqlquery.h>
#include <qsqlrecord.h>
#include <qstringlist.h>
+#if QT_CONFIG(textcodec)
#include <qtextcodec.h>
+#endif
#include <qvector.h>
#include <qfile.h>
#include <qdebug.h>
@@ -86,7 +88,7 @@ class QMYSQLDriverPrivate : public QSqlDriverPrivate
public:
QMYSQLDriverPrivate() : QSqlDriverPrivate(), mysql(0),
-#ifndef QT_NO_TEXTCODEC
+#if QT_CONFIG(textcodec)
tc(QTextCodec::codecForLocale()),
#else
tc(0),
@@ -100,7 +102,7 @@ public:
static inline QString toUnicode(QTextCodec *tc, const char *str)
{
-#ifdef QT_NO_TEXTCODEC
+#if !QT_CONFIG(textcodec)
Q_UNUSED(tc);
return QString::fromLatin1(str);
#else
@@ -110,7 +112,7 @@ static inline QString toUnicode(QTextCodec *tc, const char *str)
static inline QString toUnicode(QTextCodec *tc, const char *str, int length)
{
-#ifdef QT_NO_TEXTCODEC
+#if !QT_CONFIG(textcodec)
Q_UNUSED(tc);
return QString::fromLatin1(str, length);
#else
@@ -120,7 +122,7 @@ static inline QString toUnicode(QTextCodec *tc, const char *str, int length)
static inline QByteArray fromUnicode(QTextCodec *tc, const QString &str)
{
-#ifdef QT_NO_TEXTCODEC
+#if !QT_CONFIG(textcodec)
Q_UNUSED(tc);
return str.toLatin1();
#else
@@ -255,7 +257,7 @@ public:
bool preparedQuery;
};
-#ifndef QT_NO_TEXTCODEC
+#if QT_CONFIG(textcodec)
static QTextCodec* codec(MYSQL* mysql)
{
#if MYSQL_VERSION_ID >= 32321
@@ -265,7 +267,7 @@ static QTextCodec* codec(MYSQL* mysql)
#endif
return QTextCodec::codecForLocale();
}
-#endif // QT_NO_TEXTCODEC
+#endif // textcodec
static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type,
const QMYSQLDriverPrivate* p)
@@ -1205,7 +1207,7 @@ QMYSQLDriver::QMYSQLDriver(MYSQL * con, QObject * parent)
init();
if (con) {
d->mysql = (MYSQL *) con;
-#ifndef QT_NO_TEXTCODEC
+#if QT_CONFIG(textcodec)
d->tc = codec(con);
#endif
setOpen(true);
@@ -1434,14 +1436,14 @@ bool QMYSQLDriver::open(const QString& db,
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");
-#ifndef QT_NO_TEXTCODEC
+#if QT_CONFIG(textcodec)
d->tc = QTextCodec::codecForName("UTF-8");
#endif
} else
{
// force the communication to be utf8
mysql_set_character_set(d->mysql, "utf8");
-#ifndef QT_NO_TEXTCODEC
+#if QT_CONFIG(textcodec)
d->tc = codec(d->mysql);
#endif
}
diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index 94d048ca7e..b84448d5e2 100644
--- a/src/plugins/styles/mac/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -1512,7 +1512,7 @@ QRectF QMacStylePrivate::CocoaControl::adjustedControlFrame(const QRectF &rect)
frameRect = frameRect.translated(rect.topLeft());
if (type == QMacStylePrivate::Button_PullDown || type == QMacStylePrivate::Button_PopupButton) {
if (size == QStyleHelper::SizeLarge)
- frameRect = frameRect.adjusted(0, 0, -6, 0).translated(3, -1);
+ frameRect = frameRect.adjusted(0, 0, -6, 0).translated(3, 0);
else if (size == QStyleHelper::SizeSmall)
frameRect = frameRect.adjusted(0, 0, -4, 0).translated(2, 1);
else if (size == QStyleHelper::SizeMini)
@@ -2789,6 +2789,9 @@ int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w
case SH_SpinBox_ButtonsInsideFrame:
ret = false;
break;
+ case SH_Table_GridLineColor:
+ ret = int(qt_mac_toQColor(NSColor.gridColor).rgb());
+ break;
default:
ret = QCommonStyle::styleHint(sh, opt, w, hret);
break;
@@ -3226,7 +3229,13 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
break;
case PE_IndicatorTabClose: {
// Make close button visible only on the hovered tab.
- if (QTabBar *tabBar = qobject_cast<QTabBar*>(w->parentWidget())) {
+ QTabBar *tabBar = qobject_cast<QTabBar*>(w->parentWidget());
+ 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));
+ }
+ if (tabBar) {
const bool documentMode = tabBar->documentMode();
const QTabBarPrivate *tabBarPrivate = static_cast<QTabBarPrivate *>(QObjectPrivate::get(tabBar));
const int hoveredTabIndex = tabBarPrivate->hoveredTabIndex();