From 94e06c68461dffd6aec297395dc435737d5f0711 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Thu, 21 Apr 2022 14:59:26 +0300 Subject: [PATCH] Removed Windows tray implementation from main window. --- Telegram/SourceFiles/mainwindow.cpp | 46 ------ .../platform/win/main_window_win.cpp | 156 +++--------------- .../SourceFiles/platform/win/tray_win.cpp | 73 ++++---- Telegram/SourceFiles/platform/win/tray_win.h | 15 ++ Telegram/SourceFiles/window/main_window.cpp | 2 +- 5 files changed, 80 insertions(+), 212 deletions(-) diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index 2c8199836e..c05ceb3832 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -124,52 +124,6 @@ void MainWindow::initHook() { } void MainWindow::createTrayIconMenu() { -#ifdef Q_OS_WIN - trayIconMenu = new Ui::PopupMenu(nullptr); - trayIconMenu->deleteOnHide(false); -#else // Q_OS_WIN - trayIconMenu = new QMenu(this); - - connect(trayIconMenu, &QMenu::aboutToShow, [=] { - updateIsActive(); - updateTrayMenu(); - }); -#endif // else for Q_OS_WIN - - const auto minimizeAction = trayIconMenu->addAction(QString(), [=] { - if (_activeForTrayIconAction) { - minimizeToTray(); - } else { - showFromTrayMenu(); - } - }); - const auto notificationAction = trayIconMenu->addAction(QString(), [=] { - toggleDisplayNotifyFromTray(); - }); - trayIconMenu->addAction(tr::lng_quit_from_tray(tr::now), [=] { - quitFromTray(); - }); - - _updateTrayMenuTextActions.events( - ) | rpl::start_with_next([=] { - if (!trayIconMenu) { - return; - } - - _activeForTrayIconAction = isActiveForTrayMenu(); - minimizeAction->setText(_activeForTrayIconAction - ? tr::lng_minimize_to_tray(tr::now) - : tr::lng_open_from_tray(tr::now)); - - auto notificationActionText = Core::App().settings().desktopNotify() - ? tr::lng_disable_notifications_from_tray(tr::now) - : tr::lng_enable_notifications_from_tray(tr::now); - notificationAction->setText(notificationActionText); - }, lifetime()); - - _updateTrayMenuTextActions.fire({}); - - initTrayMenuHook(); } void MainWindow::applyInitialWorkMode() { diff --git a/Telegram/SourceFiles/platform/win/main_window_win.cpp b/Telegram/SourceFiles/platform/win/main_window_win.cpp index 3d6443590d..9c4120d657 100644 --- a/Telegram/SourceFiles/platform/win/main_window_win.cpp +++ b/Telegram/SourceFiles/platform/win/main_window_win.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_window.h" #include "platform/platform_specific.h" #include "platform/platform_notifications_manager.h" +#include "platform/win/tray_win.h" #include "platform/win/windows_dlls.h" #include "window/notifications_manager.h" #include "window/window_session_controller.h" @@ -95,69 +96,6 @@ uint32 kTaskbarCreatedMsgId = 0; return nullptr; } -[[nodiscard]] QImage IconWithCounter( - Window::CounterLayerArgs &&args, - Main::Session *session, - bool smallIcon) { - static constexpr auto kCount = 3; - static auto ScaledLogo = std::array(); - static auto ScaledLogoNoMargin = std::array(); - - struct Dimensions { - int index = 0; - int size = 0; - }; - const auto d = [&]() -> Dimensions { - switch (args.size) { - case 16: - return { - .index = 0, - .size = 16, - }; - case 32: - return { - .index = 1, - .size = 32, - }; - default: - return { - .index = 2, - .size = 64, - }; - } - }(); - Assert(d.index < kCount); - - auto &scaled = smallIcon ? ScaledLogoNoMargin : ScaledLogo; - auto result = [&] { - auto &image = scaled[d.index]; - if (image.isNull()) { - image = (smallIcon - ? Window::LogoNoMargin() - : Window::Logo()).scaledToWidth( - d.size, - Qt::SmoothTransformation); - } - return image; - }(); - if (session && session->supportMode()) { - Window::ConvertIconToBlack(result); - } - if (!args.count) { - return result; - } else if (smallIcon) { - return Window::WithSmallCounter(std::move(result), std::move(args)); - } - QPainter p(&result); - const auto half = d.size / 2; - args.size = half; - p.drawPixmap( - half, - half, - Ui::PixmapFromImage(Window::GenerateCounterLayer(std::move(args)))); - return result; -} - EventFilter::EventFilter(not_null window) : _window(window) { } @@ -278,7 +216,6 @@ void MainWindow::shadowsDeactivate() { } void MainWindow::psShowTrayMenu() { - trayIconMenu->popup(QCursor::pos()); } void MainWindow::destroyedFromSystem() { @@ -314,35 +251,9 @@ void MainWindow::psTrayMenuUpdated() { } void MainWindow::psSetupTrayIcon() { - if (!trayIcon) { - trayIcon = new QSystemTrayIcon(this); - - const auto icon = QIcon(Ui::PixmapFromImage( - QImage(Window::LogoNoMargin()))); - - trayIcon->setIcon(icon); - connect( - trayIcon, - &QSystemTrayIcon::messageClicked, - this, - [=] { showFromTray(); }); - attachToTrayIcon(trayIcon); - } - updateIconCounters(); - - trayIcon->show(); } void MainWindow::showTrayTooltip() { - if (trayIcon && !cSeenTrayTooltip()) { - trayIcon->showMessage( - AppName.utf16(), - tr::lng_tray_icon_text(tr::now), - QSystemTrayIcon::Information, - 10000); - cSetSeenTrayTooltip(true); - Local::writeSettings(); - } } void MainWindow::workmodeUpdated(Core::Settings::WorkMode mode) { @@ -350,7 +261,6 @@ void MainWindow::workmodeUpdated(Core::Settings::WorkMode mode) { switch (mode) { case WorkMode::WindowAndTray: { - psSetupTrayIcon(); HWND psOwner = (HWND)GetWindowLongPtr(_hWnd, GWLP_HWNDPARENT); if (psOwner) { SetWindowLongPtr(_hWnd, GWLP_HWNDPARENT, 0); @@ -360,7 +270,6 @@ void MainWindow::workmodeUpdated(Core::Settings::WorkMode mode) { } break; case WorkMode::TrayOnly: { - psSetupTrayIcon(); HWND psOwner = (HWND)GetWindowLongPtr(_hWnd, GWLP_HWNDPARENT); if (!psOwner) { const auto hwnd = _taskbarHiderWindow->winId(); @@ -370,12 +279,6 @@ void MainWindow::workmodeUpdated(Core::Settings::WorkMode mode) { } break; case WorkMode::WindowOnly: { - if (trayIcon) { - trayIcon->setContextMenu(0); - trayIcon->deleteLater(); - } - trayIcon = 0; - HWND psOwner = (HWND)GetWindowLongPtr(_hWnd, GWLP_HWNDPARENT); if (psOwner) { SetWindowLongPtr(_hWnd, GWLP_HWNDPARENT, 0); @@ -446,40 +349,28 @@ void MainWindow::updateIconCounters() { const auto iconSizeBig = QSize( GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)); + const auto supportMode = session && session->supportMode(); - const auto &bg = muted ? st::trayCounterBgMute : st::trayCounterBg; - const auto &fg = st::trayCounterFg; - const auto counterArgs = [&](int size, int counter) { - return Window::CounterLayerArgs{ - .size = size, - .count = counter, - .bg = bg, - .fg = fg, - }; - }; - const auto iconWithCounter = [&](int size, int counter, bool smallIcon) { - return Ui::PixmapFromImage(IconWithCounter( - counterArgs(size, counter), - session, - smallIcon)); - }; - - auto iconSmallPixmap16 = iconWithCounter(16, counter, true); - auto iconSmallPixmap32 = iconWithCounter(32, counter, true); + auto iconSmallPixmap16 = Tray::IconWithCounter( + Tray::CounterLayerArgs(16, counter, muted), + true, + supportMode); + auto iconSmallPixmap32 = Tray::IconWithCounter( + Tray::CounterLayerArgs(32, counter, muted), + true, + supportMode); QIcon iconSmall, iconBig; iconSmall.addPixmap(iconSmallPixmap16); iconSmall.addPixmap(iconSmallPixmap32); const auto bigCounter = taskbarList.Get() ? 0 : counter; - iconBig.addPixmap(iconWithCounter(32, bigCounter, false)); - iconBig.addPixmap(iconWithCounter(64, bigCounter, false)); - if (trayIcon) { - // Force Qt to use right icon size, not the larger one. - QIcon forTrayIcon; - forTrayIcon.addPixmap(iconSizeSmall.width() >= 20 - ? iconSmallPixmap32 - : iconSmallPixmap16); - trayIcon->setIcon(forTrayIcon); - } + iconBig.addPixmap(Tray::IconWithCounter( + Tray::CounterLayerArgs(32, bigCounter, muted), + false, + supportMode)); + iconBig.addPixmap(Tray::IconWithCounter( + Tray::CounterLayerArgs(64, bigCounter, muted), + false, + supportMode)); destroyCachedIcons(); _iconSmall = NativeIcon(iconSmall, iconSizeSmall); @@ -490,7 +381,7 @@ void MainWindow::updateIconCounters() { if (counter > 0) { const auto pixmap = [&](int size) { return Ui::PixmapFromImage(Window::GenerateCounterLayer( - counterArgs(size, counter))); + Tray::CounterLayerArgs(size, counter, muted))); }; QIcon iconOverlay; iconOverlay.addPixmap(pixmap(16)); @@ -625,14 +516,7 @@ void MainWindow::validateWindowTheme(bool native, bool night) { } void MainWindow::showFromTrayMenu() { - // If we try to activate() window before the trayIconMenu is hidden, - // then the window will be shown in semi-active state (Qt bug). - // It will receive input events, but it will be rendered as inactive. - using namespace rpl::mappers; - _showFromTrayLifetime = trayIconMenu->shownValue( - ) | rpl::filter(!_1) | rpl::take(1) | rpl::start_with_next([=] { - showFromTray(); - }); + showFromTray(); } HWND MainWindow::psHwnd() const { diff --git a/Telegram/SourceFiles/platform/win/tray_win.cpp b/Telegram/SourceFiles/platform/win/tray_win.cpp index 25125524dd..527126df29 100644 --- a/Telegram/SourceFiles/platform/win/tray_win.cpp +++ b/Telegram/SourceFiles/platform/win/tray_win.cpp @@ -26,7 +26,7 @@ namespace { constexpr auto kTooltipDelay = crl::time(10000); -[[nodiscard]] QImage IconWithCounter( +[[nodiscard]] QImage ImageIconWithCounter( Window::CounterLayerArgs &&args, bool supportMode, bool smallIcon) { @@ -141,39 +141,23 @@ void Tray::updateIcon() { : !controller->sessionController() ? nullptr : &controller->sessionController()->session(); + const auto supportMode = session && session->supportMode(); + const auto iconSizeWidth = GetSystemMetrics(SM_CXSMICON); - const auto iconSizeSmall = QSize( - GetSystemMetrics(SM_CXSMICON), - GetSystemMetrics(SM_CYSMICON)); - const auto iconSizeBig = QSize( - GetSystemMetrics(SM_CXICON), - GetSystemMetrics(SM_CYICON)); - - const auto &bg = muted ? st::trayCounterBgMute : st::trayCounterBg; - const auto &fg = st::trayCounterFg; - const auto counterArgs = [&](int size, int counter) { - return Window::CounterLayerArgs{ - .size = size, - .count = counter, - .bg = bg, - .fg = fg, - }; - }; - const auto iconWithCounter = [&](int size, int counter, bool smallIcon) { - return Ui::PixmapFromImage(IconWithCounter( - counterArgs(size, counter), - session && session->supportMode(), - smallIcon)); - }; - - auto iconSmallPixmap16 = iconWithCounter(16, counter, true); - auto iconSmallPixmap32 = iconWithCounter(32, counter, true); + auto iconSmallPixmap16 = Tray::IconWithCounter( + CounterLayerArgs(16, counter, muted), + true, + supportMode); + auto iconSmallPixmap32 = Tray::IconWithCounter( + CounterLayerArgs(32, counter, muted), + true, + supportMode); auto iconSmall = QIcon(); iconSmall.addPixmap(iconSmallPixmap16); iconSmall.addPixmap(iconSmallPixmap32); // Force Qt to use right icon size, not the larger one. QIcon forTrayIcon; - forTrayIcon.addPixmap(iconSizeSmall.width() >= 20 + forTrayIcon.addPixmap(iconSizeWidth >= 20 ? iconSmallPixmap32 : iconSmallPixmap16); _icon->setIcon(forTrayIcon); @@ -196,7 +180,18 @@ void Tray::addAction(rpl::producer text, Fn &&callback) { return; } - const auto action = _menu->addAction(QString(), std::move(callback)); + // If we try to activate() window before the _menu is hidden, + // then the window will be shown in semi-active state (Qt bug). + // It will receive input events, but it will be rendered as inactive. + auto callbackLater = crl::guard(_menu.get(), [=] { + using namespace rpl::mappers; + _callbackFromTrayLifetime = _menu->shownValue( + ) | rpl::filter(!_1) | rpl::take(1) | rpl::start_with_next([=] { + callback(); + }); + }); + + const auto action = _menu->addAction(QString(), std::move(callbackLater)); std::move( text ) | rpl::start_with_next([=](const QString &text) { @@ -240,4 +235,24 @@ rpl::lifetime &Tray::lifetime() { return _lifetime; } +Window::CounterLayerArgs Tray::CounterLayerArgs( + int size, + int counter, + bool muted) { + return Window::CounterLayerArgs{ + .size = size, + .count = counter, + .bg = muted ? st::trayCounterBgMute : st::trayCounterBg, + .fg = st::trayCounterFg, + }; +} + +QPixmap Tray::IconWithCounter( + Window::CounterLayerArgs &&args, + bool smallIcon, + bool supportMode) { + return Ui::PixmapFromImage( + ImageIconWithCounter(std::move(args), supportMode, smallIcon)); +} + } // namespace Platform diff --git a/Telegram/SourceFiles/platform/win/tray_win.h b/Telegram/SourceFiles/platform/win/tray_win.h index 6ff8213e07..31ea88880c 100644 --- a/Telegram/SourceFiles/platform/win/tray_win.h +++ b/Telegram/SourceFiles/platform/win/tray_win.h @@ -11,6 +11,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/unique_qptr.h" +namespace Window { +class CounterLayerArgs; +} // namespace Window + namespace Ui { class PopupMenu; } // namespace Ui @@ -43,6 +47,16 @@ public: [[nodiscard]] rpl::lifetime &lifetime(); + // Windows only. + [[nodiscard]] static Window::CounterLayerArgs CounterLayerArgs( + int size, + int counter, + bool muted); + [[nodiscard]] static QPixmap IconWithCounter( + Window::CounterLayerArgs &&args, + bool smallIcon, + bool supportMode); + private: base::unique_qptr _icon; base::unique_qptr _menu; @@ -50,6 +64,7 @@ private: rpl::event_stream<> _iconClicks; rpl::event_stream<> _aboutToShowRequests; + rpl::lifetime _callbackFromTrayLifetime; rpl::lifetime _actionsLifetime; rpl::lifetime _lifetime; diff --git a/Telegram/SourceFiles/window/main_window.cpp b/Telegram/SourceFiles/window/main_window.cpp index 9ec29ed7dd..e9d26d211f 100644 --- a/Telegram/SourceFiles/window/main_window.cpp +++ b/Telegram/SourceFiles/window/main_window.cpp @@ -896,7 +896,7 @@ void MainWindow::savePosition(Qt::WindowState state) { } bool MainWindow::minimizeToTray() { - if (Core::Quitting() || !hasTrayIcon()) { + if (Core::Quitting()/* || !hasTrayIcon()*/) { return false; }