mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-03-30 07:18:28 +00:00
Fix tray icon menu display in Fedora (Qt 5.6.2 broke it).
When activeChanged() is emitted we call updateTrayMenu(), that always called trayIcon->setContextMenu(), which was hiding the just-shown tray icon menu in case of right click with main window being active. Now we call trayIcon->setContextMenu() only if the contextMenu value has really changed for trayIcon.
This commit is contained in:
parent
40fc7379bc
commit
3503be03c9
@ -167,7 +167,7 @@ void MainWindow::init() {
|
||||
|
||||
Application::instance()->installEventFilter(this);
|
||||
connect(windowHandle(), SIGNAL(windowStateChanged(Qt::WindowState)), this, SLOT(onStateChanged(Qt::WindowState)));
|
||||
connect(windowHandle(), SIGNAL(activeChanged()), this, SLOT(checkHistoryActivation()), Qt::QueuedConnection);
|
||||
connect(windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWindowActiveChanged()), Qt::QueuedConnection);
|
||||
|
||||
QPalette p(palette());
|
||||
p.setColor(QPalette::Window, st::windowBg->c);
|
||||
@ -178,24 +178,32 @@ void MainWindow::init() {
|
||||
psInitSize();
|
||||
}
|
||||
|
||||
void MainWindow::onWindowActiveChanged() {
|
||||
checkHistoryActivation();
|
||||
QTimer::singleShot(1, this, SLOT(updateTrayMenu()));
|
||||
}
|
||||
|
||||
void MainWindow::firstShow() {
|
||||
#ifdef Q_OS_WIN
|
||||
trayIconMenu = new PopupMenu();
|
||||
trayIconMenu->deleteOnHide(false);
|
||||
#else
|
||||
#else // Q_OS_WIN
|
||||
trayIconMenu = new QMenu(this);
|
||||
#endif
|
||||
auto notificationItem = lang(Global::DesktopNotify()
|
||||
? lng_disable_notifications_from_tray : lng_enable_notifications_from_tray);
|
||||
#endif // else for Q_OS_WIN
|
||||
|
||||
if (cPlatform() == dbipWindows || cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
||||
trayIconMenu->addAction(lang(lng_minimize_to_tray), this, SLOT(minimizeToTray()))->setEnabled(true);
|
||||
trayIconMenu->addAction(notificationItem, this, SLOT(toggleDisplayNotifyFromTray()))->setEnabled(true);
|
||||
trayIconMenu->addAction(lang(lng_quit_from_tray), this, SLOT(quitFromTray()))->setEnabled(true);
|
||||
} else {
|
||||
auto isLinux = (cPlatform() == dbipLinux32 || cPlatform() == dbipLinux64);
|
||||
auto notificationActionText = lang(Global::DesktopNotify()
|
||||
? lng_disable_notifications_from_tray
|
||||
: lng_enable_notifications_from_tray);
|
||||
|
||||
if (isLinux) {
|
||||
trayIconMenu->addAction(lang(lng_open_from_tray), this, SLOT(showFromTray()))->setEnabled(true);
|
||||
trayIconMenu->addAction(lang(lng_minimize_to_tray), this, SLOT(minimizeToTray()))->setEnabled(true);
|
||||
trayIconMenu->addAction(notificationItem, this, SLOT(toggleDisplayNotifyFromTray()))->setEnabled(true);
|
||||
trayIconMenu->addAction(notificationActionText, this, SLOT(toggleDisplayNotifyFromTray()))->setEnabled(true);
|
||||
trayIconMenu->addAction(lang(lng_quit_from_tray), this, SLOT(quitFromTray()))->setEnabled(true);
|
||||
} else {
|
||||
trayIconMenu->addAction(lang(lng_minimize_to_tray), this, SLOT(minimizeToTray()))->setEnabled(true);
|
||||
trayIconMenu->addAction(notificationActionText, this, SLOT(toggleDisplayNotifyFromTray()))->setEnabled(true);
|
||||
trayIconMenu->addAction(lang(lng_quit_from_tray), this, SLOT(quitFromTray()))->setEnabled(true);
|
||||
}
|
||||
psUpdateWorkmode();
|
||||
@ -594,7 +602,6 @@ void MainWindow::checkHistoryActivation() {
|
||||
if (main && MTP::authedId() && doWeReadServerHistory()) {
|
||||
main->markActiveHistoryAsRead();
|
||||
}
|
||||
QTimer::singleShot(1, this, SLOT(updateTrayMenu()));
|
||||
}
|
||||
|
||||
void MainWindow::layerHidden() {
|
||||
@ -744,7 +751,7 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *e) {
|
||||
case QEvent::ApplicationActivate:
|
||||
if (obj == Application::instance()) {
|
||||
psUserActionDone();
|
||||
QTimer::singleShot(1, this, SLOT(checkHistoryActivation()));
|
||||
QTimer::singleShot(1, this, SLOT(onWindowActiveChanged()));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -817,29 +824,37 @@ bool MainWindow::minimizeToTray() {
|
||||
void MainWindow::updateTrayMenu(bool force) {
|
||||
if (!trayIconMenu || (cPlatform() == dbipWindows && !force)) return;
|
||||
|
||||
bool active = isActive(false);
|
||||
QString notificationItem = lang(Global::DesktopNotify()
|
||||
? lng_disable_notifications_from_tray : lng_enable_notifications_from_tray);
|
||||
|
||||
if (cPlatform() == dbipWindows || cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
||||
QAction *toggle = trayIconMenu->actions().at(0);
|
||||
disconnect(toggle, SIGNAL(triggered(bool)), this, SLOT(minimizeToTray()));
|
||||
disconnect(toggle, SIGNAL(triggered(bool)), this, SLOT(showFromTray()));
|
||||
connect(toggle, SIGNAL(triggered(bool)), this, active ? SLOT(minimizeToTray()) : SLOT(showFromTray()));
|
||||
toggle->setText(lang(active ? lng_minimize_to_tray : lng_open_from_tray));
|
||||
|
||||
trayIconMenu->actions().at(1)->setText(notificationItem);
|
||||
auto iconMenu = trayIconMenu;
|
||||
auto actions = iconMenu->actions();
|
||||
auto isLinux = (cPlatform() == dbipLinux32 || cPlatform() == dbipLinux64);
|
||||
if (isLinux) {
|
||||
auto minimizeAction = actions.at(1);
|
||||
minimizeAction->setDisabled(!isVisible());
|
||||
} else {
|
||||
QAction *minimize = trayIconMenu->actions().at(1);
|
||||
minimize->setDisabled(!isVisible());
|
||||
auto active = isActive(false);
|
||||
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(lang(active ? lng_minimize_to_tray : lng_open_from_tray));
|
||||
|
||||
trayIconMenu->actions().at(2)->setText(notificationItem);
|
||||
// On macOS just remove trayIcon menu if the window is not active.
|
||||
// So we will activate the window on click instead of showing the menu.
|
||||
if (!active && (cPlatform() == dbipMac || cPlatform() == dbipMacOld)) {
|
||||
iconMenu = nullptr;
|
||||
}
|
||||
}
|
||||
auto notificationAction = actions.at(isLinux ? 2 : 1);
|
||||
auto notificationActionText = lang(Global::DesktopNotify()
|
||||
? lng_disable_notifications_from_tray
|
||||
: lng_enable_notifications_from_tray);
|
||||
notificationAction->setText(notificationActionText);
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
if (trayIcon) {
|
||||
trayIcon->setContextMenu((active || cPlatform() == dbipLinux32 || cPlatform() == dbipLinux64) ? trayIconMenu : 0);
|
||||
if (trayIcon && trayIcon->contextMenu() != iconMenu) {
|
||||
trayIcon->setContextMenu(iconMenu);
|
||||
}
|
||||
#endif
|
||||
#endif // !Q_OS_WIN
|
||||
|
||||
psTrayMenuUpdated();
|
||||
}
|
||||
@ -902,7 +917,7 @@ void MainWindow::activate() {
|
||||
|
||||
void MainWindow::noIntro(IntroWidget *was) {
|
||||
if (was == intro) {
|
||||
intro = 0;
|
||||
intro = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,6 +126,8 @@ public:
|
||||
void noLayerStack(LayerStackWidget *was);
|
||||
void layerFinishedHide(LayerStackWidget *was);
|
||||
|
||||
void checkHistoryActivation();
|
||||
|
||||
void fixOrder();
|
||||
|
||||
enum TempDirState {
|
||||
@ -178,8 +180,6 @@ public:
|
||||
public slots:
|
||||
void updateIsActive(int timeout = 0);
|
||||
|
||||
void checkHistoryActivation();
|
||||
|
||||
void checkAutoLock();
|
||||
|
||||
void showSettings();
|
||||
@ -222,6 +222,8 @@ private slots:
|
||||
void onStateChanged(Qt::WindowState state);
|
||||
void onSettingsDestroyed(QObject *was);
|
||||
|
||||
void onWindowActiveChanged();
|
||||
|
||||
private:
|
||||
void showConnecting(const QString &text, const QString &reconnect = QString());
|
||||
void hideConnecting();
|
||||
|
@ -47,21 +47,21 @@ int32 _trayIconCount = 0;
|
||||
QImage _trayIconImageBack, _trayIconImage;
|
||||
|
||||
void _trayIconPopup(GtkStatusIcon *status_icon, guint button, guint32 activate_time, gpointer popup_menu) {
|
||||
Libs::gtk_menu_popup(Libs::gtk_menu_cast(popup_menu), NULL, NULL, Libs::gtk_status_icon_position_menu, status_icon, button, activate_time);
|
||||
Libs::gtk_menu_popup(Libs::gtk_menu_cast(popup_menu), NULL, NULL, Libs::gtk_status_icon_position_menu, status_icon, button, activate_time);
|
||||
}
|
||||
|
||||
void _trayIconActivate(GtkStatusIcon *status_icon, gpointer popup_menu) {
|
||||
if (App::wnd()->isActiveWindow() && App::wnd()->isVisible()) {
|
||||
Libs::gtk_menu_popup(Libs::gtk_menu_cast(popup_menu), NULL, NULL, Libs::gtk_status_icon_position_menu, status_icon, 0, Libs::gtk_get_current_event_time());
|
||||
} else {
|
||||
App::wnd()->showFromTray();
|
||||
}
|
||||
if (App::wnd()->isActiveWindow() && App::wnd()->isVisible()) {
|
||||
Libs::gtk_menu_popup(Libs::gtk_menu_cast(popup_menu), NULL, NULL, Libs::gtk_status_icon_position_menu, status_icon, 0, Libs::gtk_get_current_event_time());
|
||||
} else {
|
||||
App::wnd()->showFromTray();
|
||||
}
|
||||
}
|
||||
|
||||
gboolean _trayIconResized(GtkStatusIcon *status_icon, gint size, gpointer popup_menu) {
|
||||
_trayIconSize = size;
|
||||
if (App::wnd()) App::wnd()->psUpdateCounter();
|
||||
return FALSE;
|
||||
_trayIconSize = size;
|
||||
if (App::wnd()) App::wnd()->psUpdateCounter();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#define QT_RED 0
|
||||
@ -77,98 +77,98 @@ gboolean _trayIconResized(GtkStatusIcon *status_icon, gint size, gpointer popup_
|
||||
QImage _trayIconImageGen() {
|
||||
int32 counter = App::histories().unreadBadge(), counterSlice = (counter >= 1000) ? (1000 + (counter % 100)) : counter;
|
||||
bool muted = App::histories().unreadOnlyMuted();
|
||||
if (_trayIconImage.isNull() || _trayIconImage.width() != _trayIconSize || muted != _trayIconMuted || counterSlice != _trayIconCount) {
|
||||
if (_trayIconImageBack.isNull() || _trayIconImageBack.width() != _trayIconSize) {
|
||||
_trayIconImageBack = App::wnd()->iconLarge().scaled(_trayIconSize, _trayIconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
_trayIconImageBack = _trayIconImageBack.convertToFormat(QImage::Format_ARGB32);
|
||||
int w = _trayIconImageBack.width(), h = _trayIconImageBack.height(), perline = _trayIconImageBack.bytesPerLine();
|
||||
uchar *bytes = _trayIconImageBack.bits();
|
||||
for (int32 y = 0; y < h; ++y) {
|
||||
for (int32 x = 0; x < w; ++x) {
|
||||
int32 srcoff = y * perline + x * 4;
|
||||
bytes[srcoff + QT_RED ] = qMax(bytes[srcoff + QT_RED ], uchar(224));
|
||||
bytes[srcoff + QT_GREEN] = qMax(bytes[srcoff + QT_GREEN], uchar(165));
|
||||
bytes[srcoff + QT_BLUE ] = qMax(bytes[srcoff + QT_BLUE ], uchar(44));
|
||||
}
|
||||
}
|
||||
}
|
||||
_trayIconImage = _trayIconImageBack;
|
||||
if (counter > 0) {
|
||||
QPainter p(&_trayIconImage);
|
||||
int32 layerSize = -16;
|
||||
if (_trayIconSize >= 48) {
|
||||
layerSize = -32;
|
||||
} else if (_trayIconSize >= 36) {
|
||||
layerSize = -24;
|
||||
} else if (_trayIconSize >= 32) {
|
||||
layerSize = -20;
|
||||
}
|
||||
QImage layer = App::wnd()->iconWithCounter(layerSize, counter, (muted ? st::counterMuteBG : st::counterBG), false);
|
||||
p.drawImage(_trayIconImage.width() - layer.width() - 1, _trayIconImage.height() - layer.height() - 1, layer);
|
||||
}
|
||||
}
|
||||
return _trayIconImage;
|
||||
if (_trayIconImage.isNull() || _trayIconImage.width() != _trayIconSize || muted != _trayIconMuted || counterSlice != _trayIconCount) {
|
||||
if (_trayIconImageBack.isNull() || _trayIconImageBack.width() != _trayIconSize) {
|
||||
_trayIconImageBack = App::wnd()->iconLarge().scaled(_trayIconSize, _trayIconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
_trayIconImageBack = _trayIconImageBack.convertToFormat(QImage::Format_ARGB32);
|
||||
int w = _trayIconImageBack.width(), h = _trayIconImageBack.height(), perline = _trayIconImageBack.bytesPerLine();
|
||||
uchar *bytes = _trayIconImageBack.bits();
|
||||
for (int32 y = 0; y < h; ++y) {
|
||||
for (int32 x = 0; x < w; ++x) {
|
||||
int32 srcoff = y * perline + x * 4;
|
||||
bytes[srcoff + QT_RED ] = qMax(bytes[srcoff + QT_RED ], uchar(224));
|
||||
bytes[srcoff + QT_GREEN] = qMax(bytes[srcoff + QT_GREEN], uchar(165));
|
||||
bytes[srcoff + QT_BLUE ] = qMax(bytes[srcoff + QT_BLUE ], uchar(44));
|
||||
}
|
||||
}
|
||||
}
|
||||
_trayIconImage = _trayIconImageBack;
|
||||
if (counter > 0) {
|
||||
QPainter p(&_trayIconImage);
|
||||
int32 layerSize = -16;
|
||||
if (_trayIconSize >= 48) {
|
||||
layerSize = -32;
|
||||
} else if (_trayIconSize >= 36) {
|
||||
layerSize = -24;
|
||||
} else if (_trayIconSize >= 32) {
|
||||
layerSize = -20;
|
||||
}
|
||||
QImage layer = App::wnd()->iconWithCounter(layerSize, counter, (muted ? st::counterMuteBG : st::counterBG), false);
|
||||
p.drawImage(_trayIconImage.width() - layer.width() - 1, _trayIconImage.height() - layer.height() - 1, layer);
|
||||
}
|
||||
}
|
||||
return _trayIconImage;
|
||||
}
|
||||
|
||||
QString _trayIconImageFile() {
|
||||
int32 counter = App::histories().unreadBadge(), counterSlice = (counter >= 1000) ? (1000 + (counter % 100)) : counter;
|
||||
bool muted = App::histories().unreadOnlyMuted();
|
||||
|
||||
QString name = cWorkingDir() + qsl("tdata/ticons/ico%1_%2_%3.png").arg(muted ? "mute" : "").arg(_trayIconSize).arg(counterSlice);
|
||||
QFileInfo info(name);
|
||||
if (info.exists()) return name;
|
||||
QString name = cWorkingDir() + qsl("tdata/ticons/ico%1_%2_%3.png").arg(muted ? "mute" : "").arg(_trayIconSize).arg(counterSlice);
|
||||
QFileInfo info(name);
|
||||
if (info.exists()) return name;
|
||||
|
||||
QImage img = _trayIconImageGen();
|
||||
if (img.save(name, "PNG")) return name;
|
||||
QImage img = _trayIconImageGen();
|
||||
if (img.save(name, "PNG")) return name;
|
||||
|
||||
QDir dir(info.absoluteDir());
|
||||
if (!dir.exists()) {
|
||||
dir.mkpath(dir.absolutePath());
|
||||
if (img.save(name, "PNG")) return name;
|
||||
}
|
||||
QDir dir(info.absoluteDir());
|
||||
if (!dir.exists()) {
|
||||
dir.mkpath(dir.absolutePath());
|
||||
if (img.save(name, "PNG")) return name;
|
||||
}
|
||||
|
||||
return QString();
|
||||
return QString();
|
||||
}
|
||||
|
||||
void loadPixbuf(QImage image) {
|
||||
int w = image.width(), h = image.height(), perline = image.bytesPerLine(), s = image.byteCount();
|
||||
_trayPixbufData.resize(w * h * 4);
|
||||
uchar *result = (uchar*)_trayPixbufData.data(), *bytes = image.bits();
|
||||
for (int32 y = 0; y < h; ++y) {
|
||||
for (int32 x = 0; x < w; ++x) {
|
||||
int32 offset = (y * w + x) * 4, srcoff = y * perline + x * 4;
|
||||
result[offset + GTK_RED ] = bytes[srcoff + QT_RED ];
|
||||
result[offset + GTK_GREEN] = bytes[srcoff + QT_GREEN];
|
||||
result[offset + GTK_BLUE ] = bytes[srcoff + QT_BLUE ];
|
||||
result[offset + GTK_ALPHA] = bytes[srcoff + QT_ALPHA];
|
||||
}
|
||||
}
|
||||
int w = image.width(), h = image.height(), perline = image.bytesPerLine(), s = image.byteCount();
|
||||
_trayPixbufData.resize(w * h * 4);
|
||||
uchar *result = (uchar*)_trayPixbufData.data(), *bytes = image.bits();
|
||||
for (int32 y = 0; y < h; ++y) {
|
||||
for (int32 x = 0; x < w; ++x) {
|
||||
int32 offset = (y * w + x) * 4, srcoff = y * perline + x * 4;
|
||||
result[offset + GTK_RED ] = bytes[srcoff + QT_RED ];
|
||||
result[offset + GTK_GREEN] = bytes[srcoff + QT_GREEN];
|
||||
result[offset + GTK_BLUE ] = bytes[srcoff + QT_BLUE ];
|
||||
result[offset + GTK_ALPHA] = bytes[srcoff + QT_ALPHA];
|
||||
}
|
||||
}
|
||||
|
||||
if (_trayPixbuf) Libs::g_object_unref(_trayPixbuf);
|
||||
_trayPixbuf = Libs::gdk_pixbuf_new_from_data(result, GDK_COLORSPACE_RGB, true, 8, w, h, w * 4, 0, 0);
|
||||
if (_trayPixbuf) Libs::g_object_unref(_trayPixbuf);
|
||||
_trayPixbuf = Libs::gdk_pixbuf_new_from_data(result, GDK_COLORSPACE_RGB, true, 8, w, h, w * 4, 0, 0);
|
||||
}
|
||||
|
||||
void _trayMenuCallback(GtkMenu *menu, gpointer data) {
|
||||
for (int32 i = 0, l = _trayItems.size(); i < l; ++i) {
|
||||
if ((void*)_trayItems.at(i).first == (void*)menu) {
|
||||
QMetaObject::invokeMethod(_trayItems.at(i).second, "triggered");
|
||||
}
|
||||
}
|
||||
for (int32 i = 0, l = _trayItems.size(); i < l; ++i) {
|
||||
if ((void*)_trayItems.at(i).first == (void*)menu) {
|
||||
QMetaObject::invokeMethod(_trayItems.at(i).second, "triggered");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean _trayIconCheck(gpointer/* pIn*/) {
|
||||
if (useStatusIcon && !trayIconChecked) {
|
||||
if (Libs::gtk_status_icon_is_embedded(_trayIcon)) {
|
||||
trayIconChecked = true;
|
||||
cSetSupportTray(true);
|
||||
if (App::wnd()) {
|
||||
App::wnd()->psUpdateWorkmode();
|
||||
App::wnd()->psUpdateCounter();
|
||||
App::wnd()->updateTrayMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
if (useStatusIcon && !trayIconChecked) {
|
||||
if (Libs::gtk_status_icon_is_embedded(_trayIcon)) {
|
||||
trayIconChecked = true;
|
||||
cSetSupportTray(true);
|
||||
if (App::wnd()) {
|
||||
App::wnd()->psUpdateWorkmode();
|
||||
App::wnd()->psUpdateCounter();
|
||||
App::wnd()->updateTrayMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
|
||||
@ -237,9 +237,9 @@ void MainWindow::psSetupTrayIcon() {
|
||||
if (!cSupportTray()) return;
|
||||
psUpdateCounter();
|
||||
} else {
|
||||
LOG(("Using Qt tray icon."));
|
||||
if (!trayIcon) {
|
||||
trayIcon = new QSystemTrayIcon(this);
|
||||
|
||||
QIcon icon;
|
||||
QFileInfo iconFile(_trayIconImageFile());
|
||||
if (iconFile.exists()) {
|
||||
@ -532,7 +532,7 @@ void MainWindow::psCreateTrayIcon() {
|
||||
QByteArray path = QFile::encodeName(iconFile.absoluteFilePath());
|
||||
_trayIndicator = Libs::app_indicator_new("Telegram Desktop", path.constData(), APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
|
||||
if (_trayIndicator) {
|
||||
DEBUG_LOG(("Created appindicator!"));
|
||||
LOG(("Using appindicator tray icon."));
|
||||
} else {
|
||||
DEBUG_LOG(("Failed to app_indicator_new()!"));
|
||||
}
|
||||
@ -565,6 +565,8 @@ void MainWindow::psCreateTrayIcon() {
|
||||
_trayIcon = Libs::gtk_status_icon_new_from_pixbuf(_trayPixbuf);
|
||||
}
|
||||
if (_trayIcon) {
|
||||
LOG(("Using GTK status tray icon."));
|
||||
|
||||
Libs::g_signal_connect_helper(_trayIcon, "popup-menu", GCallback(_trayIconPopup), _trayMenu);
|
||||
Libs::g_signal_connect_helper(_trayIcon, "activate", GCallback(_trayIconActivate), _trayMenu);
|
||||
Libs::g_signal_connect_helper(_trayIcon, "size-changed", GCallback(_trayIconResized), _trayMenu);
|
||||
|
Loading…
Reference in New Issue
Block a user