MythTV master
mythwaylandextras.cpp
Go to the documentation of this file.
1// Qt
2#include <QWidget>
3#include <QtGlobal>
4#include <QGuiApplication>
5#include <algorithm>
6// N.B. Private headers
7#include <qpa/qplatformnativeinterface.h>
8
9// MythTV
12
13// Wayland
14#include <wayland-client.h>
15
16#define LOC QString("Wayland: ")
17
28{
29 if (!Widget)
30 return;
31
32 QWindow* window = Widget->windowHandle();
33 if (!window)
34 {
35 LOG(VB_GENERAL, LOG_WARNING, LOC + "Failed to retrieve native window");
36 return;
37 }
38
39 QPlatformNativeInterface* interface = QGuiApplication::platformNativeInterface();
40 m_display = reinterpret_cast<wl_display*>(interface->nativeResourceForWindow("display", window));
41 m_surface = reinterpret_cast<wl_surface*>(interface->nativeResourceForWindow("surface", window));
42 m_compositor = reinterpret_cast<wl_compositor*>(interface->nativeResourceForWindow("compositor", window));
43
44 if (!(m_display && m_surface && m_compositor))
45 LOG(VB_GENERAL, LOG_WARNING, LOC + "Failed to retrieve Wayland resources");
46}
47
55bool MythWaylandDevice::SetOpaqueRegion(const QRect Region) const
56{
57 if (!(m_surface && m_compositor))
58 return false;
59
60 wl_region* region = wl_compositor_create_region(m_compositor);
61 if (!region)
62 return false;
63
64 wl_region_add(region, Region.left(), Region.top(), Region.width(), Region.height());
65 wl_surface_set_opaque_region(m_surface, region);
66 wl_surface_commit(m_surface);
67 wl_region_destroy(region);
68
69 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Set opaque region: %1x%2+%3+%4")
70 .arg(Region.width()).arg(Region.height()).arg(Region.left()).arg(Region.top()));
71 return true;
72}
73
74const struct wl_registry_listener MythWaylandExtras::kRegistryListener =
75 { .global=&MythWaylandExtras::AnnounceGlobal, .global_remove=nullptr };
76
82void MythWaylandExtras::AnnounceGlobal(void *Opaque, struct wl_registry *Reg,
83 uint32_t Name, const char *Interface, uint32_t Version)
84{
85 auto * registry = reinterpret_cast<MythWaylandRegistry*>(Opaque);
86 auto found = std::ranges::find_if(*registry, [&](const auto IFace)
87 {
88 return (strcmp(Interface, IFace.first->name) == 0) && (IFace.first->version == static_cast<int>(Version));
89 });
90
91 if (found != registry->end())
92 {
93 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Found interface: %1 (v%2)")
94 .arg(found->first->name).arg(found->first->version));
95 found->second = wl_registry_bind(Reg, Name, found->first, static_cast<uint32_t>(found->first->version));
96 if (!found->second)
97 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to bind %1").arg(found->first->name));
98 }
99}
100
103{
104 static bool s_checked = false;
105 static bool s_available = false;
106 if (!s_checked)
107 {
108 s_checked = true;
109 auto waylanddisplay = qEnvironmentVariable("WAYLAND_DISPLAY");
110 const auto *name = waylanddisplay.isEmpty() ? nullptr : waylanddisplay.toLocal8Bit().constData();
111 if (auto *display = wl_display_connect(name); display)
112 {
113 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Available (WAYLAND_DISPLAY: '%1')")
114 .arg(waylanddisplay));
115 s_available = true;
116 wl_display_disconnect(display);
117 }
118 }
119 return s_available;
120}
bool SetOpaqueRegion(QRect Region) const
Provide a rendering optimisation hint to the compositor.
wl_display * m_display
static bool IsAvailable()
Check whether we can connect to a Wayland server.
wl_compositor * m_compositor
wl_surface * m_surface
MythWaylandDevice(QWidget *Widget)
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
#define LOC
std::map< const wl_interface *, void * > MythWaylandRegistry
static void AnnounceGlobal(void *Opaque, struct wl_registry *Reg, uint32_t Name, const char *Interface, uint32_t Version)
MythTV implementation of the Wayland registry callback.