Commit b8af0f13 authored by Jan Grulich's avatar Jan Grulich

Make PipeWire, GBM and Epoxy libs as required dependencies

Summary: Also allow to completely disable PipeWire support in case some distribution don't ship PipeWire yet.

Reviewers: #plasma, apol

Reviewed By: apol

Subscribers: arfrever, apol, asturmlechner, davidedmundson, plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D28677
parent 8969e6bb
......@@ -20,33 +20,35 @@ include(KDEClangFormat)
include(FeatureSummary)
find_package(PipeWire)
set_package_properties(PipeWire PROPERTIES
TYPE OPTIONAL
PURPOSE "Required for screencast portal"
)
find_package(GBM)
set_package_properties(GBM PROPERTIES
TYPE OPTIONAL
PURPOSE "Required for screencast portal"
)
find_package(Epoxy)
set_package_properties(Epoxy PROPERTIES DESCRIPTION "libepoxy"
URL "https://github.com/anholt/libepoxy"
TYPE OPTIONAL
PURPOSE "Required for screencast portal"
)
if (PipeWire_FOUND AND GBM_FOUND AND Epoxy_FOUND)
set (SCREENCAST_ENABLED true)
option(ENABLE_PIPEWIRE "Disable PipeWire support. PipeWire is needed for screen sharing and remote desktop" ON)
if(ENABLE_PIPEWIRE)
set(HAVE_PIPEWIRE_SUPPORT 1)
else()
set (SCREENCAST_ENABLED false)
message(STATUS "Disabling PipeWire support")
set(HAVE_PIPEWIRE_SUPPORT 0)
endif()
add_definitions(-DHAVE_PIPEWIRE_SUPPORT=${HAVE_PIPEWIRE_SUPPORT})
if(HAVE_PIPEWIRE_SUPPORT)
find_package(PipeWire)
set_package_properties(PipeWire PROPERTIES
TYPE REQUIRED
PURPOSE "Required for screencast portal"
)
find_package(GBM)
set_package_properties(GBM PROPERTIES
TYPE REQUIRED
PURPOSE "Required for screencast portal"
)
find_package(Epoxy)
set_package_properties(Epoxy PROPERTIES DESCRIPTION "libepoxy"
URL "https://github.com/anholt/libepoxy"
TYPE REQUIRED
PURPOSE "Required for screencast portal"
)
endif()
add_definitions(-DSCREENCAST_ENABLED=${SCREENCAST_ENABLED})
add_feature_info ("Screencast portal" ${SCREENCAST_ENABLED} "Support for screen sharing")
find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
Core
......
......@@ -2,5 +2,9 @@ configure_file(org.freedesktop.impl.portal.desktop.kde.desktop.in org.freedeskto
configure_file(org.freedesktop.impl.portal.desktop.kde.cmake.in org.freedesktop.impl.portal.desktop.kde.service @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.impl.portal.desktop.kde.service DESTINATION ${KDE_INSTALL_DBUSSERVICEDIR})
install(FILES kde.portal DESTINATION ${DATA_INSTALL_DIR}/xdg-desktop-portal/portals)
if(HAVE_PIPEWIRE_SUPPORT)
install(FILES kde.portal DESTINATION ${DATA_INSTALL_DIR}/xdg-desktop-portal/portals)
else()
install(FILES kde-no-pipewire.portal DESTINATION ${DATA_INSTALL_DIR}/xdg-desktop-portal/portals RENAME kde.portal)
endif()
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.impl.portal.desktop.kde.desktop DESTINATION ${XDG_APPS_INSTALL_DIR})
[portal]
DBusName=org.freedesktop.impl.portal.desktop.kde
Interfaces=org.freedesktop.impl.portal.Access;org.freedesktop.impl.portal.Account;org.freedesktop.impl.portal.AppChooser;org.freedesktop.impl.portal.Background;org.freedesktop.impl.portal.Email;org.freedesktop.impl.portal.FileChooser;org.freedesktop.impl.portal.Inhibit;org.freedesktop.impl.portal.Notification;org.freedesktop.impl.portal.Print;org.freedesktop.impl.portal.Screenshot;org.freedesktop.impl.portal.Settings
UseIn=KDE
......@@ -23,9 +23,10 @@ set(xdg_desktop_portal_kde_SRCS
settings.cpp
utils.cpp
userinfodialog.cpp
waylandintegration.cpp
)
if (SCREENCAST_ENABLED)
if(HAVE_PIPEWIRE_SUPPORT)
set (xdg_desktop_portal_kde_SRCS
${xdg_desktop_portal_kde_SRCS}
screencast.cpp
......@@ -33,8 +34,7 @@ if (SCREENCAST_ENABLED)
screencastwidget.cpp
screenchooserdialog.cpp
remotedesktop.cpp
remotedesktopdialog.cpp
waylandintegration.cpp)
remotedesktopdialog.cpp)
ki18n_wrap_ui(xdg_desktop_portal_kde_SRCS
screenchooserdialog.ui
......@@ -72,7 +72,7 @@ target_link_libraries(xdg-desktop-portal-kde
KF5::WindowSystem
)
if (SCREENCAST_ENABLED)
if (HAVE_PIPEWIRE_SUPPORT)
target_link_libraries(xdg-desktop-portal-kde
PipeWire::PipeWire
${Epoxy_LIBRARIES}
......
......@@ -39,11 +39,11 @@ DesktopPortal::DesktopPortal(QObject *parent)
const QByteArray xdgCurrentDesktop = qgetenv("XDG_CURRENT_DESKTOP").toUpper();
if (xdgCurrentDesktop == "KDE") {
m_background = new BackgroundPortal(this);
m_screenshot = new ScreenshotPortal(this);
#if SCREENCAST_ENABLED
#if HAVE_PIPEWIRE_SUPPORT
m_screenCast = new ScreenCastPortal(this);
m_remoteDesktop = new RemoteDesktopPortal(this);
#endif
m_screenshot = new ScreenshotPortal(this);
WaylandIntegration::init();
}
}
......
......@@ -33,14 +33,15 @@
#include "inhibit.h"
#include "notification.h"
#include "print.h"
#if SCREENCAST_ENABLED
#include "screencast.h"
#include "remotedesktop.h"
#endif
#include "screenshot.h"
#include "settings.h"
#include "waylandintegration.h"
#if HAVE_PIPEWIRE_SUPPORT
#include "screencast.h"
#include "remotedesktop.h"
#endif
class DesktopPortal : public QObject, public QDBusContext
{
Q_OBJECT
......@@ -58,12 +59,12 @@ private:
InhibitPortal *m_inhibit;
NotificationPortal *m_notification;
PrintPortal *m_print;
#if SCREENCAST_ENABLED
ScreenshotPortal *m_screenshot;
SettingsPortal *m_settings;
#if HAVE_PIPEWIRE_SUPPORT
ScreenCastPortal *m_screenCast;
RemoteDesktopPortal *m_remoteDesktop;
#endif
ScreenshotPortal *m_screenshot;
SettingsPortal *m_settings;
};
#endif // XDG_DESKTOP_PORTAL_KDE_DESKTOP_PORTAL_H
......
......@@ -20,7 +20,7 @@
#include "waylandintegration.h"
#include "waylandintegration_p.h"
#include "screencaststream.h"
#include <QDBusArgument>
#include <QDBusMetaType>
......@@ -37,33 +37,39 @@
// KWayland
#include <KWayland/Client/connection_thread.h>
#include <KWayland/Client/event_queue.h>
#include <KWayland/Client/fakeinput.h>
#include <KWayland/Client/registry.h>
#include <KWayland/Client/output.h>
#include <KWayland/Client/remote_access.h>
#include <KWayland/Client/plasmawindowmanagement.h>
// system
#include <fcntl.h>
#include <unistd.h>
#if HAVE_PIPEWIRE_SUPPORT
#include "screencaststream.h"
#include <KWayland/Client/fakeinput.h>
#include <KWayland/Client/output.h>
#include <KWayland/Client/remote_access.h>
#endif
Q_LOGGING_CATEGORY(XdgDesktopPortalKdeWaylandIntegration, "xdp-kde-wayland-integration")
Q_GLOBAL_STATIC(WaylandIntegration::WaylandIntegrationPrivate, globalWaylandIntegration)
void WaylandIntegration::authenticate()
{
globalWaylandIntegration->authenticate();
}
void WaylandIntegration::init()
{
#if SCREENCAST_ENABLED
#if HAVE_PIPEWIRE_SUPPORT
globalWaylandIntegration->initDrm();
#endif
globalWaylandIntegration->initWayland();
}
#if HAVE_PIPEWIRE_SUPPORT
void WaylandIntegration::authenticate()
{
globalWaylandIntegration->authenticate();
}
bool WaylandIntegration::isEGLInitialized()
{
return globalWaylandIntegration->isEGLInitialized();
......@@ -124,11 +130,6 @@ WaylandIntegration::EGLStruct WaylandIntegration::egl()
return globalWaylandIntegration->egl();
}
KWayland::Client::PlasmaWindowManagement * WaylandIntegration::plasmaWindowManagement()
{
return globalWaylandIntegration->plasmaWindowManagement();
}
QMap<quint32, WaylandIntegration::WaylandOutput> WaylandIntegration::screens()
{
return globalWaylandIntegration->screens();
......@@ -139,11 +140,6 @@ QVariant WaylandIntegration::streams()
return globalWaylandIntegration->streams();
}
WaylandIntegration::WaylandIntegration * WaylandIntegration::waylandIntegration()
{
return globalWaylandIntegration;
}
const char * WaylandIntegration::formatGLError(GLenum err)
{
switch(err) {
......@@ -223,24 +219,38 @@ const QDBusArgument &operator << (QDBusArgument &arg, const WaylandIntegration::
Q_DECLARE_METATYPE(WaylandIntegration::WaylandIntegrationPrivate::Stream)
Q_DECLARE_METATYPE(WaylandIntegration::WaylandIntegrationPrivate::Streams)
#endif
KWayland::Client::PlasmaWindowManagement * WaylandIntegration::plasmaWindowManagement()
{
return globalWaylandIntegration->plasmaWindowManagement();
}
WaylandIntegration::WaylandIntegration * WaylandIntegration::waylandIntegration()
{
return globalWaylandIntegration;
}
WaylandIntegration::WaylandIntegrationPrivate::WaylandIntegrationPrivate()
: WaylandIntegration()
, m_eglInitialized(false)
, m_registryInitialized(false)
, m_waylandAuthenticationRequested(false)
, m_connection(nullptr)
, m_queue(nullptr)
, m_fakeInput(nullptr)
, m_registry(nullptr)
#if HAVE_PIPEWIRE_SUPPORT
, m_fakeInput(nullptr)
, m_remoteAccessManager(nullptr)
#endif
{
#if HAVE_PIPEWIRE_SUPPORT
qDBusRegisterMetaType<WaylandIntegrationPrivate::Stream>();
qDBusRegisterMetaType<WaylandIntegrationPrivate::Streams>();
#endif
}
WaylandIntegration::WaylandIntegrationPrivate::~WaylandIntegrationPrivate()
{
#if HAVE_PIPEWIRE_SUPPORT
if (m_remoteAccessManager) {
m_remoteAccessManager->destroy();
}
......@@ -248,8 +258,10 @@ WaylandIntegration::WaylandIntegrationPrivate::~WaylandIntegrationPrivate()
if (m_gbmDevice) {
gbm_device_destroy(m_gbmDevice);
}
#endif
}
#if HAVE_PIPEWIRE_SUPPORT
bool WaylandIntegration::WaylandIntegrationPrivate::isEGLInitialized() const
{
return m_eglInitialized;
......@@ -414,11 +426,6 @@ QMap<quint32, WaylandIntegration::WaylandOutput> WaylandIntegration::WaylandInte
return m_outputMap;
}
KWayland::Client::PlasmaWindowManagement * WaylandIntegration::WaylandIntegrationPrivate::plasmaWindowManagement()
{
return m_windowManagement;
}
QVariant WaylandIntegration::WaylandIntegrationPrivate::streams()
{
Stream stream;
......@@ -427,14 +434,6 @@ QVariant WaylandIntegration::WaylandIntegrationPrivate::streams()
return QVariant::fromValue<WaylandIntegrationPrivate::Streams>({stream});
}
void WaylandIntegration::WaylandIntegrationPrivate::authenticate()
{
if (!m_waylandAuthenticationRequested) {
m_fakeInput->authenticate(i18n("xdg-desktop-portals-kde"), i18n("Remote desktop"));
m_waylandAuthenticationRequested = true;
}
}
void WaylandIntegration::WaylandIntegrationPrivate::initDrm()
{
m_drmFd = open("/dev/dri/renderD128", O_RDWR);
......@@ -506,6 +505,21 @@ void WaylandIntegration::WaylandIntegrationPrivate::initEGL()
m_eglInitialized = true;
}
void WaylandIntegration::WaylandIntegrationPrivate::authenticate()
{
if (!m_waylandAuthenticationRequested) {
m_fakeInput->authenticate(i18n("xdg-desktop-portals-kde"), i18n("Remote desktop"));
m_waylandAuthenticationRequested = true;
}
}
#endif
KWayland::Client::PlasmaWindowManagement * WaylandIntegration::WaylandIntegrationPrivate::plasmaWindowManagement()
{
return m_windowManagement;
}
void WaylandIntegration::WaylandIntegrationPrivate::initWayland()
{
m_thread = new QThread(this);
......@@ -541,6 +555,7 @@ void WaylandIntegration::WaylandIntegrationPrivate::initWayland()
m_connection->initConnection();
}
#if HAVE_PIPEWIRE_SUPPORT
void WaylandIntegration::WaylandIntegrationPrivate::addOutput(quint32 name, quint32 version)
{
KWayland::Client::Output *output = new KWayland::Client::Output(this);
......@@ -621,6 +636,7 @@ void WaylandIntegration::WaylandIntegrationPrivate::processBuffer(const KWayland
gbm_bo_destroy(imported);
close(gbmHandle);
}
#endif
void WaylandIntegration::WaylandIntegrationPrivate::setupRegistry()
{
......@@ -629,13 +645,14 @@ void WaylandIntegration::WaylandIntegrationPrivate::setupRegistry()
m_registry = new KWayland::Client::Registry(this);
#if SCREENCAST_ENABLED
#if HAVE_PIPEWIRE_SUPPORT
connect(m_registry, &KWayland::Client::Registry::fakeInputAnnounced, this, [this] (quint32 name, quint32 version) {
m_fakeInput = m_registry->createFakeInput(name, version, this);
});
connect(m_registry, &KWayland::Client::Registry::outputAnnounced, this, &WaylandIntegrationPrivate::addOutput);
connect(m_registry, &KWayland::Client::Registry::outputRemoved, this, &WaylandIntegrationPrivate::removeOutput);
#endif
connect(m_registry, &KWayland::Client::Registry::plasmaWindowManagementAnnounced, this, [this] (quint32 name, quint32 version) {
m_windowManagement = m_registry->createPlasmaWindowManagement(name, version, this);
Q_EMIT waylandIntegration()->plasmaWindowManagementInitialized();
......
......@@ -26,10 +26,11 @@
#include <QSize>
#include <QVariant>
#if HAVE_PIPEWIRE_SUPPORT
#include <gbm.h>
#include <epoxy/egl.h>
#include <epoxy/gl.h>
#endif
namespace KWayland {
namespace Client {
......@@ -39,7 +40,7 @@ namespace KWayland {
namespace WaylandIntegration
{
#if HAVE_PIPEWIRE_SUPPORT
struct EGLStruct {
QList<QByteArray> extensions;
EGLDisplay display = EGL_NO_DISPLAY;
......@@ -86,18 +87,22 @@ private:
int m_waylandOutputName;
int m_waylandOutputVersion;
};
#endif
class WaylandIntegration : public QObject
{
Q_OBJECT
Q_SIGNALS:
#if HAVE_PIPEWIRE_SUPPORT
void newBuffer(uint8_t *screenData);
#endif
void plasmaWindowManagementInitialized();
};
#if HAVE_PIPEWIRE_SUPPORT
const char * formatGLError(GLenum err);
void authenticate();
void init();
bool isEGLInitialized();
bool isStreamingEnabled();
......@@ -115,10 +120,12 @@ Q_SIGNALS:
void requestKeyboardKeycode(int keycode, bool state);
EGLStruct egl();
KWayland::Client::PlasmaWindowManagement *plasmaWindowManagement();
QMap<quint32, WaylandOutput> screens();
QVariant streams();
#endif
void init();
KWayland::Client::PlasmaWindowManagement *plasmaWindowManagement();
WaylandIntegration *waylandIntegration();
}
......
......@@ -26,19 +26,23 @@
#include <QDateTime>
#include <QMap>
#if HAVE_PIPEWIRE_SUPPORT
class ScreenCastStream;
#endif
namespace KWayland {
namespace Client {
class ConnectionThread;
class EventQueue;
class FakeInput;
class Registry;
class RemoteAccessManager;
class RemoteBuffer;
class Output;
class PlasmaWindow;
class PlasmaWindowManagement;
#if HAVE_PIPEWIRE_SUPPORT
class FakeInput;
class RemoteBuffer;
class Output;
class RemoteAccessManager;
#endif
}
}
......@@ -48,6 +52,27 @@ namespace WaylandIntegration
class WaylandIntegrationPrivate : public WaylandIntegration::WaylandIntegration
{
Q_OBJECT
public:
WaylandIntegrationPrivate();
~WaylandIntegrationPrivate();
void initWayland();
KWayland::Client::PlasmaWindowManagement *plasmaWindowManagement();
protected Q_SLOTS:
void setupRegistry();
private:
bool m_registryInitialized = false;
QThread *m_thread = nullptr;
KWayland::Client::ConnectionThread *m_connection = nullptr;
KWayland::Client::EventQueue *m_queue = nullptr;
KWayland::Client::Registry *m_registry = nullptr;
KWayland::Client::PlasmaWindowManagement *m_windowManagement = nullptr;
#if HAVE_PIPEWIRE_SUPPORT
public:
typedef struct {
uint nodeId;
......@@ -55,13 +80,10 @@ public:
} Stream;
typedef QList<Stream> Streams;
WaylandIntegrationPrivate();
~WaylandIntegrationPrivate();
void authenticate();
void initDrm();
void initEGL();
void initWayland();
bool isEGLInitialized() const;
bool isStreamingEnabled() const;
......@@ -79,7 +101,6 @@ public:
void requestKeyboardKeycode(int keycode, bool state);
EGLStruct egl();
KWayland::Client::PlasmaWindowManagement *plasmaWindowManagement();
QMap<quint32, WaylandOutput> screens();
QVariant streams();
......@@ -87,37 +108,30 @@ protected Q_SLOTS:
void addOutput(quint32 name, quint32 version);
void removeOutput(quint32 name);
void processBuffer(const KWayland::Client::RemoteBuffer *rbuf);
void setupRegistry();
private:
bool m_eglInitialized = false;
bool m_streamingEnabled = false;
bool m_streamInput = false;
bool m_registryInitialized = false;
bool m_waylandAuthenticationRequested = false;
quint32 m_output;
QDateTime m_lastFrameTime;
ScreenCastStream *m_stream = nullptr;
QThread *m_thread = nullptr;
QPoint m_streamedScreenPosition;
QMap<quint32, WaylandOutput> m_outputMap;
QList<KWayland::Client::Output*> m_bindOutputs;
KWayland::Client::ConnectionThread *m_connection = nullptr;
KWayland::Client::EventQueue *m_queue = nullptr;
KWayland::Client::FakeInput *m_fakeInput = nullptr;
KWayland::Client::Registry *m_registry = nullptr;
KWayland::Client::RemoteAccessManager *m_remoteAccessManager = nullptr;
KWayland::Client::PlasmaWindowManagement *m_windowManagement = nullptr;
qint32 m_drmFd = 0; // for GBM buffer mmap
gbm_device *m_gbmDevice = nullptr; // for passed GBM buffer retrieval
EGLStruct m_egl;
#endif
};
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment