mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-18 23:27:09 +02:00
Add support for G-S-D's media-keys extension
This fixes media keys handling on (but not limited to, probably): * GNOME * Cinnamon * MATE * Budgie * Pantheon (elementaryOS) * Unity
This commit is contained in:
parent
486424af4f
commit
28f857f763
5 changed files with 250 additions and 0 deletions
|
@ -812,6 +812,8 @@ PRIVATE
|
|||
platform/linux/linux_desktop_environment.h
|
||||
platform/linux/linux_gdk_helper.cpp
|
||||
platform/linux/linux_gdk_helper.h
|
||||
platform/linux/linux_gsd_media_keys.cpp
|
||||
platform/linux/linux_gsd_media_keys.h
|
||||
platform/linux/linux_libs.cpp
|
||||
platform/linux/linux_libs.h
|
||||
platform/linux/linux_wayland_integration.cpp
|
||||
|
@ -1101,6 +1103,13 @@ if (NOT LINUX)
|
|||
)
|
||||
endif()
|
||||
|
||||
if (LINUX AND DESKTOP_APP_DISABLE_DBUS_INTEGRATION)
|
||||
remove_target_sources(Telegram ${src_loc}
|
||||
platform/linux/linux_gsd_media_keys.cpp
|
||||
platform/linux/linux_gsd_media_keys.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if (LINUX AND DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION)
|
||||
remove_target_sources(Telegram ${src_loc} platform/linux/linux_wayland_integration.cpp)
|
||||
nice_target_sources(Telegram ${src_loc} PRIVATE platform/linux/linux_wayland_integration_dummy.cpp)
|
||||
|
|
182
Telegram/SourceFiles/platform/linux/linux_gsd_media_keys.cpp
Normal file
182
Telegram/SourceFiles/platform/linux/linux_gsd_media_keys.cpp
Normal file
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "platform/linux/linux_gsd_media_keys.h"
|
||||
|
||||
#include "core/sandbox.h"
|
||||
#include "media/player/media_player_instance.h"
|
||||
|
||||
#include <QtDBus/QDBusConnection>
|
||||
#include <QtDBus/QDBusConnectionInterface>
|
||||
|
||||
extern "C" {
|
||||
#undef signals
|
||||
#include <gio/gio.h>
|
||||
#define signals public
|
||||
} // extern "C"
|
||||
|
||||
namespace Platform {
|
||||
namespace internal {
|
||||
namespace {
|
||||
|
||||
constexpr auto kDBusTimeout = 30000;
|
||||
constexpr auto kService = "org.gnome.SettingsDaemon.MediaKeys"_cs;
|
||||
constexpr auto kOldService = "org.gnome.SettingsDaemon"_cs;
|
||||
constexpr auto kMATEService = "org.mate.SettingsDaemon"_cs;
|
||||
constexpr auto kObjectPath = "/org/gnome/SettingsDaemon/MediaKeys"_cs;
|
||||
constexpr auto kMATEObjectPath = "/org/mate/SettingsDaemon/MediaKeys"_cs;
|
||||
constexpr auto kInterface = kService;
|
||||
constexpr auto kMATEInterface = "org.mate.SettingsDaemon.MediaKeys"_cs;
|
||||
|
||||
void KeyPressed(
|
||||
GDBusConnection *connection,
|
||||
const gchar *sender_name,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
const gchar *signal_name,
|
||||
GVariant *parameters,
|
||||
gpointer user_data) {
|
||||
gchar *appUtf8;
|
||||
gchar *keyUtf8;
|
||||
g_variant_get(parameters, "(ss)", &appUtf8, &keyUtf8);
|
||||
const auto app = QString::fromUtf8(appUtf8);
|
||||
const auto key = QString::fromUtf8(keyUtf8);
|
||||
g_free(keyUtf8);
|
||||
g_free(appUtf8);
|
||||
|
||||
if (app != QCoreApplication::applicationName()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
||||
if (key == qstr("Play")) {
|
||||
Media::Player::instance()->playPause();
|
||||
} else if (key == qstr("Stop")) {
|
||||
Media::Player::instance()->stop();
|
||||
} else if (key == qstr("Next")) {
|
||||
Media::Player::instance()->next();
|
||||
} else if (key == qstr("Previous")) {
|
||||
Media::Player::instance()->previous();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
GSDMediaKeys::GSDMediaKeys() {
|
||||
GError *error = nullptr;
|
||||
const auto interface = QDBusConnection::sessionBus().interface();
|
||||
|
||||
if (!interface) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (interface->isServiceRegistered(kService.utf16())) {
|
||||
_service = kService.utf16();
|
||||
_objectPath = kObjectPath.utf16();
|
||||
_interface = kInterface.utf16();
|
||||
} else if (interface->isServiceRegistered(kOldService.utf16())) {
|
||||
_service = kOldService.utf16();
|
||||
_objectPath = kObjectPath.utf16();
|
||||
_interface = kInterface.utf16();
|
||||
} else if (interface->isServiceRegistered(kMATEService.utf16())) {
|
||||
_service = kMATEService.utf16();
|
||||
_objectPath = kMATEObjectPath.utf16();
|
||||
_interface = kMATEInterface.utf16();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
_dbusConnection = g_bus_get_sync(
|
||||
G_BUS_TYPE_SESSION,
|
||||
nullptr,
|
||||
&error);
|
||||
|
||||
if (error) {
|
||||
LOG(("GSD Media Keys Error: %1").arg(error->message));
|
||||
g_error_free(error);
|
||||
return;
|
||||
}
|
||||
|
||||
auto reply = g_dbus_connection_call_sync(
|
||||
_dbusConnection,
|
||||
_service.toUtf8(),
|
||||
_objectPath.toUtf8(),
|
||||
_interface.toUtf8(),
|
||||
"GrabMediaPlayerKeys",
|
||||
g_variant_new(
|
||||
"(su)",
|
||||
QCoreApplication::applicationName().toUtf8().constData(),
|
||||
0),
|
||||
nullptr,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
kDBusTimeout,
|
||||
nullptr,
|
||||
&error);
|
||||
|
||||
if (!error) {
|
||||
_grabbed = true;
|
||||
g_variant_unref(reply);
|
||||
} else {
|
||||
LOG(("GSD Media Keys Error: %1").arg(error->message));
|
||||
g_error_free(error);
|
||||
}
|
||||
|
||||
_signalId = g_dbus_connection_signal_subscribe(
|
||||
_dbusConnection,
|
||||
_service.toUtf8(),
|
||||
_interface.toUtf8(),
|
||||
"MediaPlayerKeyPressed",
|
||||
_objectPath.toUtf8(),
|
||||
nullptr,
|
||||
G_DBUS_SIGNAL_FLAGS_NONE,
|
||||
KeyPressed,
|
||||
nullptr,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
GSDMediaKeys::~GSDMediaKeys() {
|
||||
GError *error = nullptr;
|
||||
|
||||
if (_signalId != 0) {
|
||||
g_dbus_connection_signal_unsubscribe(
|
||||
_dbusConnection,
|
||||
_signalId);
|
||||
}
|
||||
|
||||
if (_grabbed) {
|
||||
auto reply = g_dbus_connection_call_sync(
|
||||
_dbusConnection,
|
||||
_service.toUtf8(),
|
||||
_objectPath.toUtf8(),
|
||||
_interface.toUtf8(),
|
||||
"ReleaseMediaPlayerKeys",
|
||||
g_variant_new(
|
||||
"(s)",
|
||||
QCoreApplication::applicationName().toUtf8().constData()),
|
||||
nullptr,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
kDBusTimeout,
|
||||
nullptr,
|
||||
&error);
|
||||
|
||||
if (!error) {
|
||||
_grabbed = false;
|
||||
g_variant_unref(reply);
|
||||
} else {
|
||||
LOG(("GSD Media Keys Error: %1").arg(error->message));
|
||||
g_error_free(error);
|
||||
}
|
||||
}
|
||||
|
||||
if (_dbusConnection) {
|
||||
g_object_unref(_dbusConnection);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace Platform
|
36
Telegram/SourceFiles/platform/linux/linux_gsd_media_keys.h
Normal file
36
Telegram/SourceFiles/platform/linux/linux_gsd_media_keys.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
typedef struct _GDBusConnection GDBusConnection;
|
||||
|
||||
namespace Platform {
|
||||
namespace internal {
|
||||
|
||||
class GSDMediaKeys {
|
||||
public:
|
||||
GSDMediaKeys();
|
||||
|
||||
GSDMediaKeys(const GSDMediaKeys &other) = delete;
|
||||
GSDMediaKeys &operator=(const GSDMediaKeys &other) = delete;
|
||||
GSDMediaKeys(GSDMediaKeys &&other) = delete;
|
||||
GSDMediaKeys &operator=(GSDMediaKeys &&other) = delete;
|
||||
|
||||
~GSDMediaKeys();
|
||||
|
||||
private:
|
||||
GDBusConnection *_dbusConnection = nullptr;
|
||||
QString _service;
|
||||
QString _objectPath;
|
||||
QString _interface;
|
||||
uint _signalId = 0;
|
||||
bool _grabbed = false;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace Platform
|
|
@ -23,8 +23,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "storage/localstorage.h"
|
||||
#include "window/window_controller.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "media/player/media_player_instance.h"
|
||||
#include "media/audio/media_audio.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "base/platform/linux/base_xcb_utilities_linux.h"
|
||||
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
#include "platform/linux/linux_gsd_media_keys.h"
|
||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
#include "base/call_delayed.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "facades.h"
|
||||
|
@ -572,6 +577,17 @@ void MainWindow::initHook() {
|
|||
} else {
|
||||
LOG(("Not using Unity launcher counter."));
|
||||
}
|
||||
|
||||
Media::Player::instance()->updatedNotifier(
|
||||
) | rpl::start_with_next([=](const Media::Player::TrackState &state) {
|
||||
if (!Media::Player::IsStoppedOrStopping(state.state)) {
|
||||
if (!_gsdMediaKeys) {
|
||||
_gsdMediaKeys = std::make_unique<internal::GSDMediaKeys>();
|
||||
}
|
||||
} else if (_gsdMediaKeys) {
|
||||
_gsdMediaKeys = nullptr;
|
||||
}
|
||||
}, lifetime());
|
||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
updateWaylandDecorationColors();
|
||||
|
|
|
@ -24,6 +24,11 @@ typedef struct _GDBusProxy GDBusProxy;
|
|||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
namespace Platform {
|
||||
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
namespace internal {
|
||||
class GSDMediaKeys;
|
||||
} // namespace internal
|
||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
class MainWindow : public Window::MainWindow {
|
||||
public:
|
||||
|
@ -88,6 +93,8 @@ private:
|
|||
DBusMenuExporter *_mainMenuExporter = nullptr;
|
||||
QDBusObjectPath _mainMenuPath;
|
||||
|
||||
std::unique_ptr<internal::GSDMediaKeys> _gsdMediaKeys;
|
||||
|
||||
QMenu *psMainMenu = nullptr;
|
||||
QAction *psLogout = nullptr;
|
||||
QAction *psUndo = nullptr;
|
||||
|
|
Loading…
Add table
Reference in a new issue