tdesktop/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp

159 lines
3.9 KiB
C++
Raw Normal View History

2020-11-11 23:18:18 +00:00
/*
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_wayland_integration.h"
2023-05-24 23:38:38 +00:00
#include "base/platform/linux/base_linux_wayland_utilities.h"
2020-11-11 23:18:18 +00:00
#include "base/platform/base_platform_info.h"
#include "base/qt_signal_producer.h"
#include "base/flat_map.h"
#include "qwayland-plasma-shell.h"
2020-11-11 23:18:18 +00:00
#include <QtGui/QGuiApplication>
#include <QtGui/QWindow>
#include <qpa/qplatformnativeinterface.h>
#include <qpa/qplatformwindow_p.h>
#include <wayland-client.h>
2020-11-11 23:18:18 +00:00
using namespace QNativeInterface;
using namespace QNativeInterface::Private;
2023-05-24 23:38:38 +00:00
using namespace base::Platform::Wayland;
2020-11-11 23:18:18 +00:00
namespace Platform {
namespace internal {
2021-07-25 21:30:56 +00:00
struct WaylandIntegration::Private {
2023-05-24 23:38:38 +00:00
QtWayland::org_kde_plasma_surface plasmaSurface(QWindow *window);
std::unique_ptr<wl_registry, RegistryDeleter> registry;
AutoDestroyer<QtWayland::org_kde_plasma_shell> plasmaShell;
uint32_t plasmaShellName = 0;
2023-05-24 23:38:38 +00:00
base::flat_map<
wl_surface*,
AutoDestroyer<QtWayland::org_kde_plasma_surface>
> plasmaSurfaces;
rpl::lifetime lifetime;
2023-05-24 23:38:38 +00:00
static const wl_registry_listener RegistryListener;
};
2023-05-24 23:38:38 +00:00
const wl_registry_listener WaylandIntegration::Private::RegistryListener = {
decltype(wl_registry_listener::global)(+[](
Private *data,
wl_registry *registry,
uint32_t name,
const char *interface,
uint32_t version) {
if (interface == qstr("org_kde_plasma_shell")) {
data->plasmaShell.init(registry, name, version);
data->plasmaShellName = name;
}
}),
decltype(wl_registry_listener::global_remove)(+[](
Private *data,
wl_registry *registry,
uint32_t name) {
if (name == data->plasmaShellName) {
2023-05-24 23:38:38 +00:00
data->plasmaShell = {};
data->plasmaShellName = 0;
}
}),
};
2023-05-24 23:38:38 +00:00
QtWayland::org_kde_plasma_surface WaylandIntegration::Private::plasmaSurface(
QWindow *window) {
if (!plasmaShell.isInitialized()) {
2023-05-24 23:38:38 +00:00
return {};
}
const auto native = window->nativeInterface<QWaylandWindow>();
if (!native) {
2023-05-24 23:38:38 +00:00
return {};
}
const auto surface = native->surface();
if (!surface) {
2023-05-24 23:38:38 +00:00
return {};
}
const auto it = plasmaSurfaces.find(surface);
if (it != plasmaSurfaces.cend()) {
2023-05-24 23:38:38 +00:00
return it->second;
}
2023-05-24 23:38:38 +00:00
const auto plasmaSurface = plasmaShell.get_surface(surface);
if (!plasmaSurface) {
return {};
}
2023-05-24 23:38:38 +00:00
const auto result = plasmaSurfaces.emplace(surface, plasmaSurface);
base::qt_signal_producer(
native,
&QWaylandWindow::surfaceDestroyed
) | rpl::start_with_next([=] {
auto it = plasmaSurfaces.find(surface);
if (it != plasmaSurfaces.cend()) {
plasmaSurfaces.erase(it);
}
}, lifetime);
2023-05-24 23:38:38 +00:00
return result.first->second;
}
2021-07-25 21:30:56 +00:00
WaylandIntegration::WaylandIntegration()
: _private(std::make_unique<Private>()) {
const auto native = qApp->nativeInterface<QWaylandApplication>();
if (!native) {
return;
}
const auto display = native->display();
if (!display) {
return;
}
_private->registry.reset(wl_display_get_registry(display));
wl_registry_add_listener(
_private->registry.get(),
&Private::RegistryListener,
_private.get());
wl_display_roundtrip(display);
}
WaylandIntegration::~WaylandIntegration() = default;
2020-11-11 23:18:18 +00:00
WaylandIntegration *WaylandIntegration::Instance() {
if (!IsWayland()) return nullptr;
static std::optional<WaylandIntegration> instance(std::in_place);
base::qt_signal_producer(
QGuiApplication::platformNativeInterface(),
&QObject::destroyed
) | rpl::start_with_next([&] {
instance = std::nullopt;
}, instance->_private->lifetime);
if (!instance) return nullptr;
return &*instance;
2020-11-11 23:18:18 +00:00
}
bool WaylandIntegration::skipTaskbarSupported() {
return _private->plasmaShell.isInitialized();
}
void WaylandIntegration::skipTaskbar(QWindow *window, bool skip) {
auto plasmaSurface = _private->plasmaSurface(window);
2023-05-24 23:38:38 +00:00
if (!plasmaSurface.isInitialized()) {
return;
}
2023-05-24 23:38:38 +00:00
plasmaSurface.set_skip_taskbar(skip);
}
2020-11-11 23:18:18 +00:00
} // namespace internal
} // namespace Platform