Fix build and tray icon menu on Windows.

This commit is contained in:
John Preston 2021-01-22 16:16:18 +04:00
parent 2616659116
commit 574d915c23
16 changed files with 169 additions and 92 deletions

View File

@ -23,7 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h"
#include "history/history.h"
#include "dialogs/dialogs_main_list.h"
#include "window/window_session_controller.h" // onShowAddContact()
#include "window/window_session_controller.h" // showAddContact()
#include "facades.h"
#include "styles/style_boxes.h"
#include "styles/style_profile.h"
@ -112,7 +112,7 @@ object_ptr<Ui::BoxContent> PrepareContactsBox(
box->addButton(tr::lng_close(), [=] { box->closeBox(); });
box->addLeftButton(
tr::lng_profile_add_contact(),
[=] { controller->widget()->onShowAddContact(); });
[=] { controller->widget()->showAddContact(); });
};
return Box<PeerListBox>(
std::make_unique<ContactsBoxController>(

View File

@ -642,7 +642,7 @@ HistoryItem *RepliesList::lastEditableMessage() {
const auto it = ranges::find_if(_list, std::move(proj));
return (it == end(_list))
? nullptr
: _history->owner().groups().findItemToEdit(message(*it));
: _history->owner().groups().findItemToEdit(message(*it)).get();
}
} // namespace Data

View File

@ -562,7 +562,7 @@ HistoryItem *ScheduledMessages::lastEditableMessage(
const auto it = ranges::find_if(items, std::move(proj));
return (it == end(items))
? nullptr
: history->owner().groups().findItemToEdit((*it).get());
: history->owner().groups().findItemToEdit((*it).get()).get();
}
} // namespace Data

View File

@ -2281,7 +2281,7 @@ void InnerWidget::refreshEmptyLabel() {
resizeEmptyLabel();
_empty->setClickHandlerFilter([=](const auto &...) {
if (_emptyState == EmptyState::NoContacts) {
App::wnd()->onShowAddContact();
App::wnd()->showAddContact();
} else if (_emptyState == EmptyState::EmptyFolder) {
editOpenedFilter();
}

View File

@ -146,11 +146,24 @@ void MainWindow::createTrayIconMenu() {
: tr::lng_enable_notifications_from_tray(tr::now);
if (Platform::IsLinux() && !Platform::IsWayland()) {
trayIconMenu->addAction(tr::lng_open_from_tray(tr::now), this, SLOT(showFromTray()));
trayIconMenu->addAction(tr::lng_open_from_tray(tr::now), [=] {
showFromTray();
});
}
trayIconMenu->addAction(tr::lng_minimize_to_tray(tr::now), this, SLOT(minimizeToTray()));
trayIconMenu->addAction(notificationActionText, this, SLOT(toggleDisplayNotifyFromTray()));
trayIconMenu->addAction(tr::lng_quit_from_tray(tr::now), this, SLOT(quitFromTray()));
const auto showLifetime = std::make_shared<rpl::lifetime>();
trayIconMenu->addAction(tr::lng_minimize_to_tray(tr::now), [=] {
if (_activeForTrayIconAction) {
minimizeToTray();
} else {
showFromTrayMenu();
}
});
trayIconMenu->addAction(notificationActionText, [=] {
toggleDisplayNotifyFromTray();
});
trayIconMenu->addAction(tr::lng_quit_from_tray(tr::now), [=] {
quitFromTray();
});
initTrayMenuHook();
}
@ -635,18 +648,17 @@ void MainWindow::updateTrayMenu(bool force) {
auto actions = trayIconMenu->actions();
if (Platform::IsLinux() && !Platform::IsWayland()) {
auto minimizeAction = actions.at(1);
const auto minimizeAction = actions.at(1);
minimizeAction->setEnabled(isVisible());
} else {
updateIsActive();
auto active = Platform::IsWayland() ? isVisible() : isActive();
auto toggleAction = actions.at(0);
disconnect(toggleAction, SIGNAL(triggered(bool)), this, SLOT(minimizeToTray()));
disconnect(toggleAction, SIGNAL(triggered(bool)), this, SLOT(showFromTray()));
connect(toggleAction, SIGNAL(triggered(bool)), this, active ? SLOT(minimizeToTray()) : SLOT(showFromTray()));
toggleAction->setText(active
? tr::lng_minimize_to_tray(tr::now)
: tr::lng_open_from_tray(tr::now));
const auto active = isActiveForTrayMenu();
if (_activeForTrayIconAction != active) {
_activeForTrayIconAction = active;
const auto toggleAction = actions.at(0);
toggleAction->setText(_activeForTrayIconAction
? tr::lng_minimize_to_tray(tr::now)
: tr::lng_open_from_tray(tr::now));
}
}
auto notificationAction = actions.at(Platform::IsLinux() && !Platform::IsWayland() ? 2 : 1);
auto notificationActionText = Core::App().settings().desktopNotify()
@ -657,8 +669,10 @@ void MainWindow::updateTrayMenu(bool force) {
psTrayMenuUpdated();
}
void MainWindow::onShowAddContact() {
if (isHidden()) showFromTray();
void MainWindow::showAddContact() {
if (isHidden()) {
showFromTray();
}
if (const auto controller = sessionController()) {
Ui::show(
@ -667,8 +681,10 @@ void MainWindow::onShowAddContact() {
}
}
void MainWindow::onShowNewGroup() {
if (isHidden()) showFromTray();
void MainWindow::showNewGroup() {
if (isHidden()) {
showFromTray();
}
if (const auto controller = sessionController()) {
Ui::show(
@ -677,8 +693,10 @@ void MainWindow::onShowNewGroup() {
}
}
void MainWindow::onShowNewChannel() {
if (isHidden()) showFromTray();
void MainWindow::showNewChannel() {
if (isHidden()) {
showFromTray();
}
if (const auto controller = sessionController()) {
Ui::show(
@ -720,24 +738,6 @@ void MainWindow::showLogoutConfirmation() {
callback));
}
void MainWindow::quitFromTray() {
App::quit();
}
void MainWindow::activate() {
bool wasHidden = !isVisible();
setWindowState(windowState() & ~Qt::WindowMinimized);
setVisible(true);
psActivateProcess();
activateWindow();
controller().updateIsActiveFocus();
if (wasHidden) {
if (_main) {
_main->windowShown();
}
}
}
bool MainWindow::takeThirdSectionFromLayer() {
return _layer ? _layer->takeToThirdSection() : false;
}
@ -749,23 +749,12 @@ void MainWindow::fixOrder() {
if (_testingThemeWarning) _testingThemeWarning->raise();
}
void MainWindow::showFromTray(QSystemTrayIcon::ActivationReason reason) {
if (reason != QSystemTrayIcon::Context) {
base::call_delayed(1, this, [this] {
updateTrayMenu();
updateGlobalMenu();
});
activate();
updateUnreadCounter();
}
}
void MainWindow::handleTrayIconActication(
QSystemTrayIcon::ActivationReason reason) {
updateIsActive();
if (Platform::IsMac() && isActive()) {
if (trayIcon && !trayIcon->contextMenu()) {
showFromTray(reason);
showFromTray();
}
return;
}
@ -775,10 +764,10 @@ void MainWindow::handleTrayIconActication(
psShowTrayMenu();
});
} else if (!skipTrayClick()) {
if (Platform::IsWayland() ? isVisible() : isActive()) {
if (isActiveForTrayMenu()) {
minimizeToTray();
} else {
showFromTray(reason);
showFromTray();
}
_lastTrayClickTime = crl::now();
}

View File

@ -40,8 +40,6 @@ class LayerStackWidget;
class MediaPreviewWidget;
class MainWindow : public Platform::MainWindow {
Q_OBJECT
public:
explicit MainWindow(not_null<Window::Controller*> controller);
~MainWindow();
@ -55,11 +53,17 @@ public:
void setupIntro(Intro::EnterPoint point);
void setupMain();
void showSettings();
void showAddContact();
void showNewGroup();
void showNewChannel();
void setInnerFocus();
MainWidget *sessionContent() const;
[[nodiscard]] bool doWeMarkAsRead();
void activate();
bool takeThirdSectionFromLayer();
@ -115,18 +119,6 @@ protected:
void updateIsActiveHook() override;
void clearWidgetsHook() override;
public slots:
void showSettings();
void setInnerFocus();
void quitFromTray();
void showFromTray(QSystemTrayIcon::ActivationReason reason = QSystemTrayIcon::Unknown);
void toggleDisplayNotifyFromTray();
void onShowAddContact();
void onShowNewGroup();
void onShowNewChannel();
private:
[[nodiscard]] bool skipTrayClick() const;
@ -140,12 +132,15 @@ private:
void themeUpdated(const Window::Theme::BackgroundUpdate &data);
void toggleDisplayNotifyFromTray();
QPixmap grabInner();
QImage icon16, icon32, icon64, iconbig16, iconbig32, iconbig64;
crl::time _lastTrayClickTime = 0;
QPoint _lastMousePosition;
bool _activeForTrayIconAction = true;
object_ptr<Window::PasscodeLockWidget> _passcodeLock = { nullptr };
object_ptr<Intro::Widget> _intro = { nullptr };

View File

@ -593,6 +593,11 @@ bool MainWindow::hasTrayIcon() const {
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
}
bool MainWindow::isActiveForTrayMenu() {
updateIsActive();
return Platform::IsWayland() ? isVisible() : isActive();
}
void MainWindow::psShowTrayMenu() {
_trayIconMenuXEmbed->popup(QCursor::pos());
}
@ -661,7 +666,7 @@ void MainWindow::sniSignalEmitted(
gchar *signal_name,
GVariant *parameters,
gpointer user_data) {
if(signal_name == qstr("StatusNotifierHostRegistered")) {
if (signal_name == qstr("StatusNotifierHostRegistered")) {
crl::on_main([] {
if (const auto window = App::wnd()) {
window->handleSNIHostRegistered();
@ -684,7 +689,7 @@ void MainWindow::handleSNIHostRegistered() {
LOG(("Switching to SNI tray icon..."));
if (trayIcon) {
trayIcon->setContextMenu(0);
trayIcon->setContextMenu(nullptr);
trayIcon->deleteLater();
}
trayIcon = nullptr;
@ -886,7 +891,7 @@ void MainWindow::LibsLoaded() {
}
void MainWindow::initTrayMenuHook() {
_trayIconMenuXEmbed = new Ui::PopupMenu(nullptr, trayIconMenu);
_trayIconMenuXEmbed.emplace(nullptr, trayIconMenu);
_trayIconMenuXEmbed->deleteOnHide(false);
}
@ -1031,19 +1036,19 @@ void MainWindow::createGlobalMenu() {
psAddContact = tools->addAction(
tr::lng_mac_menu_add_contact(tr::now),
App::wnd(),
[=] { App::wnd()->onShowAddContact(); });
[=] { App::wnd()->showAddContact(); });
tools->addSeparator();
psNewGroup = tools->addAction(
tr::lng_mac_menu_new_group(tr::now),
App::wnd(),
[=] { App::wnd()->onShowNewGroup(); });
[=] { App::wnd()->showNewGroup(); });
psNewChannel = tools->addAction(
tr::lng_mac_menu_new_channel(tr::now),
App::wnd(),
[=] { App::wnd()->onShowNewChannel(); });
[=] { App::wnd()->showNewChannel(); });
auto help = psMainMenu->addMenu(tr::lng_linux_menu_help(tr::now));
@ -1222,8 +1227,6 @@ MainWindow::~MainWindow() {
g_object_unref(_sniDBusProxy);
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
delete _trayIconMenuXEmbed;
}
} // namespace Platform

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "platform/platform_main_window.h"
#include "base/unique_qptr.h"
namespace Ui {
class PopupMenu;
@ -43,6 +44,8 @@ public:
return _sniAvailable || QSystemTrayIcon::isSystemTrayAvailable();
}
bool isActiveForTrayMenu() override;
static void LibsLoaded();
~MainWindow();
@ -75,7 +78,7 @@ protected:
private:
bool _sniAvailable = false;
Ui::PopupMenu *_trayIconMenuXEmbed = nullptr;
base::unique_qptr<Ui::PopupMenu> _trayIconMenuXEmbed;
void updateIconCounters();
void updateWaylandDecorationColors();

View File

@ -692,7 +692,9 @@ void MainWindow::createGlobalMenu() {
about->setMenuRole(QAction::AboutQtRole);
main->addSeparator();
QAction *prefs = main->addAction(tr::lng_mac_menu_preferences(tr::now), App::wnd(), SLOT(showSettings()), QKeySequence(Qt::ControlModifier | Qt::Key_Comma));
QAction *prefs = main->addAction(tr::lng_mac_menu_preferences(tr::now), App::wnd(), [=] {
App::wnd()->showSettings();
}, QKeySequence(Qt::ControlModifier | Qt::Key_Comma));
prefs->setMenuRole(QAction::PreferencesRole);
QMenu *file = psMainMenu.addMenu(tr::lng_mac_menu_file(tr::now));
@ -728,19 +730,27 @@ void MainWindow::createGlobalMenu() {
psContacts = window->addAction(tr::lng_mac_menu_contacts(tr::now));
connect(psContacts, &QAction::triggered, psContacts, crl::guard(this, [=] {
if (isHidden()) {
App::wnd()->showFromTray();
showFromTray();
}
if (!sessionController()) {
return;
}
Ui::show(PrepareContactsBox(sessionController()));
}));
psAddContact = window->addAction(tr::lng_mac_menu_add_contact(tr::now), App::wnd(), SLOT(onShowAddContact()));
psAddContact = window->addAction(tr::lng_mac_menu_add_contact(tr::now), App::wnd(), [=] {
App::wnd()->showAddContact();
});
window->addSeparator();
psNewGroup = window->addAction(tr::lng_mac_menu_new_group(tr::now), App::wnd(), SLOT(onShowNewGroup()));
psNewChannel = window->addAction(tr::lng_mac_menu_new_channel(tr::now), App::wnd(), SLOT(onShowNewChannel()));
psNewGroup = window->addAction(tr::lng_mac_menu_new_group(tr::now), App::wnd(), [=] {
App::wnd()->showNewGroup();
});
psNewChannel = window->addAction(tr::lng_mac_menu_new_channel(tr::now), App::wnd(), [=] {
App::wnd()->showNewChannel();
});
window->addSeparator();
psShowTelegram = window->addAction(tr::lng_mac_menu_show(tr::now), App::wnd(), SLOT(showFromTray()));
psShowTelegram = window->addAction(tr::lng_mac_menu_show(tr::now), App::wnd(), [=] {
showFromTray();
});
updateGlobalMenu();
}

View File

@ -47,6 +47,13 @@ Q_DECLARE_METATYPE(QMargins);
namespace Platform {
namespace {
// Mouse down on tray icon deactivates the application.
// So there is no way to know for sure if the tray icon was clicked from
// active application or from inactive application. So we assume that
// if the application was deactivated less than 0.5s ago, then the tray
// icon click (both left or right button) was made from the active app.
constexpr auto kKeepActiveForTrayIcon = crl::time(500);
HICON createHIconFromQIcon(const QIcon &icon, int xSize, int ySize) {
if (!icon.isNull()) {
const QPixmap pm = icon.pixmap(icon.actualSize(QSize(xSize, ySize)));
@ -113,6 +120,13 @@ MainWindow::MainWindow(not_null<Window::Controller*> controller)
}
});
setupNativeWindowFrame();
using namespace rpl::mappers;
Core::App().appDeactivatedValue(
) | rpl::distinct_until_changed(
) | rpl::filter(_1) | rpl::start_with_next([=] {
_lastDeactivateTime = crl::now();
}, lifetime());
}
void MainWindow::setupNativeWindowFrame() {
@ -280,6 +294,11 @@ void MainWindow::updateWindowIcon() {
updateIconCounters();
}
bool MainWindow::isActiveForTrayMenu() {
return !_lastDeactivateTime
|| (_lastDeactivateTime + kKeepActiveForTrayIcon >= crl::now());
}
void MainWindow::unreadCounterChangedHook() {
setWindowTitle(titleText());
updateIconCounters();
@ -604,6 +623,17 @@ void MainWindow::fixMaximizedWindow() {
}
}
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();
});
}
HWND MainWindow::psHwnd() const {
return ps_hWnd;
}

View File

@ -24,6 +24,8 @@ class MainWindow : public Window::MainWindow {
public:
explicit MainWindow(not_null<Window::Controller*> controller);
void showFromTrayMenu() override;
HWND psHwnd() const;
HMENU psMenu() const;
@ -32,6 +34,7 @@ public:
void updateCustomMargins();
void updateWindowIcon() override;
bool isActiveForTrayMenu() override;
void psRefreshTaskbarIcon();
@ -103,6 +106,10 @@ private:
bool _wasNativeFrame = false;
bool _hasActiveFrame = false;
// Workarounds for activation from tray icon.
crl::time _lastDeactivateTime = 0;
rpl::lifetime _showFromTrayLifetime;
HWND ps_hWnd = nullptr;
HWND ps_tbHider_hWnd = nullptr;
HMENU ps_menu = nullptr;

View File

@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/ui_utility.h"
#include "apiwrap.h"
#include "mainwindow.h"
#include "mainwidget.h" // session->content()->windowShown().
#include "facades.h"
#include "app.h"
#include "styles/style_window.h"
@ -296,6 +297,34 @@ void MainWindow::handleVisibleChanged(bool visible) {
handleVisibleChangedHook(visible);
}
void MainWindow::showFromTray() {
base::call_delayed(1, this, [this] {
updateTrayMenu();
updateGlobalMenu();
});
activate();
updateUnreadCounter();
}
void MainWindow::quitFromTray() {
App::quit();
}
void MainWindow::activate() {
bool wasHidden = !isVisible();
setWindowState(windowState() & ~Qt::WindowMinimized);
setVisible(true);
psActivateProcess();
raise();
activateWindow();
controller().updateIsActiveFocus();
if (wasHidden) {
if (const auto session = sessionController()) {
session->content()->windowShown();
}
}
}
void MainWindow::updatePalette() {
Ui::ForceFullRepaint(this);

View File

@ -50,6 +50,13 @@ public:
bool hideNoQuit();
void showFromTray();
void quitFromTray();
void activate();
virtual void showFromTrayMenu() {
showFromTray();
}
void init();
HitTestResult hitTest(const QPoint &p) const;
@ -58,6 +65,10 @@ public:
bool isActive() const {
return _isActive;
}
virtual bool isActiveForTrayMenu() {
updateIsActive();
return isActive();
}
bool positionInited() const {
return _positionInited;

View File

@ -859,10 +859,10 @@ void MainMenu::refreshMenu() {
if (!_controller->session().supportMode()) {
const auto controller = _controller;
_menu->addAction(tr::lng_create_group_title(tr::now), [] {
App::wnd()->onShowNewGroup();
App::wnd()->showNewGroup();
}, &st::mainMenuNewGroup, &st::mainMenuNewGroupOver);
_menu->addAction(tr::lng_create_channel_title(tr::now), [] {
App::wnd()->onShowNewChannel();
App::wnd()->showNewChannel();
}, &st::mainMenuNewChannel, &st::mainMenuNewChannelOver);
_menu->addAction(tr::lng_menu_contacts(tr::now), [=] {
Ui::show(PrepareContactsBox(controller));
@ -883,7 +883,7 @@ void MainMenu::refreshMenu() {
}
} else {
_menu->addAction(tr::lng_profile_add_contact(tr::now), [] {
App::wnd()->onShowAddContact();
App::wnd()->showAddContact();
}, &st::mainMenuContacts, &st::mainMenuContactsOver);
const auto fix = std::make_shared<QPointer<QAction>>();

@ -1 +1 @@
Subproject commit dc89f34be5387bef731c59aeca3ca201e042ecc3
Subproject commit d7342985eb85b0ab791dee0514cffb0b05b3010d

@ -1 +1 @@
Subproject commit 9ebd51c8f89799d5b6125e34028528d52b0b0b8e
Subproject commit 912f0b48a648e7f12e7bcba82a0f0ec326aab8dd