diff --git a/configure b/configure
index cb8d78fd3c..cadb3f0a88 100755
--- a/configure
+++ b/configure
@@ -511,7 +511,8 @@ if [ "$BUILD_ON_MAC" = "yes" ]; then
         exit 2
     fi
 
-    if ! /usr/bin/xcrun -find xcrun >/dev/null 2>&1; then
+    # Patch: Fix Qt for working with Xcode 8.
+    if ! /usr/bin/xcrun -find xcodebuild >/dev/null 2>&1; then
         echo >&2
         echo "   Xcode not set up properly. You may need to confirm the license" >&2
         echo "   agreement by running /usr/bin/xcodebuild without arguments." >&2
diff --git a/mkspecs/common/g++-macx.conf b/mkspecs/common/g++-macx.conf
index 086510dd96..078a5ed1dd 100644
--- a/mkspecs/common/g++-macx.conf
+++ b/mkspecs/common/g++-macx.conf
@@ -14,7 +14,13 @@ QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -gdwarf-2
 QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO += -gdwarf-2
 QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO += -g -gdwarf-2
 
-QMAKE_LFLAGS_STATIC_LIB += -all_load
+# Patch: Don't remember :(
+#QMAKE_LFLAGS_STATIC_LIB += -all_load
+
+# Patch: Use C++14 with custom libc++ build.
+QMAKE_CXXFLAGS_CXX11 = -std=c++1y
+QMAKE_CXXFLAGS += -nostdinc++ -I/usr/local/macold/include/c++/v1
+QMAKE_LFLAGS += /usr/local/macold/lib/libc++.a /usr/local/macold/lib/libc++abi.a -isysroot /
 
 QMAKE_XCODE_GCC_VERSION = com.apple.compilers.llvmgcc42
 
diff --git a/mkspecs/features/mac/default_pre.prf b/mkspecs/features/mac/default_pre.prf
index 0cc8cd6dfd..ca9725b779 100644
--- a/mkspecs/features/mac/default_pre.prf
+++ b/mkspecs/features/mac/default_pre.prf
@@ -12,7 +12,9 @@ isEmpty(QMAKE_XCODE_DEVELOPER_PATH) {
         error("Xcode is not installed in $${QMAKE_XCODE_DEVELOPER_PATH}. Please use xcode-select to choose Xcode installation path.")
 
     # Make sure Xcode is set up properly
-    isEmpty($$list($$system("/usr/bin/xcrun -find xcrun 2>/dev/null"))): \
+
+    # Patch: Fix Qt for working with Xcode 8.
+    isEmpty($$list($$system("/usr/bin/xcrun -find xcodebuild 2>/dev/null"))): \
         error("Xcode not set up properly. You may need to confirm the license agreement by running /usr/bin/xcodebuild.")
 }
 
diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp
index bb79a139b3..5d595bc3b3 100644
--- a/src/gui/image/qbmphandler.cpp
+++ b/src/gui/image/qbmphandler.cpp
@@ -220,6 +220,10 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
     int blue_scale = 0;
     int alpha_scale = 0;
 
+    // Patch: Backport a fix for bmp reader.
+    if (!d->isSequential())
+        d->seek(startpos + BMP_FILEHDR_SIZE + (bi.biSize >= BMP_WIN4? BMP_WIN : bi.biSize)); // goto start of colormap
+
     if (bi.biSize >= BMP_WIN4 || (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32))) {
         if (d->read((char *)&red_mask, sizeof(red_mask)) != sizeof(red_mask))
             return false;
@@ -307,8 +311,9 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
     image.setDotsPerMeterX(bi.biXPelsPerMeter);
     image.setDotsPerMeterY(bi.biYPelsPerMeter);
 
-    if (!d->isSequential())
-        d->seek(startpos + BMP_FILEHDR_SIZE + (bi.biSize >= BMP_WIN4? BMP_WIN : bi.biSize)); // goto start of colormap
+    // Patch: Backport a fix for bmp reader.
+    //if (!d->isSequential())
+    //    d->seek(startpos + BMP_FILEHDR_SIZE + (bi.biSize >= BMP_WIN4? BMP_WIN : bi.biSize)); // goto start of colormap
 
     if (ncols > 0) {                                // read color table
         uchar rgb[4];
diff --git a/src/gui/painting/qpaintengine_p.h b/src/gui/painting/qpaintengine_p.h
index ebff9509ab..4300ca4c0f 100644
--- a/src/gui/painting/qpaintengine_p.h
+++ b/src/gui/painting/qpaintengine_p.h
@@ -87,8 +87,18 @@ public:
         if (hasSystemTransform) {
             if (systemTransform.type() <= QTransform::TxTranslate)
                 systemClip.translate(qRound(systemTransform.dx()), qRound(systemTransform.dy()));
-            else
+            // Patch: Transform the system clip region back from device pixels to device-independent pixels before
+            // applying systemTransform, which already has transform from device-independent pixels to device pixels.
+            else {
+#ifdef Q_OS_MAC
+                QTransform scaleTransform;
+                const qreal invDevicePixelRatio = 1. / pdev->devicePixelRatio();
+                scaleTransform.scale(invDevicePixelRatio, invDevicePixelRatio);
+                systemClip = systemTransform.map(scaleTransform.map(systemClip));
+#else
                 systemClip = systemTransform.map(systemClip);
+#endif
+            }
         }
 
         // Make sure we're inside the viewport.
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 4879ae51d7..56cdcbaf01 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -654,6 +654,9 @@ int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const
         while (oldPos < len && !attributes[oldPos].graphemeBoundary)
             oldPos++;
     } else {
+        // Patch: Skip to the end of the current word, not to the start of the next one.
+        while (oldPos < len && attributes[oldPos].whiteSpace)
+            oldPos++;
         if (oldPos < len && d->atWordSeparator(oldPos)) {
             oldPos++;
             while (oldPos < len && d->atWordSeparator(oldPos))
@@ -662,8 +665,9 @@ int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const
             while (oldPos < len && !d->atSpace(oldPos) && !d->atWordSeparator(oldPos))
                 oldPos++;
         }
-        while (oldPos < len && d->atSpace(oldPos))
-            oldPos++;
+        // Patch: Skip to the end of the current word, not to the start of the next one.
+        //while (oldPos < len && d->atSpace(oldPos))
+        //    oldPos++;
     }
 
     return oldPos;
@@ -1602,6 +1606,9 @@ namespace {
         int currentPosition;
         glyph_t previousGlyph;
 
+        // Patch: Backport a crash fix.
+        QFontEngine *previousGlyphFontEngine;
+
         QFixed minw;
         QFixed softHyphenWidth;
         QFixed rightBearing;
@@ -1634,13 +1641,19 @@ namespace {
             if (currentPosition > 0 &&
                 logClusters[currentPosition - 1] < glyphs.numGlyphs) {
                 previousGlyph = currentGlyph(); // needed to calculate right bearing later
+
+                // Patch: Backport a crash fix.
+                previousGlyphFontEngine = fontEngine;
             }
         }
 
-        inline void adjustRightBearing(glyph_t glyph)
+        // Patch: Backport a crash fix.
+        inline void adjustRightBearing(QFontEngine *engine, glyph_t glyph)
         {
             qreal rb;
-            fontEngine->getGlyphBearings(glyph, 0, &rb);
+
+            // Patch: Backport a crash fix.
+            engine->getGlyphBearings(glyph, 0, &rb);
             rightBearing = qMin(QFixed(), QFixed::fromReal(rb));
         }
 
@@ -1648,13 +1661,16 @@ namespace {
         {
             if (currentPosition <= 0)
                 return;
-            adjustRightBearing(currentGlyph());
+
+            // Patch: Backport a crash fix.
+            adjustRightBearing(fontEngine, currentGlyph());
         }
 
         inline void adjustPreviousRightBearing()
         {
             if (previousGlyph > 0)
-                adjustRightBearing(previousGlyph);
+                // Patch: Backport a crash fix.
+                adjustRightBearing(previousGlyphFontEngine, previousGlyph);
         }
 
         inline void resetRightBearing()
diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h
index cbe42c3844..b273db7e78 100644
--- a/src/gui/text/qtextlayout.h
+++ b/src/gui/text/qtextlayout.h
@@ -194,6 +194,9 @@ private:
                                QRectF *brect, int tabstops, int* tabarray, int tabarraylen,
                                QPainter *painter);
     QTextEngine *d;
+
+    // Patch: Give access to the internal api.
+    friend class TextBlock;
 };
 
 
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index 360f9722c7..f28f289ef6 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -118,6 +118,8 @@ QHttpNetworkConnectionPrivate::~QHttpNetworkConnectionPrivate()
 {
     for (int i = 0; i < channelCount; ++i) {
         if (channels[i].socket) {
+            // Patch: backport critical bugfix from '4f959b6b30' commit.
+            QObject::disconnect(channels[i].socket, Q_NULLPTR, &channels[i], Q_NULLPTR);
             channels[i].socket->close();
             delete channels[i].socket;
         }
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
index ca7afb7d1b..25ae50008d 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
@@ -256,6 +256,13 @@ static void getFontDescription(CTFontDescriptorRef font, FontDescription *fd)
 
     fd->foundryName = QStringLiteral("CoreText");
     fd->familyName = (CFStringRef) CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute);
+
+    // Patch: Fix open sans semibold loading.
+    QCFString _displayName = (CFStringRef) CTFontDescriptorCopyAttribute(font, kCTFontDisplayNameAttribute);
+    if (_displayName == QStringLiteral("Open Sans Semibold")) {
+        fd->familyName = _displayName;
+    }
+
     fd->styleName = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontStyleNameAttribute);
     fd->weight = QFont::Normal;
     fd->style = QFont::StyleNormal;
diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
index 6e2c8a2a9a..3cace8abcb 100644
--- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
+++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
@@ -717,7 +717,8 @@ void QCoreTextFontEngine::getUnscaledGlyph(glyph_t, QPainterPath *, glyph_metric
 
 QFixed QCoreTextFontEngine::emSquareSize() const
 {
-    return QFixed::QFixed(int(CTFontGetUnitsPerEm(ctfont)));
+    // Patch: Fix build for Xcode 9.3.1.
+    return QFixed(int(CTFontGetUnitsPerEm(ctfont)));
 }
 
 QFontEngine *QCoreTextFontEngine::cloneWithSize(qreal pixelSize) const
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
index 92358ecc74..694fee7350 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
+++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
@@ -213,7 +213,8 @@ static void cleanupCocoaApplicationDelegate()
     if (reflectionDelegate) {
         if ([reflectionDelegate respondsToSelector:@selector(applicationShouldTerminate:)])
             return [reflectionDelegate applicationShouldTerminate:sender];
-        return NSTerminateNow;
+        // Patch: Don't terminate if reflectionDelegate does not respond to that selector, just use the default.
+        //return NSTerminateNow;
     }
 
     if ([self canQuit]) {
@@ -289,6 +290,11 @@ static void cleanupCocoaApplicationDelegate()
 
 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
 {
+    // Patch: We need to receive this notification in the delegate as well.
+    if (reflectionDelegate
+        && [reflectionDelegate respondsToSelector:@selector(applicationDidFinishLaunching:)])
+        [reflectionDelegate applicationDidFinishLaunching:aNotification];
+
     Q_UNUSED(aNotification);
     inLaunch = false;
     // qt_release_apple_event_handler();
@@ -411,7 +417,9 @@ static void cleanupCocoaApplicationDelegate()
 {
     Q_UNUSED(replyEvent);
     NSString *urlString = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
-    QWindowSystemInterface::handleFileOpenEvent(QUrl(QCFString::toQString(urlString)));
+
+    // Patch: Fix opening of an external url by a protocol handler.
+    QWindowSystemInterface::handleFileOpenEvent(QUrl::fromNSURL([NSURL URLWithString:urlString]));
 }
 
 - (void)appleEventQuit:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm
index b81b9a0b1c..4e59e833b1 100644
--- a/src/plugins/platforms/cocoa/qcocoacursor.mm
+++ b/src/plugins/platforms/cocoa/qcocoacursor.mm
@@ -81,7 +81,7 @@ void QCocoaCursor::setPos(const QPoint &position)
     pos.x = position.x();
     pos.y = position.y();
 
-    CGEventRef e = CGEventCreateMouseEvent(0, kCGEventMouseMoved, pos, 0);
+    CGEventRef e = CGEventCreateMouseEvent(0, kCGEventMouseMoved, pos, kCGMouseButtonLeft);
     CGEventPost(kCGHIDEventTap, e);
     CFRelease(e);
 }
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index 9850f83dea..b2e1d3dfda 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -649,9 +649,10 @@ OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGIm
     // Verbatim copy if HIViewDrawCGImage (as shown on Carbon-Dev)
     OSStatus err = noErr;
 
-    require_action(inContext != NULL, InvalidContext, err = paramErr);
-    require_action(inBounds != NULL, InvalidBounds, err = paramErr);
-    require_action(inImage != NULL, InvalidImage, err = paramErr);
+    // Patch: Fix build on latest Xcode.
+    //require_action(inContext != NULL, InvalidContext, err = paramErr);
+    //require_action(inBounds != NULL, InvalidBounds, err = paramErr);
+    //require_action(inImage != NULL, InvalidImage, err = paramErr);
 
     CGContextSaveGState( inContext );
     CGContextTranslateCTM (inContext, 0, inBounds->origin.y + CGRectGetMaxY(*inBounds));
@@ -660,9 +661,11 @@ OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGIm
     CGContextDrawImage(inContext, *inBounds, inImage);
 
     CGContextRestoreGState(inContext);
-InvalidImage:
-InvalidBounds:
-InvalidContext:
+
+// Patch: Fix build on latest Xcode.
+//InvalidImage:
+//InvalidBounds:
+//InvalidContext:
         return err;
 }
 
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 9fd05a65ee..dea60720e7 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -402,14 +402,24 @@ void QCocoaIntegration::updateScreens()
         }
         siblings << screen;
     }
+
+    // Patch: Backport crash fix from Qt 5.6.1.
+    // Set virtual siblings list. All screens in mScreens are siblings, because we ignored the
+    // mirrors. Note that some of the screens we update the siblings list for here may be deleted
+    // below, but update anyway to keep the to-be-deleted screens out of the siblings list.
+    foreach (QCocoaScreen* screen, mScreens)
+        screen->setVirtualSiblings(siblings);
+
     // Now the leftovers in remainingScreens are no longer current, so we can delete them.
     foreach (QCocoaScreen* screen, remainingScreens) {
         mScreens.removeOne(screen);
         delete screen;
     }
+
+    // Patch: Backport crash fix from Qt 5.6.1.
     // All screens in mScreens are siblings, because we ignored the mirrors.
-    foreach (QCocoaScreen* screen, mScreens)
-        screen->setVirtualSiblings(siblings);
+    //foreach (QCocoaScreen* screen, mScreens)
+    //    screen->setVirtualSiblings(siblings);
 }
 
 QCocoaScreen *QCocoaIntegration::screenAtIndex(int index)
diff --git a/src/plugins/platforms/cocoa/qcocoakeymapper.mm b/src/plugins/platforms/cocoa/qcocoakeymapper.mm
index e46eaff6be..c62db534a2 100644
--- a/src/plugins/platforms/cocoa/qcocoakeymapper.mm
+++ b/src/plugins/platforms/cocoa/qcocoakeymapper.mm
@@ -382,6 +382,12 @@ bool QCocoaKeyMapper::updateKeyboard()
         keyboardInputLocale = QLocale::c();
         keyboardInputDirection = Qt::LeftToRight;
     }
+
+    // Patch: Backport a fix for layout-independent keyboard shortcuts.
+    const auto newMode = keyboard_mode;
+    deleteLayouts();
+    keyboard_mode = newMode;
+
     return true;
 }
 
@@ -464,7 +470,8 @@ QList<int> QCocoaKeyMapper::possibleKeys(const QKeyEvent *event) const
         Qt::KeyboardModifiers neededMods = ModsTbl[i];
         int key = kbItem->qtKey[i];
         if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) {
-            ret << int(key + (keyMods & ~neededMods));
+            // Patch: Backport a fix for layout-independent keyboard shortcuts.
+            ret << int(key + neededMods);
         }
     }
     return ret;
diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
index 83c960d931..03ae9696af 100755
--- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
@@ -102,7 +102,10 @@ QT_USE_NAMESPACE
     QCocoaSystemTrayIcon *systray;
     NSStatusItem *item;
     QCocoaMenu *menu;
-    bool menuVisible;
+
+    // Patch: Nice macOS tray icon support.
+    bool menuVisible, iconSelected;
+
     QIcon icon;
     QT_MANGLE_NAMESPACE(QNSImageView) *imageCell;
 }
@@ -124,6 +127,10 @@ QT_USE_NAMESPACE
     QT_MANGLE_NAMESPACE(QNSStatusItem) *parent;
 }
 -(id)initWithParent:(QT_MANGLE_NAMESPACE(QNSStatusItem)*)myParent;
+
+// Patch: Nice macOS tray icon support.
+-(void)updateIconSelection;
+
 -(void)menuTrackingDone:(NSNotification*)notification;
 -(void)mousePressed:(NSEvent *)mouseEvent button:(Qt::MouseButton)mouseButton;
 @end
@@ -187,6 +194,19 @@ void QCocoaSystemTrayIcon::cleanup()
     m_sys = 0;
 }
 
+// Patch: Nice macOS tray icon support.
+namespace {
+
+qreal getDevicePixelRatio() {
+    qreal result = 1.0;
+    foreach (QScreen *screen, QGuiApplication::screens()) {
+        result = qMax(result, screen->devicePixelRatio());
+    }
+    return result;
+}
+
+} // namespace
+
 void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
 {
     if (!m_sys)
@@ -194,13 +214,18 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
 
     m_sys->item->icon = icon;
 
-    const bool menuVisible = m_sys->item->menu && m_sys->item->menuVisible;
+    // Patch: Nice macOS tray icon support.
+    //const bool menuVisible = m_sys->item->menu && m_sys->item->menuVisible;
 
-    CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
-    const short scale = hgt - 4;
+    const int padding = 0;
+    const int menuHeight = [[NSStatusBar systemStatusBar] thickness];
+    const int maxImageHeight = menuHeight - padding;
+
+    const short scale = maxImageHeight * getDevicePixelRatio();
 
     QPixmap pm = m_sys->item->icon.pixmap(QSize(scale, scale),
-                                          menuVisible ? QIcon::Selected : QIcon::Normal);
+                                          // Patch: Nice macOS tray icon support.
+                                          m_sys->item->iconSelected ? QIcon::Selected : QIcon::Normal);
     if (pm.isNull()) {
         pm = QPixmap(scale, scale);
         pm.fill(Qt::transparent);
@@ -322,15 +347,16 @@ QT_END_NAMESPACE
     return self;
 }
 
--(void)menuTrackingDone:(NSNotification*)notification
+// Patch: Nice macOS tray icon support.
+-(void)updateIconSelection
 {
-    Q_UNUSED(notification);
-    down = NO;
+    const int padding = 0;
+    const int menuHeight = [[NSStatusBar systemStatusBar] thickness];
+    const int maxImageHeight = menuHeight - padding;
 
-    CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
-    const short scale = hgt - 4;
-
-    QPixmap pm = parent->icon.pixmap(QSize(scale, scale), QIcon::Normal);
+    const short scale = maxImageHeight * getDevicePixelRatio();
+    QPixmap pm = parent->icon.pixmap(QSize(scale, scale),
+    parent->iconSelected ? QIcon::Selected : QIcon::Normal);
     if (pm.isNull()) {
         pm = QPixmap(scale, scale);
         pm.fill(Qt::transparent);
@@ -338,9 +364,19 @@ QT_END_NAMESPACE
     NSImage *nsaltimage = static_cast<NSImage *>(qt_mac_create_nsimage(pm));
     [self setImage: nsaltimage];
     [nsaltimage release];
+}
+
+-(void)menuTrackingDone:(NSNotification*)notification
+{
+    Q_UNUSED(notification);
+    down = NO;
 
     parent->menuVisible = false;
 
+    // Patch: Nice macOS tray icon support.
+    parent->iconSelected = false;
+    [self updateIconSelection];
+
     [self setNeedsDisplay:YES];
 }
 
@@ -350,18 +386,9 @@ QT_END_NAMESPACE
     int clickCount = [mouseEvent clickCount];
     [self setNeedsDisplay:YES];
 
-    CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
-    const short scale = hgt - 4;
-
-    QPixmap pm = parent->icon.pixmap(QSize(scale, scale),
-                                     parent->menuVisible ? QIcon::Selected : QIcon::Normal);
-    if (pm.isNull()) {
-        pm = QPixmap(scale, scale);
-        pm.fill(Qt::transparent);
-    }
-    NSImage *nsaltimage = static_cast<NSImage *>(qt_mac_create_nsimage(pm));
-    [self setImage: nsaltimage];
-    [nsaltimage release];
+    // Patch: Nice macOS tray icon support.
+    parent->iconSelected = (clickCount != 2) && parent->menu;
+    [self updateIconSelection];
 
     if (clickCount == 2) {
         [self menuTrackingDone:nil];
@@ -380,6 +407,10 @@ QT_END_NAMESPACE
 {
     Q_UNUSED(mouseEvent);
     [self menuTrackingDone:nil];
+
+    // Patch: Nice macOS tray icon support.
+    parent->iconSelected = false;
+    [self updateIconSelection];
 }
 
 - (void)rightMouseDown:(NSEvent *)mouseEvent
@@ -391,6 +422,10 @@ QT_END_NAMESPACE
 {
     Q_UNUSED(mouseEvent);
     [self menuTrackingDone:nil];
+
+    // Patch: Nice macOS tray icon support.
+    parent->iconSelected = false;
+    [self updateIconSelection];
 }
 
 - (void)otherMouseDown:(NSEvent *)mouseEvent
@@ -405,7 +440,8 @@ QT_END_NAMESPACE
 }
 
 -(void)drawRect:(NSRect)rect {
-    [[parent item] drawStatusBarBackgroundInRect:rect withHighlight:down];
+    // Patch: Nice macOS tray icon support.
+    [[parent item] drawStatusBarBackgroundInRect:rect withHighlight:parent->menu ? down : NO];
     [super drawRect:rect];
 }
 @end
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 4d0458a4aa..3357a5ef81 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -167,7 +167,8 @@ static bool isMouseEvent(NSEvent *ev)
     if (!self.window.delegate)
         return; // Already detached, pending NSAppKitDefined event
 
-    if (pw && pw->frameStrutEventsEnabled() && isMouseEvent(theEvent)) {
+    // Patch: Fix events loss if the window was minimized or hidden.
+    if (pw && pw->frameStrutEventsEnabled() && pw->m_synchedWindowState != Qt::WindowMinimized && pw->m_isExposed && isMouseEvent(theEvent)) {
         NSPoint loc = [theEvent locationInWindow];
         NSRect windowFrame = [self.window legacyConvertRectFromScreen:[self.window frame]];
         NSRect contentFrame = [[self.window contentView] frame];
@@ -795,6 +796,16 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags)
 {
     Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
     NSInteger styleMask = NSBorderlessWindowMask;
+
+    // Patch: allow creating panels floating on all spaces in macOS.
+    // If you call "setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary" before
+    // setting the "NSNonactivatingPanelMask" bit in the style mask it won't work after that.
+    // So we need a way to set that bit before Qt sets collection behavior the way it does.
+    QVariant nonactivatingPanelMask = window()->property("_td_macNonactivatingPanelMask");
+    if (nonactivatingPanelMask.isValid() && nonactivatingPanelMask.toBool()) {
+        styleMask |= NSNonactivatingPanelMask;
+    }
+
     if (flags & Qt::FramelessWindowHint)
         return styleMask;
     if ((type & Qt::Popup) == Qt::Popup) {
@@ -914,6 +925,19 @@ void QCocoaWindow::setWindowFilePath(const QString &filePath)
     [m_nsWindow setRepresentedFilename: fi.exists() ? QCFString::toNSString(filePath) : @""];
 }
 
+// Patch: Nice macOS window icon.
+namespace {
+
+qreal getDevicePixelRatio() {
+	qreal result = 1.0;
+	foreach (QScreen *screen, QGuiApplication::screens()) {
+		result = qMax(result, screen->devicePixelRatio());
+	}
+	return result;
+}
+
+} // namespace
+
 void QCocoaWindow::setWindowIcon(const QIcon &icon)
 {
     QCocoaAutoReleasePool pool;
@@ -929,7 +953,10 @@ void QCocoaWindow::setWindowIcon(const QIcon &icon)
     if (icon.isNull()) {
         [iconButton setImage:nil];
     } else {
-        QPixmap pixmap = icon.pixmap(QSize(22, 22));
+        // Patch: Nice macOS window icon.
+        CGFloat hgt = 16. * getDevicePixelRatio();
+        QPixmap pixmap = icon.pixmap(QSize(hgt, hgt));
+
         NSImage *image = static_cast<NSImage *>(qt_mac_create_nsimage(pixmap));
         [iconButton setImage:image];
         [image release];
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index a18ee7ff71..1f91feb0ae 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -393,7 +393,9 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
         [self notifyWindowStateChanged:newState];
         // NSWindowDidOrderOnScreenAndFinishAnimatingNotification is private API, and not
         // emitted in 10.6, so we bring back the old behavior for that case alone.
-        if (newState == Qt::WindowNoState && QSysInfo::QSysInfo::MacintoshVersion == QSysInfo::MV_10_6)
+
+        // Patch: Fix macOS window show after window was hidden.
+        if (newState == Qt::WindowNoState/* && QSysInfo::QSysInfo::MacintoshVersion == QSysInfo::MV_10_6*/)
             m_platformWindow->exposeWindow();
     } else if ([notificationName isEqualToString: @"NSWindowDidOrderOffScreenNotification"]) {
         m_platformWindow->obscureWindow();
@@ -1300,7 +1302,9 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
         if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) {
             // On 10.8 and above, MayBegin is likely to happen.  We treat it the same as an actual begin.
-            if (phase == NSEventPhaseMayBegin)
+
+            // Patch: Actual begin should be treated as begin as well.
+            if (phase == NSEventPhaseMayBegin || phase == NSEventPhaseBegan)
                 ph = Qt::ScrollBegin;
         } else
 #endif
@@ -1366,14 +1370,22 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
     quint32 nativeVirtualKey = [nsevent keyCode];
 
     QChar ch = QChar::ReplacementCharacter;
-    int keyCode = Qt::Key_unknown;
-    if ([characters length] != 0) {
-        if (((modifiers & Qt::MetaModifier) || (modifiers & Qt::AltModifier)) && ([charactersIgnoringModifiers length] != 0))
-            ch = QChar([charactersIgnoringModifiers characterAtIndex:0]);
-        else
-            ch = QChar([characters characterAtIndex:0]);
-        keyCode = [self convertKeyCode:ch];
-    }
+
+    // Patch: Backport a fix for layout-independent shortcuts.
+    if ([characters length] != 0) // https://bugreports.qt.io/browse/QTBUG-42584
+        ch = QChar([characters characterAtIndex:0]);
+    else if ([charactersIgnoringModifiers length] != 0 && ((modifiers & Qt::MetaModifier) || (modifiers & Qt::AltModifier)))
+        ch = QChar([charactersIgnoringModifiers characterAtIndex:0]);
+
+    int keyCode = [self convertKeyCode:ch];
+    //int keyCode = Qt::Key_unknown;
+    //if ([characters length] != 0) {
+    //    if (((modifiers & Qt::MetaModifier) || (modifiers & Qt::AltModifier)) && ([charactersIgnoringModifiers length] != 0))
+    //        ch = QChar([charactersIgnoringModifiers characterAtIndex:0]);
+    //    else
+    //        ch = QChar([characters characterAtIndex:0]);
+    //    keyCode = [self convertKeyCode:ch];
+    //}
 
     // we will send a key event unless the input method sets m_sendKeyEvent to false
     m_sendKeyEvent = true;
@@ -1437,6 +1449,11 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
                 && qtKey == Qt::Key_Period) {
             [self handleKeyEvent:nsevent eventType:int(QEvent::KeyPress)];
             return YES;
+
+        // Patch: Allow us to handle Ctrl+Tab and Ctrl+Backtab in the app.
+        } else if ([nsevent modifierFlags] & NSControlKeyMask && (qtKey == Qt::Key_Tab || qtKey == Qt::Key_Backtab)) {
+            [self handleKeyEvent:nsevent eventType:int(QEvent::KeyPress)];
+            return YES;
         }
     }
     return [super performKeyEquivalent:nsevent];
diff --git a/src/tools/qlalr/lalr.cpp b/src/tools/qlalr/lalr.cpp
index c68076477f..e2a7aafa58 100644
--- a/src/tools/qlalr/lalr.cpp
+++ b/src/tools/qlalr/lalr.cpp
@@ -246,11 +246,13 @@ void Grammar::buildExtendedGrammar ()
   non_terminals.insert (accept_symbol);
 }
 
-struct _Nullable: public std::unary_function<Name, bool>
+// Patch: Fix building with the new SDK.
+struct __Nullable: public std::unary_function<Name, bool>
 {
   Automaton *_M_automaton;
 
-  _Nullable (Automaton *aut):
+  // Patch: Fix building with the new SDK.
+  __Nullable (Automaton *aut):
     _M_automaton (aut) {}
 
   bool operator () (Name name) const
@@ -308,7 +310,8 @@ void Automaton::buildNullables ()
 
       for (RulePointer rule = _M_grammar->rules.begin (); rule != _M_grammar->rules.end (); ++rule)
         {
-          NameList::iterator nn = std::find_if (rule->rhs.begin (), rule->rhs.end (), std::not1 (_Nullable (this)));
+          // Patch: Fix building with the new SDK.
+          NameList::iterator nn = std::find_if (rule->rhs.begin (), rule->rhs.end (), std::not1 (__Nullable (this)));
 
           if (nn == rule->rhs.end ())
             changed |= nullables.insert (rule->lhs).second;
@@ -643,7 +646,8 @@ void Automaton::buildIncludesDigraph ()
                   if (! _M_grammar->isNonTerminal (*A))
                     continue;
 
-                  NameList::iterator first_not_nullable = std::find_if (dot, rule->rhs.end (), std::not1 (_Nullable (this)));
+                  // Patch: Fix building with the new SDK.
+                  NameList::iterator first_not_nullable = std::find_if (dot, rule->rhs.end (), std::not1 (__Nullable (this)));
                   if (first_not_nullable != rule->rhs.end ())
                     continue;
 
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 7396808442..7178aecf80 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -4722,6 +4722,17 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset,
         return; // Fully transparent.
 
     Q_D(QWidget);
+
+    // Patch: save and restore dirtyOpaqueChildren field.
+    //
+    // Just like in QWidget::grab() this field should be restored
+    // after the d->render() call, because it will be set to 1 and
+    // opaqueChildren field will be filled with empty region in
+    // case the widget is hidden (because all the opaque children
+    // will be skipped in isVisible() check).
+    //
+    const bool oldDirtyOpaqueChildren = d->dirtyOpaqueChildren;
+
     const bool inRenderWithPainter = d->extra && d->extra->inRenderWithPainter;
     const QRegion toBePainted = !inRenderWithPainter ? d->prepareToRender(sourceRegion, renderFlags)
                                                      : sourceRegion;
@@ -4743,6 +4754,10 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset,
     if (!inRenderWithPainter && (opacity < 1.0 || (target->devType() == QInternal::Printer))) {
         d->render_helper(painter, targetOffset, toBePainted, renderFlags);
         d->extra->inRenderWithPainter = inRenderWithPainter;
+
+        // Patch: save and restore dirtyOpaqueChildren field.
+        d->dirtyOpaqueChildren = oldDirtyOpaqueChildren;
+
         return;
     }
 
@@ -4774,6 +4789,9 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset,
     d->setSharedPainter(oldPainter);
 
     d->extra->inRenderWithPainter = inRenderWithPainter;
+
+    // Patch: save and restore dirtyOpaqueChildren field.
+    d->dirtyOpaqueChildren = oldDirtyOpaqueChildren;
 }
 
 static void sendResizeEvents(QWidget *target)
@@ -7983,7 +8001,8 @@ bool QWidget::event(QEvent *event)
     case QEvent::KeyPress: {
         QKeyEvent *k = (QKeyEvent *)event;
         bool res = false;
-        if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) {  //### Add MetaModifier?
+        // Patch: Allow us to handle Ctrl+Tab and Ctrl+Backtab in the app.
+        if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier))) {  //### Add MetaModifier?
             if (k->key() == Qt::Key_Backtab
                 || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier)))
                 res = focusNextPrevChild(false);
diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm
index 0845a5eb02..5735cb6b39 100644
--- a/src/widgets/styles/qmacstyle_mac.mm
+++ b/src/widgets/styles/qmacstyle_mac.mm
@@ -3667,9 +3667,11 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
 
                 NSBezierPath *pushButtonFocusRingPath;
                 if (bdi.kind == kThemeBevelButton)
-                    pushButtonFocusRingPath = [NSBezierPath bezierPathWithRect:focusRect];
+                    // Patch: Fix building with the new SDK.
+                    pushButtonFocusRingPath = [NSBezierPath bezierPathWithRect:NSRectFromCGRect(focusRect)];
                 else
-                    pushButtonFocusRingPath = [NSBezierPath bezierPathWithRoundedRect:focusRect xRadius:4 yRadius:4];
+                    // Patch: Fix building with the new SDK.
+                    pushButtonFocusRingPath = [NSBezierPath bezierPathWithRoundedRect:NSRectFromCGRect(focusRect) xRadius:4 yRadius:4];
                 qt_drawFocusRingOnPath(cg, pushButtonFocusRingPath);
             }
 
diff --git a/src/widgets/util/qsystemtrayicon_qpa.cpp b/src/widgets/util/qsystemtrayicon_qpa.cpp
index f98aeaf678..00c0734129 100644
--- a/src/widgets/util/qsystemtrayicon_qpa.cpp
+++ b/src/widgets/util/qsystemtrayicon_qpa.cpp
@@ -99,13 +99,18 @@ void QSystemTrayIconPrivate::updateIcon_sys()
 
 void QSystemTrayIconPrivate::updateMenu_sys()
 {
-    if (qpa_sys && menu) {
-        if (!menu->platformMenu()) {
-            QPlatformMenu *platformMenu = qpa_sys->createMenu();
-            if (platformMenu)
-                menu->setPlatformMenu(platformMenu);
+    // Patch: Nice macOS tray icon support.
+    if (qpa_sys) {
+        if (menu) {
+            if (!menu->platformMenu()) {
+                QPlatformMenu *platformMenu = qpa_sys->createMenu();
+                if (platformMenu)
+                    menu->setPlatformMenu(platformMenu);
+            }
+            qpa_sys->updateMenu(menu->platformMenu());
+        } else {
+            qpa_sys->updateMenu(0);
         }
-        qpa_sys->updateMenu(menu->platformMenu());
     }
 }
 
diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp
index 75f30599be..980f2be1e9 100644
--- a/src/widgets/widgets/qwidgetlinecontrol.cpp
+++ b/src/widgets/widgets/qwidgetlinecontrol.cpp
@@ -1867,7 +1867,8 @@ void QWidgetLineControl::processKeyEvent(QKeyEvent* event)
 
     if (unknown && !isReadOnly()) {
         QString t = event->text();
-        if (!t.isEmpty() && t.at(0).isPrint()) {
+        // Patch: Enable ZWJ and ZWNJ characters to be in text input.
+        if (!t.isEmpty() && (t.at(0).isPrint() || t.at(0).unicode() == 0x200C || t.at(0).unicode() == 0x200D)) {
             insert(t);
 #ifndef QT_NO_COMPLETER
             complete(event->key());
diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp
index 96438a0bdf..b0b7206405 100644
--- a/src/widgets/widgets/qwidgettextcontrol.cpp
+++ b/src/widgets/widgets/qwidgettextcontrol.cpp
@@ -1342,7 +1342,8 @@ void QWidgetTextControlPrivate::keyPressEvent(QKeyEvent *e)
 process:
     {
         QString text = e->text();
-        if (!text.isEmpty() && (text.at(0).isPrint() || text.at(0) == QLatin1Char('\t'))) {
+        // Patch: Enable ZWJ and ZWNJ characters to be in text input.
+        if (!text.isEmpty() && (text.at(0).isPrint() || text.at(0) == QLatin1Char('\t') || text.at(0).unicode() == 0x200C || text.at(0).unicode() == 0x200D)) {
             if (overwriteMode
                 // no need to call deleteChar() if we have a selection, insertText
                 // does it already
