diff --git a/Telegram/Patches/macold/qtbase_5_3_2.diff b/Telegram/Patches/macold/qtbase_5_3_2.diff index 549a14341c..5526231487 100644 --- a/Telegram/Patches/macold/qtbase_5_3_2.diff +++ b/Telegram/Patches/macold/qtbase_5_3_2.diff @@ -483,7 +483,7 @@ index 83c960d..03ae969 100755 } @end diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm -index 4d0458a..fde238a 100644 +index 4d0458a..3357a5e 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -167,7 +167,8 @@ static bool isMouseEvent(NSEvent *ev) @@ -496,7 +496,24 @@ index 4d0458a..fde238a 100644 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) +@@ -795,6 +796,16 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags) + { + Qt::WindowType type = static_cast(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) : @""]; } @@ -516,7 +533,7 @@ index 4d0458a..fde238a 100644 void QCocoaWindow::setWindowIcon(const QIcon &icon) { QCocoaAutoReleasePool pool; -@@ -929,7 +943,10 @@ void QCocoaWindow::setWindowIcon(const QIcon &icon) +@@ -929,7 +953,10 @@ void QCocoaWindow::setWindowIcon(const QIcon &icon) if (icon.isNull()) { [iconButton setImage:nil]; } else { diff --git a/Telegram/Patches/qtbase_5_6_2.diff b/Telegram/Patches/qtbase_5_6_2.diff index 4961a5bc8e..236a4dbf2b 100644 --- a/Telegram/Patches/qtbase_5_6_2.diff +++ b/Telegram/Patches/qtbase_5_6_2.diff @@ -11505,7 +11505,7 @@ index 8152c57..5ddd7b3 100644 } } diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm -index c0d5904..2991fca 100644 +index c0d5904..f3c2047 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -141,7 +141,8 @@ static bool isMouseEvent(NSEvent *ev) @@ -11518,7 +11518,24 @@ index c0d5904..2991fca 100644 NSPoint loc = [theEvent locationInWindow]; NSRect windowFrame = [self.window convertRectFromScreen:[self.window frame]]; NSRect contentFrame = [[self.window contentView] frame]; -@@ -943,6 +944,19 @@ void QCocoaWindow::setWindowFilePath(const QString &filePath) +@@ -811,6 +812,16 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags) + { + Qt::WindowType type = static_cast(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) { +@@ -943,6 +954,19 @@ void QCocoaWindow::setWindowFilePath(const QString &filePath) [m_nsWindow setRepresentedFilename: fi.exists() ? QCFString::toNSString(filePath) : @""]; } @@ -11538,7 +11555,7 @@ index c0d5904..2991fca 100644 void QCocoaWindow::setWindowIcon(const QIcon &icon) { QMacAutoReleasePool pool; -@@ -958,7 +972,9 @@ void QCocoaWindow::setWindowIcon(const QIcon &icon) +@@ -958,7 +982,9 @@ void QCocoaWindow::setWindowIcon(const QIcon &icon) if (icon.isNull()) { [iconButton setImage:nil]; } else { diff --git a/Telegram/SourceFiles/boxes/notifications_box.cpp b/Telegram/SourceFiles/boxes/notifications_box.cpp index 810c6c7f6b..46051c53e4 100644 --- a/Telegram/SourceFiles/boxes/notifications_box.cpp +++ b/Telegram/SourceFiles/boxes/notifications_box.cpp @@ -46,10 +46,10 @@ public: , _cache(cache) { resize(cache.width() / cache.devicePixelRatio(), cache.height() / cache.devicePixelRatio()); + setWindowFlags(Qt::WindowFlags(Qt::FramelessWindowHint) | Qt::WindowStaysOnTopHint | Qt::BypassWindowManagerHint | Qt::NoDropShadowWindowHint | Qt::Tool); setAttribute(Qt::WA_MacAlwaysShowToolWindow); setAttribute(Qt::WA_TransparentForMouseEvents); setAttribute(Qt::WA_OpaquePaintEvent); - setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::BypassWindowManagerHint | Qt::NoDropShadowWindowHint); setWindowOpacity(0.); show(); diff --git a/Telegram/SourceFiles/calls/calls_box_controller.cpp b/Telegram/SourceFiles/calls/calls_box_controller.cpp index c220df79b5..0dd10ec589 100644 --- a/Telegram/SourceFiles/calls/calls_box_controller.cpp +++ b/Telegram/SourceFiles/calls/calls_box_controller.cpp @@ -113,16 +113,16 @@ BoxController::Row::Row(HistoryItem *item) : PeerListBox::Row(item->history()->p } void BoxController::Row::paintStatusText(Painter &p, int x, int y, int outerWidth, bool selected) { - auto &icon = ([this] { + auto icon = ([this] { switch (_type) { - case Type::In: return st::callArrowIn; - case Type::Out: return st::callArrowOut; - case Type::Missed: return st::callArrowMissed; + case Type::In: return &st::callArrowIn; + case Type::Out: return &st::callArrowOut; + case Type::Missed: return &st::callArrowMissed; } Unexpected("_type in Calls::BoxController::Row::paintStatusText()."); })(); - icon.paint(p, x + st::callArrowPosition.x(), y + st::callArrowPosition.y(), outerWidth); - x += + st::callArrowPosition.x() + icon.width() + st::callArrowSkip; + icon->paint(p, x + st::callArrowPosition.x(), y + st::callArrowPosition.y(), outerWidth); + x += + st::callArrowPosition.x() + icon->width() + st::callArrowSkip; PeerListBox::Row::paintStatusText(p, x, y, outerWidth, selected); } @@ -285,7 +285,7 @@ bool BoxController::insertRow(HistoryItem *item, InsertWay way) { } } (way == InsertWay::Append) ? view()->appendRow(createRow(item)) : view()->prependRow(createRow(item)); - view()->reorderRows([](auto &begin, auto &end) { + view()->reorderRows([](auto &&begin, auto &&end) { std::sort(begin, end, [](auto &a, auto &b) { return static_cast(*a).maxItemId() > static_cast(*a).maxItemId(); }); diff --git a/Telegram/SourceFiles/calls/calls_panel.cpp b/Telegram/SourceFiles/calls/calls_panel.cpp index b8ed190e1b..c62fd32f65 100644 --- a/Telegram/SourceFiles/calls/calls_panel.cpp +++ b/Telegram/SourceFiles/calls/calls_panel.cpp @@ -184,8 +184,6 @@ void Panel::refreshCallbacks() { } void Panel::initLayout() { - hide(); - setWindowFlags(Qt::WindowFlags(Qt::FramelessWindowHint) | Qt::WindowStaysOnTopHint | Qt::BypassWindowManagerHint | Qt::NoDropShadowWindowHint | Qt::Tool); setAttribute(Qt::WA_MacAlwaysShowToolWindow); setAttribute(Qt::WA_NoSystemBackground, true); @@ -203,6 +201,8 @@ void Panel::initLayout() { refreshUserPhoto(); }); createDefaultCacheImage(); + + Platform::InitOnTopPanel(this); } void Panel::processUserPhoto() { @@ -235,7 +235,7 @@ void Panel::refreshUserPhoto() { void Panel::createUserpicCache(ImagePtr image) { auto size = st::callWidth * cIntRetinaFactor(); - auto options = _useTransparency ? (Images::Option::RoundedLarge | Images::Option::RoundedTopLeft | Images::Option::RoundedTopRight | Images::Option::Smooth) : 0; + auto options = _useTransparency ? (Images::Option::RoundedLarge | Images::Option::RoundedTopLeft | Images::Option::RoundedTopRight | Images::Option::Smooth) : Images::Option::None; auto width = image->width(); auto height = image->height(); if (width > height) { @@ -245,7 +245,7 @@ void Panel::createUserpicCache(ImagePtr image) { height = qMax((height * size) / width, 1); width = size; } - _userPhoto = image->pixNoCache(width, height, options, size, size); + _userPhoto = image->pixNoCache(width, height, options, st::callWidth, st::callWidth); if (cRetina()) _userPhoto.setDevicePixelRatio(cRetinaFactor()); refreshCacheImageUserPhoto(); @@ -301,7 +301,8 @@ void Panel::createDefaultCacheImage() { if (!_useTransparency || !_cache.isNull()) { return; } - auto cache = QImage(size(), QImage::Format_ARGB32_Premultiplied); + auto cache = QImage(size() * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied); + cache.setDevicePixelRatio(cRetinaFactor()); cache.fill(Qt::transparent); { Painter p(&cache); @@ -317,7 +318,8 @@ void Panel::createDefaultCacheImage() { } void Panel::refreshCacheImageUserPhoto() { - auto cache = QImage(size(), QImage::Format_ARGB32_Premultiplied); + auto cache = QImage(size() * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied); + cache.setDevicePixelRatio(cRetinaFactor()); cache.fill(Qt::transparent); { Painter p(&cache); diff --git a/Telegram/SourceFiles/calls/calls_top_bar.cpp b/Telegram/SourceFiles/calls/calls_top_bar.cpp index 9000abbe16..88357fce33 100644 --- a/Telegram/SourceFiles/calls/calls_top_bar.cpp +++ b/Telegram/SourceFiles/calls/calls_top_bar.cpp @@ -45,11 +45,9 @@ void TopBar::initControls() { _mute->setClickedCallback([this] { _call->setMute(!_call->isMute()); }); + setMuted(_call->isMute()); subscribe(_call->muteChanged(), [this](bool mute) { - _mute->setIconOverride(mute ? &st::callBarUnmuteIcon : nullptr); - _mute->setRippleColorOverride(mute ? &st::callBarUnmuteRipple : nullptr); - _hangup->setRippleColorOverride(mute ? &st::callBarUnmuteRipple : nullptr); - _muted = mute; + setMuted(mute); update(); }); _info->setClickedCallback([this] { @@ -66,6 +64,13 @@ void TopBar::initControls() { updateDurationText(); } +void TopBar::setMuted(bool mute) { + _mute->setIconOverride(mute ? &st::callBarUnmuteIcon : nullptr); + _mute->setRippleColorOverride(mute ? &st::callBarUnmuteRipple : nullptr); + _hangup->setRippleColorOverride(mute ? &st::callBarUnmuteRipple : nullptr); + _muted = mute; +} + void TopBar::updateDurationText() { if (!_call) { return; diff --git a/Telegram/SourceFiles/calls/calls_top_bar.h b/Telegram/SourceFiles/calls/calls_top_bar.h index 301c287848..6d5f2b64be 100644 --- a/Telegram/SourceFiles/calls/calls_top_bar.h +++ b/Telegram/SourceFiles/calls/calls_top_bar.h @@ -48,6 +48,7 @@ private: void updateDurationText(); void updateControlsGeometry(); void startDurationUpdateTimer(TimeMs currentDuration); + void setMuted(bool mute); base::weak_unique_ptr _call; diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h index cd4642d131..d70bcffea0 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h @@ -25,9 +25,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org namespace Platform { namespace Notifications { -inline void CustomNotificationShownHook(QWidget *widget) { -} - inline bool SkipAudio() { return false; } diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index df2da33719..157c033834 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -405,6 +405,9 @@ bool TransparentWindowsSupported(QPoint globalPosition) { return false; } +void InitOnTopPanel(QWidget *panel) { +} + namespace ThirdParty { void start() { diff --git a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm index 89741484b0..d6e8e5d92b 100644 --- a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm +++ b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm @@ -168,16 +168,6 @@ void FlashBounce() { [NSApp requestUserAttention:NSInformationalRequest]; } -void CustomNotificationShownHook(QWidget *widget) { - widget->hide(); - objc_holdOnTop(widget->winId()); - widget->show(); - psShowOverAll(widget, false); - if (auto window = App::wnd()) { - window->customNotificationCreated(widget); - } -} - class Manager::Private : public QObject, private base::Subscriber { public: Private(Manager *manager); diff --git a/Telegram/SourceFiles/platform/mac/specific_mac_p.h b/Telegram/SourceFiles/platform/mac/specific_mac_p.h index 62daf8fcea..838203880a 100644 --- a/Telegram/SourceFiles/platform/mac/specific_mac_p.h +++ b/Telegram/SourceFiles/platform/mac/specific_mac_p.h @@ -20,7 +20,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org // e is NSEvent* bool objc_handleMediaKeyEvent(void *e); -void objc_holdOnTop(WId winId); bool objc_darkMode(); void objc_showOverAll(WId winId, bool canFocus = true); void objc_bringToBack(WId winId); diff --git a/Telegram/SourceFiles/platform/mac/specific_mac_p.mm b/Telegram/SourceFiles/platform/mac/specific_mac_p.mm index 73290e9919..9751a4a816 100644 --- a/Telegram/SourceFiles/platform/mac/specific_mac_p.mm +++ b/Telegram/SourceFiles/platform/mac/specific_mac_p.mm @@ -36,7 +36,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org namespace { -constexpr auto kIgnoreActivationTimeoutMs = 1500; +constexpr auto kIgnoreActivationTimeoutMs = 500; } // namespace @@ -196,13 +196,34 @@ void SetWatchingMediaKeys(bool watching) { } } -} // namespace Platform +void InitOnTopPanel(QWidget *panel) { + Expects(!panel->windowHandle()); -void objc_holdOnTop(WId winId) { - NSWindow *wnd = [reinterpret_cast(winId) window]; - [wnd setHidesOnDeactivate:NO]; + // Force creating windowHandle() without creating the platform window yet. + panel->setAttribute(Qt::WA_NativeWindow, true); + panel->windowHandle()->setProperty("_td_macNonactivatingPanelMask", QVariant(true)); + panel->setAttribute(Qt::WA_NativeWindow, false); + + panel->createWinId(); + + auto platformWindow = [reinterpret_cast(panel->winId()) window]; + t_assert([platformWindow isKindOfClass:[NSPanel class]]); + + auto platformPanel = static_cast(platformWindow); + [platformPanel setLevel:NSPopUpMenuWindowLevel]; + [platformPanel setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces|NSWindowCollectionBehaviorStationary|NSWindowCollectionBehaviorFullScreenAuxiliary|NSWindowCollectionBehaviorIgnoresCycle]; + [platformPanel setFloatingPanel:YES]; + [platformPanel setHidesOnDeactivate:NO]; + + if (auto window = App::wnd()) { + window->customNotificationCreated(panel); + } + + objc_ignoreApplicationActivationRightNow(); } +} // namespace Platform + bool objc_darkMode() { bool result = false; @autoreleasepool { diff --git a/Telegram/SourceFiles/platform/platform_notifications_manager.h b/Telegram/SourceFiles/platform/platform_notifications_manager.h index 50b8e0af31..e303272e1f 100644 --- a/Telegram/SourceFiles/platform/platform_notifications_manager.h +++ b/Telegram/SourceFiles/platform/platform_notifications_manager.h @@ -25,7 +25,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org namespace Platform { namespace Notifications { -void CustomNotificationShownHook(QWidget *widget); bool SkipAudio(); bool SkipToast(); diff --git a/Telegram/SourceFiles/platform/platform_specific.h b/Telegram/SourceFiles/platform/platform_specific.h index fad961c4e1..f5cca73ce5 100644 --- a/Telegram/SourceFiles/platform/platform_specific.h +++ b/Telegram/SourceFiles/platform/platform_specific.h @@ -36,6 +36,8 @@ void finish(); void SetWatchingMediaKeys(bool watching); bool TransparentWindowsSupported(QPoint globalPosition); +void InitOnTopPanel(QWidget *panel); + namespace ThirdParty { void start(); diff --git a/Telegram/SourceFiles/platform/win/notifications_manager_win.h b/Telegram/SourceFiles/platform/win/notifications_manager_win.h index 5171b10c4a..48516a402d 100644 --- a/Telegram/SourceFiles/platform/win/notifications_manager_win.h +++ b/Telegram/SourceFiles/platform/win/notifications_manager_win.h @@ -25,9 +25,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org namespace Platform { namespace Notifications { -inline void CustomNotificationShownHook(QWidget *widget) { -} - class Manager : public Window::Notifications::NativeManager { public: Manager(Window::Notifications::System *system); diff --git a/Telegram/SourceFiles/platform/win/specific_win.cpp b/Telegram/SourceFiles/platform/win/specific_win.cpp index 1a5fad6f05..f452fcd4d4 100644 --- a/Telegram/SourceFiles/platform/win/specific_win.cpp +++ b/Telegram/SourceFiles/platform/win/specific_win.cpp @@ -534,6 +534,9 @@ bool TransparentWindowsSupported(QPoint globalPosition) { return true; } +void InitOnTopPanel(QWidget *panel) { +} + namespace ThirdParty { void start() { diff --git a/Telegram/SourceFiles/window/notifications_manager_default.cpp b/Telegram/SourceFiles/window/notifications_manager_default.cpp index 1f2417892f..34736afbbb 100644 --- a/Telegram/SourceFiles/window/notifications_manager_default.cpp +++ b/Telegram/SourceFiles/window/notifications_manager_default.cpp @@ -199,7 +199,6 @@ void Manager::showNextFromQueue() { queued.item, queued.forwardedCount, startPosition, startShift, shiftDirection); - Platform::Notifications::CustomNotificationShownHook(notification.get()); _notifications.push_back(std::move(notification)); --count; } while (count > 0 && !_queuedNotifications.empty()); @@ -353,9 +352,11 @@ Widget::Widget(Manager *manager, QPoint startPosition, int shift, Direction shif , _a_shift(animation(this, &Widget::step_shift)) { setWindowOpacity(0.); - setWindowFlags(qFlags(Qt::Tool) | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::BypassWindowManagerHint | Qt::NoDropShadowWindowHint); - setAttribute(Qt::WA_OpaquePaintEvent); + setWindowFlags(Qt::WindowFlags(Qt::FramelessWindowHint) | Qt::WindowStaysOnTopHint | Qt::BypassWindowManagerHint | Qt::NoDropShadowWindowHint | Qt::Tool); setAttribute(Qt::WA_MacAlwaysShowToolWindow); + setAttribute(Qt::WA_OpaquePaintEvent); + + Platform::InitOnTopPanel(this); _a_opacity.start([this] { opacityAnimationCallback(); }, 0., 1., st::notifyFastAnim); }