SPMediaKeyTap solution for macOS media keys added.
This commit is contained in:
		
							parent
							
								
									eb939fa4b0
								
							
						
					
					
						commit
						fd6a312abc
					
				
					 15 changed files with 1435 additions and 11972 deletions
				
			
		|  | @ -34,7 +34,7 @@ The source code is published under GPLv3 with OpenSSL exception, the license is | |||
| ## Build instructions | ||||
| 
 | ||||
| * [Visual Studio 2015][msvc] | ||||
| * [Xcode 7][xcode] | ||||
| * [Xcode 8][xcode] | ||||
| * [GYP/CMake on GNU/Linux][cmake] | ||||
| 
 | ||||
| ## Projects in Telegram solution | ||||
|  |  | |||
							
								
								
									
										703
									
								
								Telegram/Patches/qtbase_5_3_2.diff
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										703
									
								
								Telegram/Patches/qtbase_5_3_2.diff
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,703 @@ | |||
| diff --git a/configure b/configure
 | ||||
| index cb8d78f..cadb3f0 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 086510d..ae4f81a 100644
 | ||||
| --- a/mkspecs/common/g++-macx.conf
 | ||||
| +++ b/mkspecs/common/g++-macx.conf
 | ||||
| @@ -14,7 +14,8 @@ 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
 | ||||
|   | ||||
|  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 0cc8cd6..ca9725b 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 bb79a13..5d595bc 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 ebff950..4300ca4 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 4879ae5..3251354 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,17 @@ 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);
 | ||||
| +            engine->getGlyphBearings(glyph, 0, &rb);
 | ||||
|              rightBearing = qMin(QFixed(), QFixed::fromReal(rb)); | ||||
|          } | ||||
|   | ||||
| @@ -1648,13 +1659,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 cbe42c3..b273db7 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/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
 | ||||
| index ca7afb7..25ae500 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/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
 | ||||
| index 92358ec..694fee7 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/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
 | ||||
| index 9fd05a6..dea6072 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 e46eaff..c62db53 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 83c960d..3b9f8d4 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,17 @@ 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;
 | ||||
| +
 | ||||
| +    // Patch: Nice macOS tray icon support.
 | ||||
| +    const short scale = hgt * 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 +346,13 @@ QT_END_NAMESPACE
 | ||||
|      return self; | ||||
|  } | ||||
|   | ||||
| --(void)menuTrackingDone:(NSNotification*)notification
 | ||||
| +// Patch: Nice macOS tray icon support.
 | ||||
| +-(void)updateIconSelection
 | ||||
|  { | ||||
| -    Q_UNUSED(notification);
 | ||||
| -    down = NO;
 | ||||
| -
 | ||||
|      CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight]; | ||||
| -    const short scale = hgt - 4;
 | ||||
| -
 | ||||
| -    QPixmap pm = parent->icon.pixmap(QSize(scale, scale), QIcon::Normal);
 | ||||
| +    const short scale = hgt * 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 +360,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 +382,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 +403,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 +418,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 +436,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 4d0458a..fde238a 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]; | ||||
| @@ -914,6 +915,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 +943,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 a18ee7f..1f91feb 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 c680764..e2a7aaf 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 7396808..87b4978 100644
 | ||||
| --- a/src/widgets/kernel/qwidget.cpp
 | ||||
| +++ b/src/widgets/kernel/qwidget.cpp
 | ||||
| @@ -7983,7 +7983,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 0845a5e..5735cb6 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 f98aeaf..00c0734 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 75f3059..980f2be 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 96438a0..b0b7206 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 | ||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1,3 +1,17 @@ | |||
| diff --git a/configure b/configure
 | ||||
| index 7651e29..11e6f90 100755
 | ||||
| --- a/configure
 | ||||
| +++ b/configure
 | ||||
| @@ -527,7 +527,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/msvc-desktop.conf b/mkspecs/common/msvc-desktop.conf
 | ||||
| index eec9e1f..ec3015e 100644
 | ||||
| --- a/mkspecs/common/msvc-desktop.conf
 | ||||
|  | @ -16,6 +30,21 @@ index eec9e1f..ec3015e 100644 | |||
|  QMAKE_CFLAGS_YACC       = | ||||
|  QMAKE_CFLAGS_LTCG       = -GL | ||||
|  QMAKE_CFLAGS_SSE2       = -arch:SSE2 | ||||
| diff --git a/mkspecs/features/mac/default_pre.prf b/mkspecs/features/mac/default_pre.prf
 | ||||
| index 0cc8cd6..ca9725b 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/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
 | ||||
| index f1a6019..81ff6ef 100644
 | ||||
| --- a/src/corelib/io/qfilesystemengine_win.cpp
 | ||||
|  | @ -11250,7 +11279,7 @@ index faea54b..7d85080 100644 | |||
|   | ||||
|  contains(QT_CONFIG, xcb-plugin): SUBDIRS += compose | ||||
| diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
 | ||||
| index caa8884..b083e65 100644
 | ||||
| index caa8884..72941e4 100644
 | ||||
| --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
 | ||||
| +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
 | ||||
| @@ -210,7 +210,8 @@ QT_END_NAMESPACE
 | ||||
|  | @ -11263,6 +11292,23 @@ index caa8884..b083e65 100644 | |||
|      } | ||||
|   | ||||
|      if ([self canQuit]) { | ||||
| @@ -287,11 +288,15 @@ QT_END_NAMESPACE
 | ||||
|   | ||||
|  - (void)applicationDidFinishLaunching:(NSNotification *)aNotification | ||||
|  { | ||||
| +    // We need to catch that notification in delegate.
 | ||||
| +    if (reflectionDelegate
 | ||||
| +        && [reflectionDelegate respondsToSelector:@selector(applicationDidFinishLaunching:)])
 | ||||
| +        [reflectionDelegate applicationDidFinishLaunching:aNotification];
 | ||||
| +
 | ||||
|      Q_UNUSED(aNotification); | ||||
|      inLaunch = false; | ||||
|      // qt_release_apple_event_handler(); | ||||
|   | ||||
| -
 | ||||
|      // Insert code here to initialize your application | ||||
|  } | ||||
|   | ||||
| diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h
 | ||||
| index 5a199de..5622728 100644
 | ||||
| --- a/src/plugins/platforms/cocoa/qcocoabackingstore.h
 | ||||
|  |  | |||
							
								
								
									
										47
									
								
								Telegram/Patches/qtimageformats_5_3_2.diff
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								Telegram/Patches/qtimageformats_5_3_2.diff
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,47 @@ | |||
| diff --git a/src/3rdparty/libwebp/src/dec/vp8l.c b/src/3rdparty/libwebp/src/dec/vp8l.c
 | ||||
| index ea0254d..953ff01 100644
 | ||||
| --- a/src/3rdparty/libwebp/src/dec/vp8l.c
 | ||||
| +++ b/src/3rdparty/libwebp/src/dec/vp8l.c
 | ||||
| @@ -12,7 +12,7 @@
 | ||||
|  // Authors: Vikas Arora (vikaas.arora@gmail.com) | ||||
|  //          Jyrki Alakuijala (jyrki@google.com) | ||||
|   | ||||
| -#include <stdio.h>
 | ||||
| +// Patch: Backport of a crash fix.
 | ||||
|  #include <stdlib.h> | ||||
|  #include "./alphai.h" | ||||
|  #include "./vp8li.h" | ||||
| @@ -740,6 +740,10 @@ static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data,
 | ||||
|    const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES; | ||||
|    const int mask = hdr->huffman_mask_; | ||||
|    assert(htree_group != NULL); | ||||
| +
 | ||||
| +  // Patch: Backport of a crash fix.
 | ||||
| +  assert(pos < end);
 | ||||
| +
 | ||||
|    assert(last_row <= height); | ||||
|    assert(Is8bOptimizable(hdr)); | ||||
|   | ||||
| @@ -830,6 +834,10 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
 | ||||
|        (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL; | ||||
|    const int mask = hdr->huffman_mask_; | ||||
|    assert(htree_group != NULL); | ||||
| +
 | ||||
| +  // Patch: Backport of a crash fix.
 | ||||
| +  assert(src < src_end);
 | ||||
| +
 | ||||
|    assert(src_last <= src_end); | ||||
|   | ||||
|    while (!br->eos_ && src < src_last) { | ||||
| @@ -1294,6 +1302,11 @@ int VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) {
 | ||||
|    assert(dec->action_ == READ_DATA); | ||||
|    assert(last_row <= dec->height_); | ||||
|   | ||||
| +  // Patch: Backport of a crash fix.
 | ||||
| +  if (dec->last_pixel_ == dec->width_ * dec->height_) {
 | ||||
| +    return 1; // done
 | ||||
| +  }
 | ||||
| +
 | ||||
|    // Decode (with special row processing). | ||||
|    return alph_dec->use_8b_decode ? | ||||
|        DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_, | ||||
|  | @ -33,10 +33,14 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org | |||
| 
 | ||||
| #include <IOKit/hidsystem/ev_keymap.h> | ||||
| 
 | ||||
| #include <SPMediaKeyTap.h> | ||||
| 
 | ||||
| using Platform::Q2NSString; | ||||
| using Platform::NSlang; | ||||
| using Platform::NS2QString; | ||||
| 
 | ||||
| bool handleMediaKeyEvent(NSEvent *e); | ||||
| 
 | ||||
| @interface qVisualize : NSObject { | ||||
| } | ||||
| 
 | ||||
|  | @ -81,11 +85,16 @@ using Platform::NS2QString; | |||
| @end | ||||
| 
 | ||||
| @interface ApplicationDelegate : NSObject<NSApplicationDelegate> { | ||||
| 
 | ||||
| SPMediaKeyTap *keyTap; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| - (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag; | ||||
| - (void)applicationDidFinishLaunching:(NSNotification *)aNotification; | ||||
| - (void)applicationDidBecomeActive:(NSNotification *)aNotification; | ||||
| - (void)receiveWakeNote:(NSNotification*)note; | ||||
| - (void)mediaKeyTap:(SPMediaKeyTap*)keyTap receivedMediaKeyEvent:(NSEvent*)event; | ||||
| 
 | ||||
| @end | ||||
| 
 | ||||
|  | @ -99,6 +108,15 @@ ApplicationDelegate *_sharedDelegate = nil; | |||
| 	return YES; | ||||
| } | ||||
| 
 | ||||
| - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { | ||||
| 	keyTap = [[SPMediaKeyTap alloc] initWithDelegate:self]; | ||||
| 	if ([SPMediaKeyTap usesGlobalMediaKeyTap]) { | ||||
| 		[keyTap startWatchingMediaKeys]; | ||||
| 	} else { | ||||
| 		LOG(("Media key monitoring disabled")); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| - (void)applicationDidBecomeActive:(NSNotification *)aNotification { | ||||
| 	if (App::app()) App::app()->checkLocalTime(); | ||||
| } | ||||
|  | @ -107,6 +125,12 @@ ApplicationDelegate *_sharedDelegate = nil; | |||
| 	if (App::app()) App::app()->checkLocalTime(); | ||||
| } | ||||
| 
 | ||||
| - (void)mediaKeyTap:(SPMediaKeyTap*)keyTap receivedMediaKeyEvent:(NSEvent*)e { | ||||
| 	if (e && [e type] == NSSystemDefined && [e subtype] == SPSystemDefinedEventMediaKeys) { | ||||
| 		handleMediaKeyEvent(e); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @end | ||||
| 
 | ||||
| @interface ObserverHelper : NSObject { | ||||
|  | @ -173,6 +197,9 @@ PsMacWindowPrivate::PsMacWindowPrivate() : data(new PsMacWindowData(this)) { | |||
| 	[[NSDistributedNotificationCenter defaultCenter] addObserver:data->observerHelper selector:@selector(screenIsLocked:) name:Q2NSString(strNotificationAboutScreenLocked()) object:nil]; | ||||
| 	[[NSDistributedNotificationCenter defaultCenter] addObserver:data->observerHelper selector:@selector(screenIsUnlocked:) name:Q2NSString(strNotificationAboutScreenUnlocked()) object:nil]; | ||||
| 
 | ||||
| 	// Register defaults for the whitelist of apps that want to use media keys | ||||
| 	[[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:[SPMediaKeyTap defaultMediaKeyUserBundleIdentifiers], kMediaKeyUsingBundleIdentifiersDefaultsKey, nil]]; | ||||
| 
 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -225,6 +252,43 @@ void objc_activateWnd(WId winId) { | |||
| 	[wnd orderFront:wnd]; | ||||
| } | ||||
| 
 | ||||
| bool handleMediaKeyEvent(NSEvent *e) { | ||||
| 	int keyCode = (([e data1] & 0xFFFF0000) >> 16); | ||||
| 	int keyFlags = ([e data1] & 0x0000FFFF); | ||||
| 	int keyState = (((keyFlags & 0xFF00) >> 8)) == 0xA; | ||||
| 	int keyRepeat = (keyFlags & 0x1); | ||||
| 
 | ||||
| 	switch (keyCode) { | ||||
| 	case NX_KEYTYPE_PLAY: | ||||
| 		if (keyState == 0) { // Play pressed and released | ||||
| 			if (Media::Player::exists()) { | ||||
| 				Media::Player::instance()->playPause(); | ||||
| 			} | ||||
| 			return true; | ||||
| 		} | ||||
| 		break; | ||||
| 
 | ||||
| 	case NX_KEYTYPE_FAST: | ||||
| 		if (keyState == 0) { // Next pressed and released | ||||
| 			if (Media::Player::exists()) { | ||||
| 				Media::Player::instance()->next(); | ||||
| 			} | ||||
| 			return true; | ||||
| 		} | ||||
| 		break; | ||||
| 
 | ||||
| 	case NX_KEYTYPE_REWIND: | ||||
| 		if (keyState == 0) { // Previous pressed and released | ||||
| 			if (Media::Player::exists()) { | ||||
| 				Media::Player::instance()->previous(); | ||||
| 			} | ||||
| 			return true; | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| void PsMacWindowPrivate::enableShadow(WId winId) { | ||||
| //	[[(NSView*)winId window] setStyleMask:NSBorderlessWindowMask]; | ||||
| //	[[(NSView*)winId window] setHasShadow:YES]; | ||||
|  | @ -232,39 +296,10 @@ void PsMacWindowPrivate::enableShadow(WId winId) { | |||
| 
 | ||||
| bool PsMacWindowPrivate::filterNativeEvent(void *event) { | ||||
| 	NSEvent *e = static_cast<NSEvent*>(event); | ||||
| 	if (e && [e type] == NSSystemDefined && [e subtype] == 8) { | ||||
| 		int keyCode = (([e data1] & 0xFFFF0000) >> 16); | ||||
| 		int keyFlags = ([e data1] & 0x0000FFFF); | ||||
| 		int keyState = (((keyFlags & 0xFF00) >> 8)) == 0xA; | ||||
| 		int keyRepeat = (keyFlags & 0x1); | ||||
| 
 | ||||
| 		switch (keyCode) { | ||||
| 		case NX_KEYTYPE_PLAY: | ||||
| 			if (keyState == 0) { // Play pressed and released | ||||
| 				if (Media::Player::exists()) { | ||||
| 					Media::Player::instance()->playPause(); | ||||
| 				} | ||||
| 				return true; | ||||
| 			} | ||||
| 			break; | ||||
| 
 | ||||
| 		case NX_KEYTYPE_FAST: | ||||
| 			if (keyState == 0) { // Next pressed and released | ||||
| 				if (Media::Player::exists()) { | ||||
| 					Media::Player::instance()->next(); | ||||
| 				} | ||||
| 				return true; | ||||
| 			} | ||||
| 			break; | ||||
| 
 | ||||
| 		case NX_KEYTYPE_REWIND: | ||||
| 			if (keyState == 0) { // Previous pressed and released | ||||
| 				if (Media::Player::exists()) { | ||||
| 					Media::Player::instance()->previous(); | ||||
| 				} | ||||
| 				return true; | ||||
| 			} | ||||
| 			break; | ||||
| 	if (e && [e type] == NSSystemDefined && [e subtype] == SPSystemDefinedEventMediaKeys) { | ||||
| 		// If event tap is not installed, handle events that reach the app instead | ||||
| 		if (![SPMediaKeyTap usesGlobalMediaKeyTap]) { | ||||
| 			return handleMediaKeyEvent(e); | ||||
| 		} | ||||
| 	} | ||||
| 	return false; | ||||
|  |  | |||
							
								
								
									
										30
									
								
								Telegram/ThirdParty/SPMediaKeyTap/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								Telegram/ThirdParty/SPMediaKeyTap/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | |||
| #import <Foundation/Foundation.h> | ||||
| 
 | ||||
| @interface SPInvocationGrabber : NSObject { | ||||
|     id _object; | ||||
|     NSInvocation *_invocation; | ||||
|     int frameCount; | ||||
|     char **frameStrings; | ||||
|     BOOL backgroundAfterForward; | ||||
|     BOOL onMainAfterForward; | ||||
|     BOOL waitUntilDone; | ||||
| } | ||||
| -(id)initWithObject:(id)obj; | ||||
| -(id)initWithObject:(id)obj stacktraceSaving:(BOOL)saveStack; | ||||
| @property (readonly, retain, nonatomic) id object; | ||||
| @property (readonly, retain, nonatomic) NSInvocation *invocation; | ||||
| @property BOOL backgroundAfterForward; | ||||
| @property BOOL onMainAfterForward; | ||||
| @property BOOL waitUntilDone; | ||||
| -(void)invoke; // will release object and invocation
 | ||||
| -(void)printBacktrace; | ||||
| -(void)saveBacktrace; | ||||
| @end | ||||
| 
 | ||||
| @interface NSObject (SPInvocationGrabbing) | ||||
| -(id)grab; | ||||
| -(id)invokeAfter:(NSTimeInterval)delta; | ||||
| -(id)nextRunloop; | ||||
| -(id)inBackground; | ||||
| -(id)onMainAsync:(BOOL)async; | ||||
| @end | ||||
							
								
								
									
										127
									
								
								Telegram/ThirdParty/SPMediaKeyTap/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.m
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								Telegram/ThirdParty/SPMediaKeyTap/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.m
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,127 @@ | |||
| #import "NSObject+SPInvocationGrabbing.h" | ||||
| #import <execinfo.h> | ||||
| 
 | ||||
| #pragma mark Invocation grabbing | ||||
| @interface SPInvocationGrabber () | ||||
| @property (readwrite, retain, nonatomic) id object; | ||||
| @property (readwrite, retain, nonatomic) NSInvocation *invocation; | ||||
| 
 | ||||
| @end | ||||
| 
 | ||||
| @implementation SPInvocationGrabber | ||||
| - (id)initWithObject:(id)obj | ||||
| { | ||||
| 	return [self initWithObject:obj stacktraceSaving:YES]; | ||||
| } | ||||
| 
 | ||||
| -(id)initWithObject:(id)obj stacktraceSaving:(BOOL)saveStack | ||||
| { | ||||
| 	self.object = obj; | ||||
| 
 | ||||
| 	if(saveStack) | ||||
| 		[self saveBacktrace]; | ||||
| 
 | ||||
| 	return self; | ||||
| } | ||||
| -(void)dealloc | ||||
| { | ||||
| 	free(frameStrings); | ||||
| 	self.object = nil; | ||||
| 	self.invocation = nil; | ||||
| 	[super dealloc]; | ||||
| } | ||||
| @synthesize invocation = _invocation, object = _object; | ||||
| 
 | ||||
| @synthesize backgroundAfterForward, onMainAfterForward, waitUntilDone; | ||||
| - (void)runInBackground | ||||
| { | ||||
| 	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; | ||||
| 	@try { | ||||
| 		[self invoke]; | ||||
| 	} | ||||
| 	@finally { | ||||
| 		[pool drain]; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| - (void)forwardInvocation:(NSInvocation *)anInvocation { | ||||
| 	[anInvocation retainArguments]; | ||||
| 	anInvocation.target = _object; | ||||
| 	self.invocation = anInvocation; | ||||
| 	 | ||||
| 	if(backgroundAfterForward) | ||||
| 		[NSThread detachNewThreadSelector:@selector(runInBackground) toTarget:self withObject:nil]; | ||||
| 	else if(onMainAfterForward) | ||||
|         [self performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:waitUntilDone]; | ||||
| } | ||||
| - (NSMethodSignature *)methodSignatureForSelector:(SEL)inSelector { | ||||
| 	NSMethodSignature *signature = [super methodSignatureForSelector:inSelector]; | ||||
| 	if (signature == NULL) | ||||
| 		signature = [_object methodSignatureForSelector:inSelector]; | ||||
|      | ||||
| 	return signature; | ||||
| } | ||||
| 
 | ||||
| - (void)invoke | ||||
| { | ||||
| 
 | ||||
| 	@try { | ||||
| 		[_invocation invoke]; | ||||
| 	} | ||||
| 	@catch (NSException * e) { | ||||
| 		NSLog(@"SPInvocationGrabber's target raised %@:\n\t%@\nInvocation was originally scheduled at:", e.name, e); | ||||
| 		[self printBacktrace]; | ||||
| 		printf("\n"); | ||||
| 		[e raise]; | ||||
| 	} | ||||
| 
 | ||||
| 	self.invocation = nil; | ||||
| 	self.object = nil; | ||||
| } | ||||
| 
 | ||||
| -(void)saveBacktrace | ||||
| { | ||||
|   void *backtraceFrames[128]; | ||||
|   frameCount = backtrace(&backtraceFrames[0], 128); | ||||
|   frameStrings = backtrace_symbols(&backtraceFrames[0], frameCount); | ||||
| } | ||||
| -(void)printBacktrace | ||||
| { | ||||
| 	for(int x = 3; x < frameCount; x++) { | ||||
| 		if(frameStrings[x] == NULL) { break; } | ||||
| 		printf("%s\n", frameStrings[x]); | ||||
| 	} | ||||
| } | ||||
| @end | ||||
| 
 | ||||
| @implementation NSObject (SPInvocationGrabbing) | ||||
| -(id)grab | ||||
| { | ||||
| 	return [[[SPInvocationGrabber alloc] initWithObject:self] autorelease]; | ||||
| } | ||||
| -(id)invokeAfter:(NSTimeInterval)delta | ||||
| { | ||||
| 	id grabber = [self grab]; | ||||
| 	[NSTimer scheduledTimerWithTimeInterval:delta target:grabber selector:@selector(invoke) userInfo:nil repeats:NO]; | ||||
| 	return grabber; | ||||
| } | ||||
| - (id)nextRunloop | ||||
| { | ||||
| 	return [self invokeAfter:0]; | ||||
| } | ||||
| -(id)inBackground | ||||
| { | ||||
|     SPInvocationGrabber *grabber = [self grab]; | ||||
| 	grabber.backgroundAfterForward = YES; | ||||
| 	return grabber; | ||||
| } | ||||
| -(id)onMainAsync:(BOOL)async | ||||
| { | ||||
|     SPInvocationGrabber *grabber = [self grab]; | ||||
| 	grabber.onMainAfterForward = YES; | ||||
|     grabber.waitUntilDone = !async; | ||||
| 	return grabber; | ||||
| } | ||||
| 
 | ||||
| @end | ||||
							
								
								
									
										43
									
								
								Telegram/ThirdParty/SPMediaKeyTap/SPMediaKeyTap.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								Telegram/ThirdParty/SPMediaKeyTap/SPMediaKeyTap.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,43 @@ | |||
| #include <Cocoa/Cocoa.h> | ||||
| #import <IOKit/hidsystem/ev_keymap.h> | ||||
| #import <Carbon/Carbon.h> | ||||
| 
 | ||||
| // http://overooped.com/post/2593597587/mediakeys
 | ||||
| 
 | ||||
| #define SPSystemDefinedEventMediaKeys 8 | ||||
| 
 | ||||
| @interface SPMediaKeyTap : NSObject { | ||||
| 	EventHandlerRef _app_switching_ref; | ||||
| 	EventHandlerRef _app_terminating_ref; | ||||
| 	CFMachPortRef _eventPort; | ||||
| 	CFRunLoopSourceRef _eventPortSource; | ||||
| 	CFRunLoopRef _tapThreadRL; | ||||
| 	BOOL _shouldInterceptMediaKeyEvents; | ||||
| 	id _delegate; | ||||
| 	// The app that is frontmost in this list owns media keys
 | ||||
| 	NSMutableArray *_mediaKeyAppList; | ||||
| } | ||||
| + (NSArray*)defaultMediaKeyUserBundleIdentifiers; | ||||
| 
 | ||||
| -(id)initWithDelegate:(id)delegate; | ||||
| 
 | ||||
| +(BOOL)usesGlobalMediaKeyTap; | ||||
| -(void)startWatchingMediaKeys; | ||||
| -(void)stopWatchingMediaKeys; | ||||
| -(void)handleAndReleaseMediaKeyEvent:(NSEvent *)event; | ||||
| @end | ||||
| 
 | ||||
| @interface NSObject (SPMediaKeyTapDelegate) | ||||
| -(void)mediaKeyTap:(SPMediaKeyTap*)keyTap receivedMediaKeyEvent:(NSEvent*)event; | ||||
| @end | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| extern NSString *kMediaKeyUsingBundleIdentifiersDefaultsKey; | ||||
| extern NSString *kIgnoreMediaKeysDefaultsKey; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
							
								
								
									
										347
									
								
								Telegram/ThirdParty/SPMediaKeyTap/SPMediaKeyTap.m
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										347
									
								
								Telegram/ThirdParty/SPMediaKeyTap/SPMediaKeyTap.m
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,347 @@ | |||
| // Copyright (c) 2010 Spotify AB | ||||
| #import "SPMediaKeyTap.h" | ||||
| #import "SPInvocationGrabbing/NSObject+SPInvocationGrabbing.h" // https://gist.github.com/511181, in submodule | ||||
| 
 | ||||
| @interface SPMediaKeyTap () | ||||
| -(BOOL)shouldInterceptMediaKeyEvents; | ||||
| -(void)setShouldInterceptMediaKeyEvents:(BOOL)newSetting; | ||||
| -(void)startWatchingAppSwitching; | ||||
| -(void)stopWatchingAppSwitching; | ||||
| -(void)eventTapThread; | ||||
| @end | ||||
| static SPMediaKeyTap *singleton = nil; | ||||
| 
 | ||||
| static pascal OSStatus appSwitched (EventHandlerCallRef nextHandler, EventRef evt, void* userData); | ||||
| static pascal OSStatus appTerminated (EventHandlerCallRef nextHandler, EventRef evt, void* userData); | ||||
| static CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon); | ||||
| 
 | ||||
| // Inspired by http://gist.github.com/546311 | ||||
| 
 | ||||
| @implementation SPMediaKeyTap | ||||
| 
 | ||||
| #pragma mark - | ||||
| #pragma mark Setup and teardown | ||||
| -(id)initWithDelegate:(id)delegate | ||||
| { | ||||
| 	_delegate = delegate; | ||||
| 	[self startWatchingAppSwitching]; | ||||
| 	singleton = self; | ||||
| 	_mediaKeyAppList = [NSMutableArray new]; | ||||
|     _tapThreadRL=nil; | ||||
|     _eventPort=nil; | ||||
|     _eventPortSource=nil; | ||||
| 	return self; | ||||
| } | ||||
| -(void)dealloc | ||||
| { | ||||
| 	[self stopWatchingMediaKeys]; | ||||
| 	[self stopWatchingAppSwitching]; | ||||
| 	[_mediaKeyAppList release]; | ||||
| 	[super dealloc]; | ||||
| } | ||||
| 
 | ||||
| -(void)startWatchingAppSwitching | ||||
| { | ||||
| 	// Listen to "app switched" event, so that we don't intercept media keys if we | ||||
| 	// weren't the last "media key listening" app to be active | ||||
| 	EventTypeSpec eventType = { kEventClassApplication, kEventAppFrontSwitched }; | ||||
|     OSStatus err = InstallApplicationEventHandler(NewEventHandlerUPP(appSwitched), 1, &eventType, self, &_app_switching_ref); | ||||
| 	assert(err == noErr); | ||||
| 	 | ||||
| 	eventType.eventKind = kEventAppTerminated; | ||||
|     err = InstallApplicationEventHandler(NewEventHandlerUPP(appTerminated), 1, &eventType, self, &_app_terminating_ref); | ||||
| 	assert(err == noErr); | ||||
| } | ||||
| -(void)stopWatchingAppSwitching | ||||
| { | ||||
| 	if(!_app_switching_ref) return; | ||||
| 	RemoveEventHandler(_app_switching_ref); | ||||
| 	_app_switching_ref = NULL; | ||||
| } | ||||
| 
 | ||||
| -(void)startWatchingMediaKeys | ||||
| { | ||||
|     // Prevent having multiple mediaKeys threads | ||||
|     [self stopWatchingMediaKeys]; | ||||
|      | ||||
| 	[self setShouldInterceptMediaKeyEvents:YES]; | ||||
| 	 | ||||
| 	// Add an event tap to intercept the system defined media key events | ||||
| 	_eventPort = CGEventTapCreate(kCGSessionEventTap, | ||||
| 								  kCGHeadInsertEventTap, | ||||
| 								  kCGEventTapOptionDefault, | ||||
| 								  CGEventMaskBit(NX_SYSDEFINED), | ||||
| 								  tapEventCallback, | ||||
| 								  self); | ||||
| 	assert(_eventPort != NULL); | ||||
| 	 | ||||
|     _eventPortSource = CFMachPortCreateRunLoopSource(kCFAllocatorSystemDefault, _eventPort, 0); | ||||
| 	assert(_eventPortSource != NULL); | ||||
| 	 | ||||
| 	// Let's do this in a separate thread so that a slow app doesn't lag the event tap | ||||
| 	[NSThread detachNewThreadSelector:@selector(eventTapThread) toTarget:self withObject:nil]; | ||||
| } | ||||
| -(void)stopWatchingMediaKeys | ||||
| { | ||||
| 	// TODO<nevyn>: Shut down thread, remove event tap port and source | ||||
|      | ||||
|     if(_tapThreadRL){ | ||||
|         CFRunLoopStop(_tapThreadRL); | ||||
|         _tapThreadRL=nil; | ||||
|     } | ||||
|      | ||||
|     if(_eventPort){ | ||||
|         CFMachPortInvalidate(_eventPort); | ||||
|         CFRelease(_eventPort); | ||||
|         _eventPort=nil; | ||||
|     } | ||||
|      | ||||
|     if(_eventPortSource){ | ||||
|         CFRelease(_eventPortSource); | ||||
|         _eventPortSource=nil; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #pragma mark - | ||||
| #pragma mark Accessors | ||||
| 
 | ||||
| +(BOOL)usesGlobalMediaKeyTap | ||||
| { | ||||
| #ifdef _DEBUG | ||||
| 	// breaking in gdb with a key tap inserted sometimes locks up all mouse and keyboard input forever, forcing reboot | ||||
| 	return NO; | ||||
| #else | ||||
| 	// XXX(nevyn): MediaKey event tap doesn't work on 10.4, feel free to figure out why if you have the energy. | ||||
| 	return  | ||||
| 		![[NSUserDefaults standardUserDefaults] boolForKey:kIgnoreMediaKeysDefaultsKey] | ||||
| 		&& floor(NSAppKitVersionNumber) >= 949/*NSAppKitVersionNumber10_5*/; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| + (NSArray*)defaultMediaKeyUserBundleIdentifiers | ||||
| { | ||||
| 	return [NSArray arrayWithObjects: | ||||
| 		[[NSBundle mainBundle] bundleIdentifier], // your app | ||||
| 		@"com.spotify.client", | ||||
| 		@"com.apple.iTunes", | ||||
| 		@"com.apple.QuickTimePlayerX", | ||||
| 		@"com.apple.quicktimeplayer", | ||||
| 		@"com.apple.iWork.Keynote", | ||||
| 		@"com.apple.iPhoto", | ||||
| 		@"org.videolan.vlc", | ||||
| 		@"com.apple.Aperture", | ||||
| 		@"com.plexsquared.Plex", | ||||
| 		@"com.soundcloud.desktop", | ||||
| 		@"org.niltsh.MPlayerX", | ||||
| 		@"com.ilabs.PandorasHelper", | ||||
| 		@"com.mahasoftware.pandabar", | ||||
| 		@"com.bitcartel.pandorajam", | ||||
| 		@"org.clementine-player.clementine", | ||||
| 		@"fm.last.Last.fm", | ||||
| 		@"fm.last.Scrobbler", | ||||
| 		@"com.beatport.BeatportPro", | ||||
| 		@"com.Timenut.SongKey", | ||||
| 		@"com.macromedia.fireworks", // the tap messes up their mouse input | ||||
| 		@"at.justp.Theremin", | ||||
| 		@"ru.ya.themblsha.YandexMusic", | ||||
| 		@"com.jriver.MediaCenter18", | ||||
| 		@"com.jriver.MediaCenter19", | ||||
| 		@"com.jriver.MediaCenter20", | ||||
| 		@"co.rackit.mate", | ||||
| 		@"com.ttitt.b-music", | ||||
| 		@"com.beardedspice.BeardedSpice", | ||||
| 		@"com.plug.Plug", | ||||
| 		@"com.plug.Plug2", | ||||
| 		@"com.netease.163music", | ||||
|     	@"org.quodlibet.quodlibet", | ||||
| 		nil | ||||
| 	]; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| -(BOOL)shouldInterceptMediaKeyEvents | ||||
| { | ||||
| 	BOOL shouldIntercept = NO; | ||||
| 	@synchronized(self) { | ||||
| 		shouldIntercept = _shouldInterceptMediaKeyEvents; | ||||
| 	} | ||||
| 	return shouldIntercept; | ||||
| } | ||||
| 
 | ||||
| -(void)pauseTapOnTapThread:(BOOL)yeahno | ||||
| { | ||||
| 	CGEventTapEnable(self->_eventPort, yeahno); | ||||
| } | ||||
| -(void)setShouldInterceptMediaKeyEvents:(BOOL)newSetting | ||||
| { | ||||
| 	BOOL oldSetting; | ||||
| 	@synchronized(self) { | ||||
| 		oldSetting = _shouldInterceptMediaKeyEvents; | ||||
| 		_shouldInterceptMediaKeyEvents = newSetting; | ||||
| 	} | ||||
| 	if(_tapThreadRL && oldSetting != newSetting) { | ||||
| 		id grab = [self grab]; | ||||
| 		[grab pauseTapOnTapThread:newSetting]; | ||||
| 		NSTimer *timer = [NSTimer timerWithTimeInterval:0 invocation:[grab invocation] repeats:NO]; | ||||
| 		CFRunLoopAddTimer(_tapThreadRL, (CFRunLoopTimerRef)timer, kCFRunLoopCommonModes); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| #pragma mark  | ||||
| #pragma mark - | ||||
| #pragma mark Event tap callbacks | ||||
| 
 | ||||
| // Note: method called on background thread | ||||
| 
 | ||||
| static CGEventRef tapEventCallback2(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) | ||||
| { | ||||
| 	SPMediaKeyTap *self = refcon; | ||||
| 
 | ||||
|     if(type == kCGEventTapDisabledByTimeout) { | ||||
| 		NSLog(@"Media key event tap was disabled by timeout"); | ||||
| 		CGEventTapEnable(self->_eventPort, TRUE); | ||||
| 		return event; | ||||
| 	} else if(type == kCGEventTapDisabledByUserInput) { | ||||
| 		// Was disabled manually by -[pauseTapOnTapThread] | ||||
| 		return event; | ||||
| 	} | ||||
| 	NSEvent *nsEvent = nil; | ||||
| 	@try { | ||||
| 		nsEvent = [NSEvent eventWithCGEvent:event]; | ||||
| 	} | ||||
| 	@catch (NSException * e) { | ||||
| 		NSLog(@"Strange CGEventType: %d: %@", type, e); | ||||
| 		assert(0); | ||||
| 		return event; | ||||
| 	} | ||||
| 
 | ||||
| 	if (type != NX_SYSDEFINED || [nsEvent subtype] != SPSystemDefinedEventMediaKeys) | ||||
| 		return event; | ||||
| 
 | ||||
| 	int keyCode = (([nsEvent data1] & 0xFFFF0000) >> 16); | ||||
|     if (keyCode != NX_KEYTYPE_PLAY && keyCode != NX_KEYTYPE_FAST && keyCode != NX_KEYTYPE_REWIND && keyCode != NX_KEYTYPE_PREVIOUS && keyCode != NX_KEYTYPE_NEXT) | ||||
| 		return event; | ||||
| 
 | ||||
| 	if (![self shouldInterceptMediaKeyEvents]) | ||||
| 		return event; | ||||
| 	 | ||||
| 	[nsEvent retain]; // matched in handleAndReleaseMediaKeyEvent: | ||||
| 	[self performSelectorOnMainThread:@selector(handleAndReleaseMediaKeyEvent:) withObject:nsEvent waitUntilDone:NO]; | ||||
| 	 | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| static CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) | ||||
| { | ||||
| 	NSAutoreleasePool *pool = [NSAutoreleasePool new]; | ||||
| 	CGEventRef ret = tapEventCallback2(proxy, type, event, refcon); | ||||
| 	[pool drain]; | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| // event will have been retained in the other thread | ||||
| -(void)handleAndReleaseMediaKeyEvent:(NSEvent *)event { | ||||
| 	[event autorelease]; | ||||
| 	 | ||||
| 	[_delegate mediaKeyTap:self receivedMediaKeyEvent:event]; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| -(void)eventTapThread | ||||
| { | ||||
| 	_tapThreadRL = CFRunLoopGetCurrent(); | ||||
| 	CFRunLoopAddSource(_tapThreadRL, _eventPortSource, kCFRunLoopCommonModes); | ||||
| 	CFRunLoopRun(); | ||||
| } | ||||
| 
 | ||||
| #pragma mark Task switching callbacks | ||||
| 
 | ||||
| NSString *kMediaKeyUsingBundleIdentifiersDefaultsKey = @"SPApplicationsNeedingMediaKeys"; | ||||
| NSString *kIgnoreMediaKeysDefaultsKey = @"SPIgnoreMediaKeys"; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| -(void)mediaKeyAppListChanged | ||||
| { | ||||
| 	if([_mediaKeyAppList count] == 0) return; | ||||
| 	 | ||||
| 	/*NSLog(@"--"); | ||||
| 	int i = 0; | ||||
| 	for (NSValue *psnv in _mediaKeyAppList) { | ||||
| 		ProcessSerialNumber psn; [psnv getValue:&psn]; | ||||
| 		NSDictionary *processInfo = [(id)ProcessInformationCopyDictionary( | ||||
| 			&psn, | ||||
| 			kProcessDictionaryIncludeAllInformationMask | ||||
| 		) autorelease]; | ||||
| 		NSString *bundleIdentifier = [processInfo objectForKey:(id)kCFBundleIdentifierKey]; | ||||
| 		NSLog(@"%d: %@", i++, bundleIdentifier); | ||||
| 	}*/ | ||||
| 	 | ||||
|     ProcessSerialNumber mySerial, topSerial; | ||||
| 	GetCurrentProcess(&mySerial); | ||||
| 	[[_mediaKeyAppList objectAtIndex:0] getValue:&topSerial]; | ||||
| 
 | ||||
| 	Boolean same; | ||||
| 	OSErr err = SameProcess(&mySerial, &topSerial, &same); | ||||
| 	[self setShouldInterceptMediaKeyEvents:(err == noErr && same)];	 | ||||
| 
 | ||||
| } | ||||
| -(void)appIsNowFrontmost:(ProcessSerialNumber)psn | ||||
| { | ||||
| 	NSValue *psnv = [NSValue valueWithBytes:&psn objCType:@encode(ProcessSerialNumber)]; | ||||
| 	 | ||||
| 	NSDictionary *processInfo = [(id)ProcessInformationCopyDictionary( | ||||
| 		&psn, | ||||
| 		kProcessDictionaryIncludeAllInformationMask | ||||
| 	) autorelease]; | ||||
| 	NSString *bundleIdentifier = [processInfo objectForKey:(id)kCFBundleIdentifierKey]; | ||||
| 
 | ||||
| 	NSArray *whitelistIdentifiers = [[NSUserDefaults standardUserDefaults] arrayForKey:kMediaKeyUsingBundleIdentifiersDefaultsKey]; | ||||
| 	if(![whitelistIdentifiers containsObject:bundleIdentifier]) return; | ||||
| 
 | ||||
| 	[_mediaKeyAppList removeObject:psnv]; | ||||
| 	[_mediaKeyAppList insertObject:psnv atIndex:0]; | ||||
| 	[self mediaKeyAppListChanged]; | ||||
| } | ||||
| -(void)appTerminated:(ProcessSerialNumber)psn | ||||
| { | ||||
| 	NSValue *psnv = [NSValue valueWithBytes:&psn objCType:@encode(ProcessSerialNumber)]; | ||||
| 	[_mediaKeyAppList removeObject:psnv]; | ||||
| 	[self mediaKeyAppListChanged]; | ||||
| } | ||||
| 
 | ||||
| static pascal OSStatus appSwitched (EventHandlerCallRef nextHandler, EventRef evt, void* userData) | ||||
| { | ||||
| 	SPMediaKeyTap *self = (id)userData; | ||||
| 
 | ||||
|     ProcessSerialNumber newSerial; | ||||
|     GetFrontProcess(&newSerial); | ||||
| 	 | ||||
| 	[self appIsNowFrontmost:newSerial]; | ||||
| 		 | ||||
|     return CallNextEventHandler(nextHandler, evt); | ||||
| } | ||||
| 
 | ||||
| static pascal OSStatus appTerminated (EventHandlerCallRef nextHandler, EventRef evt, void* userData) | ||||
| { | ||||
| 	SPMediaKeyTap *self = (id)userData; | ||||
| 	 | ||||
| 	ProcessSerialNumber deadPSN; | ||||
| 
 | ||||
| 	GetEventParameter( | ||||
| 		evt,  | ||||
| 		kEventParamProcessID,  | ||||
| 		typeProcessSerialNumber,  | ||||
| 		NULL,  | ||||
| 		sizeof(deadPSN),  | ||||
| 		NULL,  | ||||
| 		&deadPSN | ||||
| 	); | ||||
| 
 | ||||
| 	 | ||||
| 	[self appTerminated:deadPSN]; | ||||
|     return CallNextEventHandler(nextHandler, evt); | ||||
| } | ||||
| 
 | ||||
| @end | ||||
|  | @ -27,7 +27,9 @@ | |||
|       'libs_loc': '../../../Libraries', | ||||
|       'src_loc': '../SourceFiles', | ||||
|       'res_loc': '../Resources', | ||||
|       'minizip_loc': '../ThirdParty/minizip', | ||||
|       'third_party_loc': '../ThirdParty', | ||||
|       'minizip_loc': '<(third_party_loc)/minizip', | ||||
|       'sp_media_key_tap_loc': '<(third_party_loc)/SPMediaKeyTap', | ||||
|       'style_files': [ | ||||
|         '<(res_loc)/basic.style', | ||||
|         '<(res_loc)/basic_types.style', | ||||
|  | @ -85,6 +87,7 @@ | |||
|       '<(libs_loc)/ffmpeg', | ||||
|       '<(libs_loc)/openal-soft/include', | ||||
|       '<(minizip_loc)', | ||||
|       '<(sp_media_key_tap_loc)', | ||||
|     ], | ||||
|     'sources': [ | ||||
|       '<@(qrc_files)', | ||||
|  | @ -530,6 +533,11 @@ | |||
|       '<(src_loc)/window/slide_animation.h', | ||||
|       '<(src_loc)/window/top_bar_widget.cpp', | ||||
|       '<(src_loc)/window/top_bar_widget.h', | ||||
| 
 | ||||
|       '<(sp_media_key_tap_loc)/SPMediaKeyTap.m', | ||||
|       '<(sp_media_key_tap_loc)/SPMediaKeyTap.h', | ||||
|       '<(sp_media_key_tap_loc)/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.m', | ||||
|       '<(sp_media_key_tap_loc)/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.h', | ||||
|     ], | ||||
|     'conditions': [ | ||||
|       [ '"<(official_build_target)" != ""', { | ||||
|  | @ -570,6 +578,10 @@ | |||
|           '<(src_loc)/platform/mac/main_window_mac.h', | ||||
|           '<(src_loc)/platform/mac/notifications_manager_mac.mm', | ||||
|           '<(src_loc)/platform/mac/notifications_manager_mac.h', | ||||
|           '<(sp_media_key_tap_loc)/SPMediaKeyTap.m', | ||||
|           '<(sp_media_key_tap_loc)/SPMediaKeyTap.h', | ||||
|           '<(sp_media_key_tap_loc)/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.m', | ||||
|           '<(sp_media_key_tap_loc)/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.h', | ||||
|         ], | ||||
|       }], | ||||
|       [ '"<(build_win)" != "1"', { | ||||
|  |  | |||
|  | @ -40,6 +40,7 @@ | |||
|           ], | ||||
|         }, | ||||
|         'qt_version%': '<(qt_version)', | ||||
|         'qt_loc_unix': '/usr/local/tdesktop/Qt-<(qt_version)', | ||||
|         'conditions': [ | ||||
|           [ 'build_win', { | ||||
|             'qt_lib_prefix': '<(ld_lib_prefix)', | ||||
|  | @ -65,11 +66,7 @@ | |||
|               'qcocoa', | ||||
|             ], | ||||
|           }], | ||||
|           [ 'build_macold', { | ||||
|             'qt_loc_unix': '/usr/local/Qt-<(qt_version)' | ||||
|           }], | ||||
|           [ 'build_mac and not build_macold', { | ||||
|             'qt_loc_unix': '/usr/local/tdesktop/Qt-<(qt_version)', | ||||
|             'qt_libs': [ | ||||
|               '<@(qt_libs)', | ||||
|               'Qt5Core', | ||||
|  | @ -78,7 +75,6 @@ | |||
|             ], | ||||
|           }], | ||||
|           [ 'build_linux', { | ||||
|             'qt_loc_unix': '/usr/local/tdesktop/Qt-<(qt_version)', | ||||
|             'qt_lib_prefix': 'lib', | ||||
|             'qt_lib_debug_postfix': '.a', | ||||
|             'qt_lib_release_postfix': '.a', | ||||
|  |  | |||
|  | @ -65,7 +65,7 @@ Building | |||
| 
 | ||||
| 
 | ||||
|     # Build patched Qt | ||||
|     cd "$srcdir/Libraries/QtStatic" | ||||
|     cd "$qtdir" | ||||
|     ./configure -prefix "$srcdir/qt" -release -opensource -confirm-license -qt-zlib \ | ||||
|                 -qt-libpng -qt-libjpeg -qt-freetype -qt-harfbuzz -qt-pcre -qt-xcb \ | ||||
|                 -qt-xkbcommon-x11 -no-opengl -no-gtkstyle -static -nomake examples -nomake tests | ||||
|  |  | |||
|  | @ -6,8 +6,6 @@ | |||
| 
 | ||||
| Choose a folder for the future build, for example **/Users/user/TBuild** There you will have two folders, **Libraries** for third-party libs and **tdesktop** (or **tdesktop-master**) for the app. | ||||
| 
 | ||||
| **IMPORTANT** You are required to build and install Qt 5.6.0 from the [Xcode 7](building-xcode.md) instructions first. | ||||
| 
 | ||||
| ###Clone source code | ||||
| 
 | ||||
| By git – in Terminal go to **/Users/user/TBuild** and run | ||||
|  | @ -165,8 +163,8 @@ Then in Terminal go to **/Users/user/TBuild/Libraries/ffmpeg** and run | |||
| 
 | ||||
| In Terminal go to **/Users/user/TBuild/Libraries** and run: | ||||
| 
 | ||||
|     git clone git://code.qt.io/qt/qt5.git QtStatic | ||||
|     cd QtStatic | ||||
|     git clone git://code.qt.io/qt/qt5.git qt5_3_2 | ||||
|     cd qt5_3_2 | ||||
|     git checkout 5.3 | ||||
|     perl init-repository --module-subset=qtbase,qtimageformats | ||||
|     git checkout v5.3.2 | ||||
|  | @ -175,19 +173,19 @@ In Terminal go to **/Users/user/TBuild/Libraries** and run: | |||
| 
 | ||||
| #####Apply the patch | ||||
| 
 | ||||
| From **/Users/user/TBuild/Libraries/QtStatic/qtbase**, run: | ||||
| From **/Users/user/TBuild/Libraries/qt5_3_2/qtbase**, run: | ||||
| 
 | ||||
|     git apply ../../../tdesktop/Telegram/Patches/qtbase_5_3_2.diff | ||||
| 
 | ||||
| From **/Users/user/TBuild/Libraries/QtStatic/qtimageformats**, run: | ||||
| From **/Users/user/TBuild/Libraries/qt5_3_2/qtimageformats**, run: | ||||
| 
 | ||||
|     git apply ../../../tdesktop/Telegram/Patches/qtimageformats_5_3_2.diff | ||||
| 
 | ||||
| #####Building library | ||||
| 
 | ||||
| Go to **/Users/user/TBuild/Libraries/QtStatic** and run: | ||||
| Go to **/Users/user/TBuild/Libraries/qt5_3_2** and run: | ||||
| 
 | ||||
|     ./configure -debug-and-release -force-debug-info -opensource -confirm-license -static -opengl desktop -nomake examples -nomake tests -platform macx-g++ | ||||
|     ./configure -prefix "/usr/local/tdesktop/Qt-5.3.2" -debug-and-release -force-debug-info -opensource -confirm-license -static -opengl desktop -nomake examples -nomake tests -platform macx-g++ | ||||
|     make -j4 | ||||
|     sudo make -j4 install | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| ##Build instructions for Xcode 7.2.1 | ||||
| ##Build instructions for Xcode 8.0 | ||||
| 
 | ||||
| ###Prepare folder | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 John Preston
						John Preston