Move remaining usage of dbus to glibmm in main_window_linux

This commit is contained in:
Ilya Fedin 2021-03-02 08:01:04 +04:00 committed by John Preston
parent a2f8546033
commit b08c33cf8a
2 changed files with 123 additions and 92 deletions

View file

@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "app.h"
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
#include "base/platform/linux/base_linux_glibmm_helper.h"
#include "base/platform/linux/base_linux_dbus_utilities.h"
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
@ -43,12 +44,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtGui/QWindow>
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
#include <QtDBus/QDBusInterface>
#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusServiceWatcher>
#include <QtDBus/QDBusMessage>
#include <QtDBus/QDBusReply>
#include <QtDBus/QDBusError>
#include <QtDBus/QDBusObjectPath>
#include <QtDBus/QDBusMetaType>
@ -414,50 +411,65 @@ std::unique_ptr<QTemporaryFile> TrayIconFile(
}
bool UseUnityCounter() {
static const auto Result = QDBusInterface(
"com.canonical.Unity",
"/").isValid();
static const auto Result = [&] {
try {
const auto connection = Gio::DBus::Connection::get_sync(
Gio::DBus::BusType::BUS_TYPE_SESSION);
return base::Platform::DBus::NameHasOwner(
connection,
"com.canonical.Unity");
} catch (...) {
}
return false;
}();
return Result;
}
bool IsSNIAvailable() {
auto message = QDBusMessage::createMethodCall(
kSNIWatcherService.utf16(),
kSNIWatcherObjectPath.utf16(),
kPropertiesInterface.utf16(),
qsl("Get"));
try {
const auto connection = Gio::DBus::Connection::get_sync(
Gio::DBus::BusType::BUS_TYPE_SESSION);
message.setArguments({
kSNIWatcherInterface.utf16(),
qsl("IsStatusNotifierHostRegistered")
});
auto reply = connection->call_sync(
std::string(kSNIWatcherObjectPath),
std::string(kPropertiesInterface),
"Get",
base::Platform::MakeGlibVariant(std::tuple{
Glib::ustring(std::string(kSNIWatcherInterface)),
Glib::ustring("IsStatusNotifierHostRegistered"),
}),
std::string(kSNIWatcherService));
const QDBusReply<QVariant> reply = QDBusConnection::sessionBus().call(
message);
return base::Platform::GlibVariantCast<bool>(
base::Platform::GlibVariantCast<Glib::VariantBase>(
reply.get_child(0)));
} catch (const Glib::Error &e) {
static const auto NotSupportedErrors = {
"org.freedesktop.DBus.Error.Disconnected",
"org.freedesktop.DBus.Error.ServiceUnknown",
};
if (reply.isValid()) {
return reply.value().toBool();
}
switch (reply.error().type()) {
case QDBusError::Disconnected:
case QDBusError::ServiceUnknown:
const auto errorName = Gio::DBus::ErrorUtils::get_remote_error(e);
if (ranges::contains(NotSupportedErrors, errorName)) {
return false;
default:
break;
}
LOG(("SNI Error: %1: %2")
.arg(reply.error().name())
.arg(reply.error().message()));
LOG(("SNI Error: %1")
.arg(QString::fromStdString(e.what())));
} catch (const std::exception &e) {
LOG(("SNI Error: %1")
.arg(QString::fromStdString(e.what())));
}
return false;
}
quint32 djbStringHash(QString string) {
quint32 hash = 5381;
QByteArray chars = string.toLatin1();
uint djbStringHash(const std::string &string) {
uint hash = 5381;
const auto chars = QByteArray::fromStdString(string.data());
for(int i = 0; i < chars.length(); i++){
hash = (hash << 5) + hash + chars[i];
}
@ -478,6 +490,8 @@ bool IsAppMenuSupported() {
return false;
}
// This call must be made from the same bus connection as DBusMenuExporter
// So it must use QDBusConnection
void RegisterAppMenu(uint winId, const QString &menuPath) {
auto message = QDBusMessage::createMethodCall(
kAppMenuService.utf16(),
@ -493,6 +507,8 @@ void RegisterAppMenu(uint winId, const QString &menuPath) {
QDBusConnection::sessionBus().send(message);
}
// This call must be made from the same bus connection as DBusMenuExporter
// So it must use QDBusConnection
void UnregisterAppMenu(uint winId) {
auto message = QDBusMessage::createMethodCall(
kAppMenuService.utf16(),
@ -555,6 +571,7 @@ MainWindow::MainWindow(not_null<Window::Controller*> controller)
void MainWindow::initHook() {
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
_sniAvailable = IsSNIAvailable();
_appMenuSupported = IsAppMenuSupported();
try {
_private->dbusConnection = Gio::DBus::Connection::get_sync(
@ -580,45 +597,35 @@ void MainWindow::initHook() {
std::string(kSNIWatcherInterface),
"StatusNotifierHostRegistered",
std::string(kSNIWatcherObjectPath));
_sniWatcherId = base::Platform::DBus::RegisterServiceWatcher(
_private->dbusConnection,
std::string(kSNIWatcherService),
[=](
const Glib::ustring &service,
const Glib::ustring &oldOwner,
const Glib::ustring &newOwner) {
handleSNIOwnerChanged(
QString::fromStdString(service),
QString::fromStdString(oldOwner),
QString::fromStdString(newOwner));
});
_appMenuWatcherId = base::Platform::DBus::RegisterServiceWatcher(
_private->dbusConnection,
std::string(kAppMenuService),
[=](
const Glib::ustring &service,
const Glib::ustring &oldOwner,
const Glib::ustring &newOwner) {
handleAppMenuOwnerChanged(
QString::fromStdString(service),
QString::fromStdString(oldOwner),
QString::fromStdString(newOwner));
});
} catch (...) {
}
auto sniWatcher = new QDBusServiceWatcher(
kSNIWatcherService.utf16(),
QDBusConnection::sessionBus(),
QDBusServiceWatcher::WatchForOwnerChange,
this);
connect(
sniWatcher,
&QDBusServiceWatcher::serviceOwnerChanged,
this,
[=](
const QString &service,
const QString &oldOwner,
const QString &newOwner) {
handleSNIOwnerChanged(service, oldOwner, newOwner);
});
_appMenuSupported = IsAppMenuSupported();
auto appMenuWatcher = new QDBusServiceWatcher(
kAppMenuService.utf16(),
QDBusConnection::sessionBus(),
QDBusServiceWatcher::WatchForOwnerChange,
this);
connect(
appMenuWatcher,
&QDBusServiceWatcher::serviceOwnerChanged,
this,
[=](
const QString &service,
const QString &oldOwner,
const QString &newOwner) {
handleAppMenuOwnerChanged(service, oldOwner, newOwner);
});
if (_appMenuSupported) {
LOG(("Using D-Bus global menu."));
} else {
@ -866,30 +873,39 @@ void MainWindow::updateIconCounters() {
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
if (UseUnityCounter()) {
const auto launcherUrl = "application://" + GetLauncherFilename();
// Gnome requires that count is a 64bit integer
const qint64 counterSlice = std::min(counter, 9999);
QVariantMap dbusUnityProperties;
const auto launcherUrl = Glib::ustring(
"application://" + GetLauncherFilename().toStdString());
const auto counterSlice = std::min(counter, 9999);
std::map<Glib::ustring, Glib::VariantBase> dbusUnityProperties;
if (counterSlice > 0) {
dbusUnityProperties["count"] = counterSlice;
dbusUnityProperties["count-visible"] = true;
// According to the spec, it should be of 'x' D-Bus signature,
// which corresponds to gint64 (signed long) type with glib
// https://wiki.ubuntu.com/Unity/LauncherAPI#Low_level_DBus_API:_com.canonical.Unity.LauncherEntry
dbusUnityProperties["count"] = Glib::Variant<long>::create(
counterSlice);
dbusUnityProperties["count-visible"] =
Glib::Variant<bool>::create(true);
} else {
dbusUnityProperties["count-visible"] = false;
dbusUnityProperties["count-visible"] =
Glib::Variant<bool>::create(false);
}
auto signal = QDBusMessage::createSignal(
try {
if (_private->dbusConnection) {
_private->dbusConnection->emit_signal(
"/com/canonical/unity/launcherentry/"
+ QString::number(djbStringHash(launcherUrl)),
+ std::to_string(djbStringHash(launcherUrl)),
"com.canonical.Unity.LauncherEntry",
"Update");
signal.setArguments({
"Update",
{},
base::Platform::MakeGlibVariant(std::tuple{
launcherUrl,
dbusUnityProperties
});
QDBusConnection::sessionBus().send(signal);
dbusUnityProperties,
}));
}
} catch (...) {
}
}
if (_sniTrayIcon) {
@ -1251,8 +1267,21 @@ void MainWindow::handleVisibleChangedHook(bool visible) {
MainWindow::~MainWindow() {
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
if (_private->dbusConnection) {
if (_sniRegisteredSignalId != 0) {
_private->dbusConnection->signal_unsubscribe(_sniRegisteredSignalId);
_private->dbusConnection->signal_unsubscribe(
_sniRegisteredSignalId);
}
if (_sniWatcherId != 0) {
_private->dbusConnection->signal_unsubscribe(
_sniWatcherId);
}
if (_appMenuWatcherId != 0) {
_private->dbusConnection->signal_unsubscribe(
_appMenuWatcherId);
}
}
delete _sniTrayIcon;

View file

@ -80,6 +80,8 @@ private:
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
StatusNotifierItem *_sniTrayIcon = nullptr;
uint _sniRegisteredSignalId = 0;
uint _sniWatcherId = 0;
uint _appMenuWatcherId = 0;
std::unique_ptr<QTemporaryFile> _trayIconFile;
bool _appMenuSupported = false;