mirror of
https://github.com/kotatogram/kotatogram-desktop
synced 2025-08-31 06:35:14 +00:00
Use LXQt's StatusNotifierItem implementation instead of appindicator
This commit is contained in:
@@ -9,10 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
#include "platform/linux/specific_linux.h"
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
#include <QDBusInterface>
|
||||
#endif
|
||||
|
||||
namespace Platform {
|
||||
namespace DesktopEnvironment {
|
||||
namespace {
|
||||
@@ -44,18 +40,15 @@ Type Compute() {
|
||||
return Type::Gnome;
|
||||
}
|
||||
return Type::Unity;
|
||||
} else if (list.contains("pantheon")) {
|
||||
return Type::Pantheon;
|
||||
} else if (list.contains("gnome")) {
|
||||
if (list.contains("ubuntu"))
|
||||
return Type::Ubuntu;
|
||||
|
||||
return Type::Gnome;
|
||||
} else if (list.contains("kde")) {
|
||||
if (kdeSession == qstr("5")) {
|
||||
return Type::KDE5;
|
||||
}
|
||||
return Type::KDE4;
|
||||
} else if (list.contains("mate")) {
|
||||
return Type::MATE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +63,8 @@ Type Compute() {
|
||||
return Type::KDE4;
|
||||
}
|
||||
return Type::KDE3;
|
||||
} else if (desktopSession == qstr("mate")) {
|
||||
return Type::MATE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,9 +91,8 @@ Type ComputeAndLog() {
|
||||
case Type::KDE3: return "KDE3";
|
||||
case Type::KDE4: return "KDE4";
|
||||
case Type::KDE5: return "KDE5";
|
||||
case Type::Ubuntu: return "Ubuntu";
|
||||
case Type::Unity: return "Unity";
|
||||
case Type::Pantheon: return "Pantheon";
|
||||
case Type::MATE: return "MATE";
|
||||
}
|
||||
return QString::number(static_cast<int>(result));
|
||||
};
|
||||
@@ -114,20 +108,5 @@ Type Get() {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool TryQtTrayIcon() {
|
||||
return !IsPantheon();
|
||||
}
|
||||
|
||||
bool PreferAppIndicatorTrayIcon() {
|
||||
return (InSandbox() && !IsKDE())
|
||||
|| IsUnity()
|
||||
|| IsUbuntu()
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
|| (IsGnome() && QDBusInterface("org.kde.StatusNotifierWatcher", "/").isValid());
|
||||
#else
|
||||
|| IsGnome();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace DesktopEnvironment
|
||||
} // namespace Platform
|
||||
|
@@ -16,9 +16,8 @@ enum class Type {
|
||||
KDE3,
|
||||
KDE4,
|
||||
KDE5,
|
||||
Ubuntu,
|
||||
Unity,
|
||||
Pantheon,
|
||||
MATE,
|
||||
};
|
||||
|
||||
Type Get();
|
||||
@@ -43,20 +42,13 @@ inline bool IsKDE() {
|
||||
return IsKDE3() || IsKDE4() || IsKDE5();
|
||||
}
|
||||
|
||||
inline bool IsUbuntu() {
|
||||
return Get() == Type::Ubuntu;
|
||||
}
|
||||
|
||||
inline bool IsUnity() {
|
||||
return Get() == Type::Unity;
|
||||
}
|
||||
|
||||
inline bool IsPantheon() {
|
||||
return Get() == Type::Pantheon;
|
||||
inline bool IsMATE() {
|
||||
return Get() == Type::MATE;
|
||||
}
|
||||
|
||||
bool TryQtTrayIcon();
|
||||
bool PreferAppIndicatorTrayIcon();
|
||||
|
||||
} // namespace DesktopEnvironment
|
||||
} // namespace Platform
|
||||
|
@@ -126,16 +126,6 @@ bool setupGtkBase(QLibrary &lib_gtk) {
|
||||
DEBUG_LOG(("Checked gtk with gtk_init_check!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool setupAppIndicator(QLibrary &lib_indicator) {
|
||||
if (!load(lib_indicator, "app_indicator_new", app_indicator_new)) return false;
|
||||
if (!load(lib_indicator, "app_indicator_set_status", app_indicator_set_status)) return false;
|
||||
if (!load(lib_indicator, "app_indicator_set_menu", app_indicator_set_menu)) return false;
|
||||
if (!load(lib_indicator, "app_indicator_set_icon_full", app_indicator_set_icon_full)) return false;
|
||||
|
||||
DEBUG_LOG(("Library appindicator functions loaded!"));
|
||||
return true;
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
|
||||
} // namespace
|
||||
@@ -197,10 +187,6 @@ f_g_type_check_instance_cast g_type_check_instance_cast = nullptr;
|
||||
f_g_type_check_instance_is_a g_type_check_instance_is_a = nullptr;
|
||||
f_g_signal_connect_data g_signal_connect_data = nullptr;
|
||||
f_g_signal_handler_disconnect g_signal_handler_disconnect = nullptr;
|
||||
f_app_indicator_new app_indicator_new = nullptr;
|
||||
f_app_indicator_set_status app_indicator_set_status = nullptr;
|
||||
f_app_indicator_set_menu app_indicator_set_menu = nullptr;
|
||||
f_app_indicator_set_icon_full app_indicator_set_icon_full = nullptr;
|
||||
f_gdk_init_check gdk_init_check = nullptr;
|
||||
f_gdk_pixbuf_new_from_data gdk_pixbuf_new_from_data = nullptr;
|
||||
f_gdk_pixbuf_new_from_file gdk_pixbuf_new_from_file = nullptr;
|
||||
@@ -233,33 +219,14 @@ void start() {
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
|
||||
bool gtkLoaded = false;
|
||||
bool indicatorLoaded = false;
|
||||
bool isWayland = QGuiApplication::platformName().startsWith(qsl("wayland"), Qt::CaseInsensitive);
|
||||
QLibrary lib_gtk, lib_indicator;
|
||||
if (loadLibrary(lib_indicator, "ayatana-appindicator3", 1) || loadLibrary(lib_indicator, "appindicator3", 1)) {
|
||||
if (loadLibrary(lib_gtk, "gtk-3", 0)) {
|
||||
gtkLoaded = setupGtkBase(lib_gtk);
|
||||
indicatorLoaded = setupAppIndicator(lib_indicator);
|
||||
}
|
||||
}
|
||||
if ((!gtkLoaded || !indicatorLoaded) && !isWayland) {
|
||||
if (loadLibrary(lib_indicator, "ayatana-appindicator", 1) || loadLibrary(lib_indicator, "appindicator", 1)) {
|
||||
if (loadLibrary(lib_gtk, "gtk-x11-2.0", 0)) {
|
||||
gtkLoaded = indicatorLoaded = false;
|
||||
gtkLoaded = setupGtkBase(lib_gtk);
|
||||
indicatorLoaded = setupAppIndicator(lib_indicator);
|
||||
}
|
||||
}
|
||||
}
|
||||
QLibrary lib_gtk;
|
||||
|
||||
// If no appindicator, try at least load gtk.
|
||||
if (!gtkLoaded && !indicatorLoaded) {
|
||||
if (loadLibrary(lib_gtk, "gtk-3", 0)) {
|
||||
gtkLoaded = setupGtkBase(lib_gtk);
|
||||
}
|
||||
if (!gtkLoaded && !isWayland && loadLibrary(lib_gtk, "gtk-x11-2.0", 0)) {
|
||||
gtkLoaded = setupGtkBase(lib_gtk);
|
||||
}
|
||||
if (loadLibrary(lib_gtk, "gtk-3", 0)) {
|
||||
gtkLoaded = setupGtkBase(lib_gtk);
|
||||
}
|
||||
if (!gtkLoaded && !isWayland && loadLibrary(lib_gtk, "gtk-x11-2.0", 0)) {
|
||||
gtkLoaded = setupGtkBase(lib_gtk);
|
||||
}
|
||||
|
||||
if (gtkLoaded) {
|
||||
@@ -287,7 +254,7 @@ void start() {
|
||||
load(lib_gtk, "gtk_button_set_label", gtk_button_set_label);
|
||||
load(lib_gtk, "gtk_button_get_type", gtk_button_get_type);
|
||||
} else {
|
||||
LOG(("Could not load gtk-x11-2.0!"));
|
||||
LOG(("Could not load gtk-3 or gtk-x11-2.0!"));
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
}
|
||||
|
@@ -13,11 +13,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
extern "C" {
|
||||
#undef signals
|
||||
#ifdef TDESKTOP_USE_AYATANA_INDICATORS
|
||||
#include <libayatana-appindicator/app-indicator.h>
|
||||
#else
|
||||
#include <libappindicator/app-indicator.h>
|
||||
#endif
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdk.h>
|
||||
#define signals public
|
||||
@@ -278,18 +273,6 @@ inline gulong g_signal_connect_swapped_helper(gpointer instance, const gchar *de
|
||||
typedef void (*f_g_signal_handler_disconnect)(gpointer instance, gulong handler_id);
|
||||
extern f_g_signal_handler_disconnect g_signal_handler_disconnect;
|
||||
|
||||
typedef AppIndicator* (*f_app_indicator_new)(const gchar *id, const gchar *icon_name, AppIndicatorCategory category);
|
||||
extern f_app_indicator_new app_indicator_new;
|
||||
|
||||
typedef void (*f_app_indicator_set_status)(AppIndicator *self, AppIndicatorStatus status);
|
||||
extern f_app_indicator_set_status app_indicator_set_status;
|
||||
|
||||
typedef void (*f_app_indicator_set_menu)(AppIndicator *self, GtkMenu *menu);
|
||||
extern f_app_indicator_set_menu app_indicator_set_menu;
|
||||
|
||||
typedef void (*f_app_indicator_set_icon_full)(AppIndicator *self, const gchar *icon_name, const gchar *icon_desc);
|
||||
extern f_app_indicator_set_icon_full app_indicator_set_icon_full;
|
||||
|
||||
typedef gboolean (*f_gdk_init_check)(gint *argc, gchar ***argv);
|
||||
extern f_gdk_init_check gdk_init_check;
|
||||
|
||||
|
@@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "history/history.h"
|
||||
#include "mainwindow.h"
|
||||
#include "core/application.h"
|
||||
#include "core/sandbox.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "facades.h"
|
||||
@@ -22,101 +23,77 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
#include <QtDBus>
|
||||
#endif
|
||||
|
||||
#include <QtWidgets/QMenu>
|
||||
#include <QtWidgets/QAction>
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
namespace Platform {
|
||||
namespace {
|
||||
|
||||
bool noQtTrayIcon = false, tryAppIndicator = false;
|
||||
bool useGtkBase = false, useAppIndicator = false, useStatusIcon = false, trayIconChecked = false, useUnityCount = false;
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
AppIndicator *_trayIndicator = 0;
|
||||
GtkStatusIcon *_trayIcon = 0;
|
||||
GtkWidget *_trayMenu = 0;
|
||||
GdkPixbuf *_trayPixbuf = 0;
|
||||
QByteArray _trayPixbufData;
|
||||
QList<QPair<GtkWidget*, QObject*> > _trayItems;
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
constexpr auto kDisableTrayCounter = "TDESKTOP_DISABLE_TRAY_COUNTER"_cs;
|
||||
constexpr auto kTrayIconName = "telegram"_cs;
|
||||
constexpr auto kPanelTrayIconName = "telegram-panel"_cs;
|
||||
constexpr auto kMutePanelTrayIconName = "telegram-mute-panel"_cs;
|
||||
constexpr auto kAttentionPanelTrayIconName = "telegram-attention-panel"_cs;
|
||||
constexpr auto kSNIWatcherService = "org.kde.StatusNotifierWatcher"_cs;
|
||||
constexpr auto kTrayIconFilename = "tdesktop-trayicon-XXXXXX.png"_cs;
|
||||
|
||||
int32 _trayIconSize = 48;
|
||||
bool _trayIconMuted = true;
|
||||
int32 _trayIconCount = 0;
|
||||
QImage _trayIconImageBack, _trayIconImage;
|
||||
QString _trayIconThemeName, _trayIconName;
|
||||
QString _desktopFile;
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
QString _dbusPath = "/";
|
||||
#endif
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
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);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
gboolean _trayIconResized(GtkStatusIcon *status_icon, gint size, gpointer popup_menu) {
|
||||
_trayIconSize = size;
|
||||
if (Global::started()) Notify::unreadCounterUpdated();
|
||||
return FALSE;
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
bool UseUnityCount = false;
|
||||
QString UnityCountDesktopFile;
|
||||
QString UnityCountDBusPath = "/";
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
#define QT_RED 0
|
||||
#define QT_GREEN 1
|
||||
#define QT_BLUE 2
|
||||
#define QT_ALPHA 3
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
#define GTK_RED 2
|
||||
#define GTK_GREEN 1
|
||||
#define GTK_BLUE 0
|
||||
#define GTK_ALPHA 3
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
QString GetTrayIconName() {
|
||||
const auto counter = Core::App().unreadBadge();
|
||||
const auto muted = Core::App().unreadBadgeMuted();
|
||||
|
||||
QImage _trayIconImageGen(bool useSystemIcon) {
|
||||
return (counter > 0)
|
||||
? (muted
|
||||
? kMutePanelTrayIconName.utf16()
|
||||
: kAttentionPanelTrayIconName.utf16())
|
||||
: kPanelTrayIconName.utf16();
|
||||
}
|
||||
|
||||
QImage TrayIconImageGen() {
|
||||
const auto counter = Core::App().unreadBadge();
|
||||
const auto muted = Core::App().unreadBadgeMuted();
|
||||
const auto counterSlice = (counter >= 1000)
|
||||
? (1000 + (counter % 100))
|
||||
: counter;
|
||||
|
||||
QString iconThemeName = QIcon::themeName();
|
||||
QString iconName = (counter > 0)
|
||||
? (muted ? "telegram-mute-panel" : "telegram-attention-panel")
|
||||
: "telegram-panel";
|
||||
const auto iconThemeName = QIcon::themeName();
|
||||
const auto iconName = GetTrayIconName();
|
||||
|
||||
if (_trayIconImage.isNull() || _trayIconImage.width() != _trayIconSize
|
||||
|| (useSystemIcon && (iconThemeName != _trayIconThemeName
|
||||
|| iconName != _trayIconName))
|
||||
|| muted != _trayIconMuted || counterSlice != _trayIconCount) {
|
||||
if (_trayIconImage.isNull()
|
||||
|| _trayIconImage.width() != _trayIconSize
|
||||
|| iconThemeName != _trayIconThemeName
|
||||
|| iconName != _trayIconName
|
||||
|| muted != _trayIconMuted
|
||||
|| counterSlice != _trayIconCount) {
|
||||
if (_trayIconImageBack.isNull()
|
||||
|| _trayIconImageBack.width() != _trayIconSize
|
||||
|| iconThemeName != _trayIconThemeName
|
||||
|| iconName != _trayIconName) {
|
||||
_trayIconImageBack = Core::App().logo();
|
||||
|
||||
if (useSystemIcon) {
|
||||
_trayIconImageBack = QIcon::fromTheme(
|
||||
iconName,
|
||||
QIcon::fromTheme(
|
||||
"telegram",
|
||||
QIcon(QPixmap::fromImage(_trayIconImageBack)))
|
||||
).pixmap(_trayIconSize, _trayIconSize).toImage();
|
||||
}
|
||||
_trayIconImageBack = QIcon::fromTheme(
|
||||
iconName,
|
||||
QIcon::fromTheme(
|
||||
kTrayIconName.utf16(),
|
||||
QIcon(QPixmap::fromImage(_trayIconImageBack)))
|
||||
).pixmap(_trayIconSize, _trayIconSize).toImage();
|
||||
|
||||
int w = _trayIconImageBack.width(),
|
||||
auto w = _trayIconImageBack.width(),
|
||||
h = _trayIconImageBack.height();
|
||||
|
||||
if (w != _trayIconSize || h != _trayIconSize) {
|
||||
@@ -132,8 +109,8 @@ QImage _trayIconImageGen(bool useSystemIcon) {
|
||||
|
||||
w = _trayIconImageBack.width();
|
||||
h = _trayIconImageBack.height();
|
||||
int perline = _trayIconImageBack.bytesPerLine();
|
||||
uchar *bytes = _trayIconImageBack.bits();
|
||||
const auto perline = _trayIconImageBack.bytesPerLine();
|
||||
auto *bytes = _trayIconImageBack.bits();
|
||||
|
||||
for (int32 y = 0; y < h; ++y) {
|
||||
for (int32 x = 0; x < w; ++x) {
|
||||
@@ -189,81 +166,66 @@ QImage _trayIconImageGen(bool useSystemIcon) {
|
||||
return _trayIconImage;
|
||||
}
|
||||
|
||||
QString _trayIconImageFile() {
|
||||
const auto counter = Core::App().unreadBadge();
|
||||
const auto muted = Core::App().unreadBadgeMuted();
|
||||
const auto counterSlice = (counter >= 1000)
|
||||
? (1000 + (counter % 100))
|
||||
: counter;
|
||||
|
||||
QString iconThemeName = QIcon::themeName();
|
||||
|
||||
QString name = cWorkingDir() + qsl("tdata/ticons/icon%1_%2_%3_%4.png")
|
||||
.arg(muted ? "mute" : "")
|
||||
.arg(iconThemeName)
|
||||
.arg(_trayIconSize)
|
||||
.arg(counterSlice);
|
||||
|
||||
QFileInfo info(name);
|
||||
if (info.exists()) return name;
|
||||
|
||||
QImage img = _trayIconImageGen(false);
|
||||
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();
|
||||
}
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
|
||||
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];
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
static bool NeedTrayIconFile() {
|
||||
// Hack for indicator-application, which doesn't handle icons sent across D-Bus:
|
||||
// save the icon to a temp file and set the icon name to that filename.
|
||||
static const auto TrayIconFileNeeded = [&] {
|
||||
auto necessary = false;
|
||||
const auto session = QDBusConnection::sessionBus();
|
||||
const auto pid = session.interface()
|
||||
->servicePid(kSNIWatcherService.utf16()).value();
|
||||
const auto processName = ProcessNameByPID(QString::number(pid));
|
||||
necessary = processName.endsWith(
|
||||
qsl("indicator-application-service"));
|
||||
if (!necessary) {
|
||||
// Accessing to process name might be not allowed if the application
|
||||
// is confined, thus we can just rely on the current desktop in use
|
||||
necessary = DesktopEnvironment::IsUnity()
|
||||
|| DesktopEnvironment::IsMATE();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
return necessary;
|
||||
}();
|
||||
return TrayIconFileNeeded;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
static inline QString TrayIconFileTemplate() {
|
||||
static const auto TempFileTemplate = AppRuntimeDirectory()
|
||||
+ kTrayIconFilename.utf16();
|
||||
return TempFileTemplate;
|
||||
}
|
||||
|
||||
static gboolean _trayIconCheck(gpointer/* pIn*/) {
|
||||
if (useStatusIcon && !trayIconChecked) {
|
||||
if (Libs::gtk_status_icon_is_embedded(_trayIcon)) {
|
||||
trayIconChecked = true;
|
||||
cSetSupportTray(true);
|
||||
if (Global::started()) {
|
||||
Global::RefWorkMode().setForced(Global::WorkMode().value(), true);
|
||||
}
|
||||
if (App::wnd()) {
|
||||
Notify::unreadCounterUpdated();
|
||||
App::wnd()->updateTrayMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
std::unique_ptr<QTemporaryFile> TrayIconFile(
|
||||
const QPixmap &icon, QObject *parent) {
|
||||
auto ret = std::make_unique<QTemporaryFile>(
|
||||
TrayIconFileTemplate(),
|
||||
parent);
|
||||
ret->open();
|
||||
icon.save(ret.get());
|
||||
ret->close();
|
||||
return ret;
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
bool IsSNIAvailable() {
|
||||
static const auto SNIAvailable = [&] {
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
QDBusInterface systrayHost(
|
||||
kSNIWatcherService.utf16(),
|
||||
qsl("/StatusNotifierWatcher"),
|
||||
kSNIWatcherService.utf16());
|
||||
|
||||
return systrayHost.isValid()
|
||||
&& systrayHost
|
||||
.property("IsStatusNotifierHostRegistered")
|
||||
.toBool();
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
return false;
|
||||
}();
|
||||
|
||||
return SNIAvailable;
|
||||
}
|
||||
|
||||
quint32 djbStringHash(QString string) {
|
||||
quint32 hash = 5381;
|
||||
@@ -278,71 +240,106 @@ quint32 djbStringHash(QString string) {
|
||||
|
||||
MainWindow::MainWindow(not_null<Window::Controller*> controller)
|
||||
: Window::MainWindow(controller) {
|
||||
connect(&_psCheckStatusIconTimer, SIGNAL(timeout()), this, SLOT(psStatusIconCheck()));
|
||||
_psCheckStatusIconTimer.setSingleShot(false);
|
||||
|
||||
connect(&_psUpdateIndicatorTimer, SIGNAL(timeout()), this, SLOT(psUpdateIndicator()));
|
||||
_psUpdateIndicatorTimer.setSingleShot(true);
|
||||
}
|
||||
|
||||
bool MainWindow::hasTrayIcon() const {
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
return trayIcon || ((useAppIndicator || (useStatusIcon && trayIconChecked)) && (Global::WorkMode().value() != dbiwmWindowOnly));
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
return trayIcon || _sniTrayIcon;
|
||||
#else
|
||||
return trayIcon;
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
}
|
||||
|
||||
void MainWindow::psStatusIconCheck() {
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
_trayIconCheck(0);
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
if (cSupportTray() || !--_psCheckStatusIconLeft) {
|
||||
_psCheckStatusIconTimer.stop();
|
||||
return;
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
}
|
||||
|
||||
void MainWindow::psShowTrayMenu() {
|
||||
if (!IsSNIAvailable()) {
|
||||
_trayIconMenuXEmbed->popup(QCursor::pos());
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::psTrayMenuUpdated() {
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
if (noQtTrayIcon && (useAppIndicator || useStatusIcon)) {
|
||||
const QList<QAction*> &actions = trayIconMenu->actions();
|
||||
if (_trayItems.isEmpty()) {
|
||||
DEBUG_LOG(("Creating tray menu!"));
|
||||
for (int32 i = 0, l = actions.size(); i != l; ++i) {
|
||||
GtkWidget *item = Libs::gtk_menu_item_new_with_label(actions.at(i)->text().toUtf8());
|
||||
Libs::gtk_menu_shell_append(Libs::gtk_menu_shell_cast(_trayMenu), item);
|
||||
Libs::g_signal_connect_helper(item, "activate", G_CALLBACK(_trayMenuCallback), this);
|
||||
Libs::gtk_widget_show(item);
|
||||
Libs::gtk_widget_set_sensitive(item, actions.at(i)->isEnabled());
|
||||
|
||||
_trayItems.push_back(qMakePair(item, actions.at(i)));
|
||||
}
|
||||
} else {
|
||||
DEBUG_LOG(("Updating tray menu!"));
|
||||
for (int32 i = 0, l = actions.size(); i != l; ++i) {
|
||||
if (i < _trayItems.size()) {
|
||||
Libs::gtk_menu_item_set_label(reinterpret_cast<GtkMenuItem*>(_trayItems.at(i).first), actions.at(i)->text().toUtf8());
|
||||
Libs::gtk_widget_set_sensitive(_trayItems.at(i).first, actions.at(i)->isEnabled());
|
||||
}
|
||||
}
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
if (IsSNIAvailable()) {
|
||||
if (_sniTrayIcon && trayIconMenu) {
|
||||
_sniTrayIcon->setContextMenu(trayIconMenu);
|
||||
}
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
}
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
void MainWindow::setSNITrayIcon(
|
||||
const QIcon &icon, const QPixmap &iconPixmap) {
|
||||
if (!NeedTrayIconFile()) {
|
||||
_sniTrayIcon->setIconByPixmap(icon);
|
||||
_sniTrayIcon->setToolTipIconByPixmap(icon);
|
||||
}
|
||||
|
||||
if (qEnvironmentVariableIsSet(kDisableTrayCounter.utf8())) {
|
||||
const auto iconName = GetTrayIconName();
|
||||
_sniTrayIcon->setIconByName(iconName);
|
||||
_sniTrayIcon->setToolTipIconByName(iconName);
|
||||
} else if (NeedTrayIconFile()) {
|
||||
_trayIconFile = TrayIconFile(iconPixmap, this);
|
||||
|
||||
if (_trayIconFile) {
|
||||
_sniTrayIcon->setIconByName(_trayIconFile->fileName());
|
||||
_sniTrayIcon->setToolTipIconByName(_trayIconFile->fileName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::attachToSNITrayIcon() {
|
||||
_sniTrayIcon->setToolTipTitle(AppName.utf16());
|
||||
connect(_sniTrayIcon,
|
||||
&StatusNotifierItem::activateRequested,
|
||||
this,
|
||||
[=](const QPoint &) {
|
||||
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
||||
handleTrayIconActication(QSystemTrayIcon::Trigger);
|
||||
});
|
||||
});
|
||||
connect(_sniTrayIcon,
|
||||
&StatusNotifierItem::secondaryActivateRequested,
|
||||
this,
|
||||
[=](const QPoint &) {
|
||||
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
||||
handleTrayIconActication(QSystemTrayIcon::MiddleClick);
|
||||
});
|
||||
});
|
||||
updateTrayMenu();
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
void MainWindow::psSetupTrayIcon() {
|
||||
if (noQtTrayIcon) {
|
||||
if (!cSupportTray()) return;
|
||||
const auto iconPixmap = QPixmap::fromImage(TrayIconImageGen());
|
||||
const auto icon = QIcon(iconPixmap);
|
||||
|
||||
if (IsSNIAvailable()) {
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
LOG(("Using SNI tray icon."));
|
||||
if (!_sniTrayIcon) {
|
||||
_sniTrayIcon = new StatusNotifierItem(
|
||||
QCoreApplication::applicationName(),
|
||||
this);
|
||||
|
||||
_sniTrayIcon->setTitle(QCoreApplication::applicationName());
|
||||
setSNITrayIcon(icon, iconPixmap);
|
||||
|
||||
attachToSNITrayIcon();
|
||||
}
|
||||
updateIconCounters();
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
} else {
|
||||
LOG(("Using Qt tray icon."));
|
||||
|
||||
if (!_trayIconMenuXEmbed) {
|
||||
_trayIconMenuXEmbed = new Ui::PopupMenu(nullptr, trayIconMenu);
|
||||
_trayIconMenuXEmbed->deleteOnHide(false);
|
||||
}
|
||||
|
||||
if (!trayIcon) {
|
||||
trayIcon = new QSystemTrayIcon(this);
|
||||
trayIcon->setIcon(QIcon(QPixmap::fromImage(_trayIconImageGen(true))));
|
||||
trayIcon->setIcon(icon);
|
||||
|
||||
attachToTrayIcon(trayIcon);
|
||||
}
|
||||
@@ -356,14 +353,14 @@ void MainWindow::workmodeUpdated(DBIWorkMode mode) {
|
||||
if (!cSupportTray()) return;
|
||||
|
||||
if (mode == dbiwmWindowOnly) {
|
||||
if (noQtTrayIcon) {
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
if (useAppIndicator) {
|
||||
Libs::app_indicator_set_status(_trayIndicator, APP_INDICATOR_STATUS_PASSIVE);
|
||||
} else if (useStatusIcon) {
|
||||
Libs::gtk_status_icon_set_visible(_trayIcon, false);
|
||||
if (IsSNIAvailable()) {
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
if (_sniTrayIcon) {
|
||||
_sniTrayIcon->setContextMenu(0);
|
||||
_sniTrayIcon->deleteLater();
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
_sniTrayIcon = 0;
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
} else {
|
||||
if (trayIcon) {
|
||||
trayIcon->setContextMenu(0);
|
||||
@@ -372,35 +369,10 @@ void MainWindow::workmodeUpdated(DBIWorkMode mode) {
|
||||
trayIcon = 0;
|
||||
}
|
||||
} else {
|
||||
if (noQtTrayIcon) {
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
if (useAppIndicator) {
|
||||
Libs::app_indicator_set_status(_trayIndicator, APP_INDICATOR_STATUS_ACTIVE);
|
||||
} else if (useStatusIcon) {
|
||||
Libs::gtk_status_icon_set_visible(_trayIcon, true);
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
} else {
|
||||
psSetupTrayIcon();
|
||||
}
|
||||
psSetupTrayIcon();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::psUpdateIndicator() {
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
_psUpdateIndicatorTimer.stop();
|
||||
_psLastIndicatorUpdate = crl::now();
|
||||
QFileInfo iconFile(_trayIconImageFile());
|
||||
if (iconFile.exists()) {
|
||||
QByteArray path = QFile::encodeName(iconFile.absoluteFilePath()), name = QFile::encodeName(iconFile.fileName());
|
||||
name = name.mid(0, name.size() - 4);
|
||||
Libs::app_indicator_set_icon_full(_trayIndicator, path.constData(), name);
|
||||
} else {
|
||||
useAppIndicator = false;
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
}
|
||||
|
||||
void MainWindow::unreadCounterChangedHook() {
|
||||
setWindowTitle(titleText());
|
||||
updateIconCounters();
|
||||
@@ -410,208 +382,91 @@ void MainWindow::updateIconCounters() {
|
||||
updateWindowIcon();
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
if (useUnityCount) {
|
||||
if (UseUnityCount) {
|
||||
const auto counter = Core::App().unreadBadge();
|
||||
QVariantMap dbusUnityProperties;
|
||||
if (counter > 0) {
|
||||
// Gnome requires that count is a 64bit integer
|
||||
dbusUnityProperties.insert("count", (qint64) ((counter > 9999) ? 9999 : (counter)));
|
||||
dbusUnityProperties.insert(
|
||||
"count",
|
||||
(qint64) ((counter > 9999)
|
||||
? 9999
|
||||
: (counter)));
|
||||
dbusUnityProperties.insert("count-visible", true);
|
||||
} else {
|
||||
dbusUnityProperties.insert("count-visible", false);
|
||||
}
|
||||
QDBusMessage signal = QDBusMessage::createSignal(_dbusPath, "com.canonical.Unity.LauncherEntry", "Update");
|
||||
signal << "application://" + _desktopFile;
|
||||
QDBusMessage signal = QDBusMessage::createSignal(
|
||||
UnityCountDBusPath,
|
||||
"com.canonical.Unity.LauncherEntry",
|
||||
"Update");
|
||||
signal << "application://" + UnityCountDesktopFile;
|
||||
signal << dbusUnityProperties;
|
||||
QDBusConnection::sessionBus().send(signal);
|
||||
}
|
||||
#endif
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
if (noQtTrayIcon) {
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
if (useAppIndicator) {
|
||||
if (crl::now() > _psLastIndicatorUpdate + 1000) {
|
||||
psUpdateIndicator();
|
||||
} else if (!_psUpdateIndicatorTimer.isActive()) {
|
||||
_psUpdateIndicatorTimer.start(100);
|
||||
}
|
||||
} else if (useStatusIcon && trayIconChecked) {
|
||||
loadPixbuf(_trayIconImageGen(true));
|
||||
Libs::gtk_status_icon_set_from_pixbuf(_trayIcon, _trayPixbuf);
|
||||
const auto iconPixmap = QPixmap::fromImage(TrayIconImageGen());
|
||||
const auto icon = QIcon(iconPixmap);
|
||||
|
||||
if (IsSNIAvailable()) {
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
if (_sniTrayIcon) {
|
||||
setSNITrayIcon(icon, iconPixmap);
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
} else if (trayIcon) {
|
||||
trayIcon->setIcon(QIcon(QPixmap::fromImage(_trayIconImageGen(true))));
|
||||
trayIcon->setIcon(icon);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::LibsLoaded() {
|
||||
noQtTrayIcon = !DesktopEnvironment::TryQtTrayIcon();
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
tryAppIndicator = DesktopEnvironment::PreferAppIndicatorTrayIcon();
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
qDBusRegisterMetaType<ToolTip>();
|
||||
qDBusRegisterMetaType<IconPixmap>();
|
||||
qDBusRegisterMetaType<IconPixmapList>();
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
LOG(("Tray Icon: Try Qt = %1, Prefer appindicator = %2").arg(Logs::b(!noQtTrayIcon)).arg(Logs::b(tryAppIndicator)));
|
||||
|
||||
if (noQtTrayIcon) cSetSupportTray(false);
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
useGtkBase = (Libs::gtk_init_check != nullptr)
|
||||
&& (Libs::gtk_menu_new != nullptr)
|
||||
&& (Libs::gtk_menu_get_type != nullptr)
|
||||
&& (Libs::gtk_menu_item_new_with_label != nullptr)
|
||||
&& (Libs::gtk_menu_item_set_label != nullptr)
|
||||
&& (Libs::gtk_menu_shell_append != nullptr)
|
||||
&& (Libs::gtk_menu_shell_get_type != nullptr)
|
||||
&& (Libs::gtk_widget_show != nullptr)
|
||||
&& (Libs::gtk_widget_get_toplevel != nullptr)
|
||||
&& (Libs::gtk_widget_get_visible != nullptr)
|
||||
&& (Libs::gtk_widget_set_sensitive != nullptr)
|
||||
&& (Libs::g_type_check_instance_cast != nullptr)
|
||||
&& (Libs::g_signal_connect_data != nullptr)
|
||||
&& (Libs::g_object_ref_sink != nullptr)
|
||||
&& (Libs::g_object_unref != nullptr);
|
||||
|
||||
useAppIndicator = useGtkBase
|
||||
&& (Libs::app_indicator_new != nullptr)
|
||||
&& (Libs::app_indicator_set_status != nullptr)
|
||||
&& (Libs::app_indicator_set_menu != nullptr)
|
||||
&& (Libs::app_indicator_set_icon_full != nullptr);
|
||||
|
||||
if (tryAppIndicator && useGtkBase && useAppIndicator) {
|
||||
noQtTrayIcon = true;
|
||||
cSetSupportTray(false);
|
||||
if (!IsSNIAvailable()) {
|
||||
_trayIconSize = 22;
|
||||
}
|
||||
|
||||
useStatusIcon = (Libs::gdk_init_check != nullptr)
|
||||
&& (Libs::gdk_pixbuf_new_from_data != nullptr)
|
||||
&& (Libs::gtk_status_icon_new_from_pixbuf != nullptr)
|
||||
&& (Libs::gtk_status_icon_set_from_pixbuf != nullptr)
|
||||
&& (Libs::gtk_status_icon_new_from_file != nullptr)
|
||||
&& (Libs::gtk_status_icon_set_from_file != nullptr)
|
||||
&& (Libs::gtk_status_icon_set_title != nullptr)
|
||||
&& (Libs::gtk_status_icon_set_tooltip_text != nullptr)
|
||||
&& (Libs::gtk_status_icon_set_visible != nullptr)
|
||||
&& (Libs::gtk_status_icon_is_embedded != nullptr)
|
||||
&& (Libs::gtk_status_icon_get_geometry != nullptr)
|
||||
&& (Libs::gtk_status_icon_position_menu != nullptr)
|
||||
&& (Libs::gtk_menu_popup != nullptr)
|
||||
&& (Libs::gtk_get_current_event_time != nullptr)
|
||||
&& (Libs::g_idle_add != nullptr);
|
||||
if (useStatusIcon) {
|
||||
DEBUG_LOG(("Status icon api loaded!"));
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
}
|
||||
|
||||
void MainWindow::psCreateTrayIcon() {
|
||||
if (!noQtTrayIcon) {
|
||||
LOG(("Tray Icon: Using Qt tray icon, available: %1").arg(Logs::b(QSystemTrayIcon::isSystemTrayAvailable())));
|
||||
cSetSupportTray(QSystemTrayIcon::isSystemTrayAvailable());
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
if (useAppIndicator) {
|
||||
DEBUG_LOG(("Trying to create AppIndicator"));
|
||||
_trayMenu = Libs::gtk_menu_new();
|
||||
if (_trayMenu) {
|
||||
DEBUG_LOG(("Created gtk menu for appindicator!"));
|
||||
QFileInfo iconFile(_trayIconImageFile());
|
||||
if (iconFile.exists()) {
|
||||
QByteArray path = QFile::encodeName(iconFile.absoluteFilePath());
|
||||
_trayIndicator = Libs::app_indicator_new("Telegram Desktop", path.constData(), APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
|
||||
if (_trayIndicator) {
|
||||
LOG(("Tray Icon: Using appindicator tray icon."));
|
||||
} else {
|
||||
DEBUG_LOG(("Failed to app_indicator_new()!"));
|
||||
}
|
||||
} else {
|
||||
useAppIndicator = false;
|
||||
DEBUG_LOG(("Failed to create image file!"));
|
||||
}
|
||||
} else {
|
||||
DEBUG_LOG(("Failed to gtk_menu_new()!"));
|
||||
}
|
||||
if (_trayMenu && _trayIndicator) {
|
||||
Libs::app_indicator_set_status(_trayIndicator, APP_INDICATOR_STATUS_ACTIVE);
|
||||
Libs::app_indicator_set_menu(_trayIndicator, Libs::gtk_menu_cast(_trayMenu));
|
||||
useStatusIcon = false;
|
||||
} else {
|
||||
DEBUG_LOG(("AppIndicator failed!"));
|
||||
useAppIndicator = false;
|
||||
}
|
||||
}
|
||||
if (useStatusIcon) {
|
||||
if (Libs::gdk_init_check(0, 0)) {
|
||||
if (!_trayMenu) _trayMenu = Libs::gtk_menu_new();
|
||||
if (_trayMenu) {
|
||||
loadPixbuf(_trayIconImageGen(true));
|
||||
_trayIcon = Libs::gtk_status_icon_new_from_pixbuf(_trayPixbuf);
|
||||
if (_trayIcon) {
|
||||
LOG(("Tray Icon: 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);
|
||||
|
||||
Libs::gtk_status_icon_set_title(_trayIcon, "Telegram Desktop");
|
||||
Libs::gtk_status_icon_set_tooltip_text(_trayIcon, "Telegram Desktop");
|
||||
Libs::gtk_status_icon_set_visible(_trayIcon, true);
|
||||
} else {
|
||||
useStatusIcon = false;
|
||||
}
|
||||
} else {
|
||||
useStatusIcon = false;
|
||||
}
|
||||
} else {
|
||||
useStatusIcon = false;
|
||||
}
|
||||
}
|
||||
if (!useStatusIcon && !useAppIndicator) {
|
||||
LOG(("Tray Icon: Not able to use any tray icon :("));
|
||||
if (_trayMenu) {
|
||||
Libs::g_object_ref_sink(_trayMenu);
|
||||
Libs::g_object_unref(_trayMenu);
|
||||
_trayMenu = nullptr;
|
||||
}
|
||||
}
|
||||
cSetSupportTray(useAppIndicator);
|
||||
if (useStatusIcon) {
|
||||
Libs::g_idle_add((GSourceFunc)_trayIconCheck, 0);
|
||||
_psCheckStatusIconTimer.start(100);
|
||||
} else {
|
||||
workmodeUpdated(Global::WorkMode().value());
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
}
|
||||
|
||||
void MainWindow::psFirstShow() {
|
||||
psCreateTrayIcon();
|
||||
const auto trayAvailable = IsSNIAvailable()
|
||||
|| QSystemTrayIcon::isSystemTrayAvailable();
|
||||
|
||||
LOG(("System tray available: %1").arg(Logs::b(trayAvailable)));
|
||||
cSetSupportTray(trayAvailable);
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
if (QDBusInterface("com.canonical.Unity", "/").isValid()) {
|
||||
std::vector<QString> possibleDesktopFiles = {
|
||||
const std::vector<QString> possibleDesktopFiles = {
|
||||
GetLauncherFilename(),
|
||||
"Telegram.desktop"
|
||||
};
|
||||
|
||||
for (auto it = possibleDesktopFiles.begin(); it != possibleDesktopFiles.end(); it++) {
|
||||
if (!QStandardPaths::locate(QStandardPaths::ApplicationsLocation, *it).isEmpty()) {
|
||||
_desktopFile = *it;
|
||||
LOG(("Found Unity Launcher entry %1!").arg(_desktopFile));
|
||||
useUnityCount = true;
|
||||
for (auto it = possibleDesktopFiles.begin();
|
||||
it != possibleDesktopFiles.end(); it++) {
|
||||
if (!QStandardPaths::locate(
|
||||
QStandardPaths::ApplicationsLocation, *it).isEmpty()) {
|
||||
UnityCountDesktopFile = *it;
|
||||
LOG(("Found Unity Launcher entry %1!")
|
||||
.arg(UnityCountDesktopFile));
|
||||
UseUnityCount = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!useUnityCount) {
|
||||
if (!UseUnityCount) {
|
||||
LOG(("Could not get Unity Launcher entry!"));
|
||||
}
|
||||
_dbusPath = "/com/canonical/unity/launcherentry/" + QString::number(djbStringHash("application://" + _desktopFile));
|
||||
UnityCountDBusPath = "/com/canonical/unity/launcherentry/"
|
||||
+ QString::number(
|
||||
djbStringHash("application://" + UnityCountDesktopFile));
|
||||
} else {
|
||||
LOG(("Not using Unity Launcher count."));
|
||||
}
|
||||
#endif
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
show();
|
||||
if (cWindowPos().maximized) {
|
||||
@@ -619,13 +474,15 @@ void MainWindow::psFirstShow() {
|
||||
setWindowState(Qt::WindowMaximized);
|
||||
}
|
||||
|
||||
if ((cLaunchMode() == LaunchModeAutoStart && cStartMinimized()) || cStartInTray()) {
|
||||
if ((cLaunchMode() == LaunchModeAutoStart && cStartMinimized())
|
||||
|| cStartInTray()) {
|
||||
// If I call hide() synchronously here after show() then on Ubuntu 14.04
|
||||
// it will show a window frame with transparent window body, without content.
|
||||
// And to be able to "Show from tray" one more hide() will be required.
|
||||
crl::on_main(this, [=] {
|
||||
setWindowState(Qt::WindowMinimized);
|
||||
if (Global::WorkMode().value() == dbiwmTrayOnly || Global::WorkMode().value() == dbiwmWindowAndTray) {
|
||||
if (Global::WorkMode().value() == dbiwmTrayOnly
|
||||
|| Global::WorkMode().value() == dbiwmWindowAndTray) {
|
||||
hide();
|
||||
} else {
|
||||
show();
|
||||
@@ -637,25 +494,11 @@ void MainWindow::psFirstShow() {
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() {
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
if (_trayIcon) {
|
||||
Libs::g_object_unref(_trayIcon);
|
||||
_trayIcon = nullptr;
|
||||
}
|
||||
if (_trayPixbuf) {
|
||||
Libs::g_object_unref(_trayPixbuf);
|
||||
_trayPixbuf = nullptr;
|
||||
}
|
||||
if (_trayMenu) {
|
||||
Libs::g_object_ref_sink(_trayMenu);
|
||||
Libs::g_object_unref(_trayMenu);
|
||||
_trayMenu = nullptr;
|
||||
}
|
||||
if (_trayIndicator) {
|
||||
Libs::g_object_unref(_trayIndicator);
|
||||
_trayIndicator = nullptr;
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
delete _sniTrayIcon;
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
delete _trayIconMenuXEmbed;
|
||||
}
|
||||
|
||||
} // namespace Platform
|
||||
|
@@ -9,7 +9,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
#include "platform/platform_main_window.h"
|
||||
|
||||
#include <QtCore/QTimer>
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
#include "statusnotifieritem.h"
|
||||
#include <QtCore/QTemporaryFile>
|
||||
#endif
|
||||
|
||||
namespace Platform {
|
||||
|
||||
@@ -21,7 +26,12 @@ public:
|
||||
|
||||
void psFirstShow();
|
||||
|
||||
virtual QImage iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) = 0;
|
||||
virtual QImage iconWithCounter(
|
||||
int size,
|
||||
int count,
|
||||
style::color bg,
|
||||
style::color fg,
|
||||
bool smallIcon) = 0;
|
||||
|
||||
static void LibsLoaded();
|
||||
|
||||
@@ -30,9 +40,6 @@ public:
|
||||
public slots:
|
||||
void psShowTrayMenu();
|
||||
|
||||
void psStatusIconCheck();
|
||||
void psUpdateIndicator();
|
||||
|
||||
protected:
|
||||
void unreadCounterChangedHook() override;
|
||||
|
||||
@@ -46,17 +53,26 @@ protected:
|
||||
void psTrayMenuUpdated();
|
||||
void psSetupTrayIcon();
|
||||
|
||||
virtual void placeSmallCounter(QImage &img, int size, int count, style::color bg, const QPoint &shift, style::color color) = 0;
|
||||
virtual void placeSmallCounter(
|
||||
QImage &img,
|
||||
int size,
|
||||
int count,
|
||||
style::color bg,
|
||||
const QPoint &shift,
|
||||
style::color color) = 0;
|
||||
|
||||
private:
|
||||
Ui::PopupMenu *_trayIconMenuXEmbed = nullptr;
|
||||
|
||||
void updateIconCounters();
|
||||
void psCreateTrayIcon();
|
||||
|
||||
QTimer _psCheckStatusIconTimer;
|
||||
int _psCheckStatusIconLeft = 100;
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
StatusNotifierItem *_sniTrayIcon = nullptr;
|
||||
std::unique_ptr<QTemporaryFile> _trayIconFile = nullptr;
|
||||
|
||||
QTimer _psUpdateIndicatorTimer;
|
||||
crl::time _psLastIndicatorUpdate = 0;
|
||||
void setSNITrayIcon(const QIcon &icon, const QPixmap &iconPixmap);
|
||||
void attachToSNITrayIcon();
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
};
|
||||
|
||||
|
@@ -44,7 +44,7 @@ namespace {
|
||||
|
||||
constexpr auto kDesktopFile = ":/misc/telegramdesktop.desktop"_cs;
|
||||
|
||||
bool XDGDesktopPortalIsPresent = false;
|
||||
bool XDGDesktopPortalPresent = false;
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
void SandboxAutostart(bool autostart) {
|
||||
@@ -196,13 +196,13 @@ bool InSnap() {
|
||||
}
|
||||
|
||||
bool IsXDGDesktopPortalPresent() {
|
||||
return XDGDesktopPortalIsPresent;
|
||||
};
|
||||
return XDGDesktopPortalPresent;
|
||||
}
|
||||
|
||||
QString CurrentExecutablePath(int argc, char *argv[]) {
|
||||
QString ProcessNameByPID(const QString &pid) {
|
||||
constexpr auto kMaxPath = 1024;
|
||||
char result[kMaxPath] = { 0 };
|
||||
auto count = readlink("/proc/self/exe", result, kMaxPath);
|
||||
auto count = readlink("/proc/" + pid.toLatin1() + "/exe", result, kMaxPath);
|
||||
if (count > 0) {
|
||||
auto filename = QFile::decodeName(result);
|
||||
auto deletedPostfix = qstr(" (deleted)");
|
||||
@@ -212,26 +212,53 @@ QString CurrentExecutablePath(int argc, char *argv[]) {
|
||||
return filename;
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString CurrentExecutablePath(int argc, char *argv[]) {
|
||||
const auto processName = ProcessNameByPID(qsl("self"));
|
||||
|
||||
// Fallback to the first command line argument.
|
||||
return argc ? QFile::decodeName(argv[0]) : QString();
|
||||
return !processName.isEmpty()
|
||||
? processName
|
||||
: argc
|
||||
? QFile::decodeName(argv[0])
|
||||
: QString();
|
||||
}
|
||||
|
||||
QString AppRuntimeDirectory() {
|
||||
static const auto RuntimeDirectory = [&] {
|
||||
auto runtimeDir = QStandardPaths::writableLocation(
|
||||
QStandardPaths::RuntimeLocation);
|
||||
|
||||
if (InSandbox()) {
|
||||
runtimeDir += qsl("/app/")
|
||||
+ QString::fromLatin1(qgetenv("FLATPAK_ID"));
|
||||
}
|
||||
|
||||
if (!QFileInfo::exists(runtimeDir)) { // non-systemd distros
|
||||
runtimeDir = QDir::tempPath();
|
||||
}
|
||||
|
||||
if (runtimeDir.isEmpty()) {
|
||||
runtimeDir = qsl("/tmp/");
|
||||
}
|
||||
|
||||
if (!runtimeDir.endsWith('/')) {
|
||||
runtimeDir += '/';
|
||||
}
|
||||
|
||||
return runtimeDir;
|
||||
}();
|
||||
|
||||
return RuntimeDirectory;
|
||||
}
|
||||
|
||||
QString SingleInstanceLocalServerName(const QString &hash) {
|
||||
const auto runtimeDir = QStandardPaths::writableLocation(
|
||||
QStandardPaths::RuntimeLocation);
|
||||
|
||||
if (InSandbox()) {
|
||||
return runtimeDir
|
||||
+ qsl("/app/")
|
||||
+ QString::fromLatin1(qgetenv("FLATPAK_ID"))
|
||||
+ '/' + hash;
|
||||
} else if (QFileInfo::exists(runtimeDir) && InSnap()) {
|
||||
return runtimeDir + '/' + hash;
|
||||
} else if (QFileInfo::exists(runtimeDir)) {
|
||||
return runtimeDir + '/' + hash + '-' + cGUIDStr();
|
||||
} else { // non-systemd distros
|
||||
return QStandardPaths::writableLocation(QStandardPaths::TempLocation)
|
||||
+ '/' + hash + '-' + cGUIDStr();
|
||||
if (InSandbox() || InSnap()) {
|
||||
return AppRuntimeDirectory() + hash;
|
||||
} else {
|
||||
return AppRuntimeDirectory() + hash + '-' + cGUIDStr();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,12 +408,12 @@ void start() {
|
||||
|
||||
#if !defined(TDESKTOP_DISABLE_DBUS_INTEGRATION) && defined(TDESKTOP_FORCE_GTK_FILE_DIALOG)
|
||||
LOG(("Checking for XDG Desktop Portal..."));
|
||||
XDGDesktopPortalIsPresent = QDBusInterface(
|
||||
XDGDesktopPortalPresent = QDBusInterface(
|
||||
"org.freedesktop.portal.Desktop",
|
||||
"/org/freedesktop/portal/desktop").isValid();
|
||||
|
||||
// this can give us a chance to use a proper file dialog for current session
|
||||
if(XDGDesktopPortalIsPresent) {
|
||||
if(XDGDesktopPortalPresent) {
|
||||
LOG(("XDG Desktop Portal is present!"));
|
||||
qputenv("QT_QPA_PLATFORMTHEME", "xdgdesktopportal");
|
||||
} else {
|
||||
@@ -467,6 +494,8 @@ bool OpenSystemSettings(SystemSettingsType type) {
|
||||
add("kcmshell4 phonon");
|
||||
} else if (DesktopEnvironment::IsGnome()) {
|
||||
add("gnome-control-center sound");
|
||||
} else if (DesktopEnvironment::IsMATE()) {
|
||||
add("mate-volume-control");
|
||||
}
|
||||
add("pavucontrol-qt");
|
||||
add("pavucontrol");
|
||||
|
@@ -25,8 +25,10 @@ bool InSnap();
|
||||
|
||||
bool IsXDGDesktopPortalPresent();
|
||||
|
||||
QString ProcessNameByPID(const QString &pid);
|
||||
QString CurrentExecutablePath(int argc, char *argv[]);
|
||||
|
||||
QString AppRuntimeDirectory();
|
||||
QString SingleInstanceLocalServerName(const QString &hash);
|
||||
|
||||
QString GetLauncherBasename();
|
||||
|
Reference in New Issue
Block a user