Create a plugin for each of the wayland backends

Each of the backends becomes a plugin. This allows kwin_wayland to load
the requested plugin and kwin itself doesn't need to link all the
libraries needed. E.g. libdrm is no longer linked if running kwin_x11.
Also this allows to create backends for the non-standard EGL platforms
(examples could be raspberrypi or Android devices).
This commit is contained in:
Martin Gräßlin 2015-05-05 17:58:09 +02:00
parent 33fb763e37
commit 2220ae44c4
30 changed files with 189 additions and 147 deletions

View file

@ -436,39 +436,9 @@ if(HAVE_WAYLAND)
set(kwin_KDEINIT_SRCS
${kwin_KDEINIT_SRCS}
abstract_backend.cpp
backends/fbdev/fb_backend.cpp
backends/fbdev/logging.cpp
backends/fbdev/scene_qpainter_fb_backend.cpp
backends/fbdev/screens_fb.cpp
backends/wayland/scene_qpainter_wayland_backend.cpp
backends/wayland/screens_wayland.cpp
backends/x11/scene_qpainter_x11_backend.cpp
backends/x11/screens_x11windowed.cpp
virtual_terminal.cpp
backends/wayland/logging.cpp
backends/wayland/wayland_backend.cpp
wayland_server.cpp
backends/x11/x11windowed_backend.cpp
backends/x11/logging.cpp
)
if(KWIN_HAVE_EGL AND Wayland_Egl_FOUND)
set(kwin_KDEINIT_SRCS ${kwin_KDEINIT_SRCS} backends/wayland/egl_wayland_backend.cpp)
endif()
if(HAVE_DRM)
set(kwin_KDEINIT_SRCS
${kwin_KDEINIT_SRCS}
backends/drm/drm_backend.cpp
backends/drm/logging.cpp
backends/drm/screens_drm.cpp
backends/drm/scene_qpainter_drm_backend.cpp
)
endif()
if(HAVE_GBM)
set(kwin_KDEINIT_SRCS
${kwin_KDEINIT_SRCS}
backends/drm/egl_gbm_backend.cpp
)
endif()
if(HAVE_WAYLAND_CURSOR)
set(kwin_KDEINIT_SRCS
${kwin_KDEINIT_SRCS}
@ -565,14 +535,6 @@ set(kwin_WAYLAND_LIBS
${CMAKE_THREAD_LIBS_INIT}
)
set(kwin_WAYLAND_EGL_LIBS
Wayland::Egl
)
if(X11_XCB_FOUND)
set(kwin_WAYLAND_LIBS ${kwin_WAYLAND_LIBS} X11::XCB)
endif()
if(Wayland_Cursor_FOUND)
set(kwin_WAYLAND_LIBS ${kwin_WAYLAND_LIBS} Wayland::Cursor)
endif()
@ -595,9 +557,6 @@ set(kwinLibs
if(HAVE_WAYLAND)
set(kwinLibs ${kwinLibs} ${kwin_WAYLAND_LIBS})
if(KWIN_HAVE_EGL AND Wayland_Egl_FOUND)
set(kwinLibs ${kwinLibs} ${kwin_WAYLAND_EGL_LIBS})
endif()
endif()
if(UDEV_FOUND)
@ -608,14 +567,6 @@ if(HAVE_INPUT)
set(kwinLibs ${kwinLibs} Libinput::Libinput)
endif()
if(HAVE_DRM)
set(kwinLibs ${kwinLibs} Libdrm::Libdrm)
endif()
if(HAVE_GBM)
set(kwinLibs ${kwinLibs} gbm::gbm)
endif()
add_library(kwin SHARED ${kwin_KDEINIT_SRCS})
set_target_properties(kwin PROPERTIES
@ -652,6 +603,8 @@ if(HAVE_WAYLAND)
install(TARGETS kdeinit_kwin_wayland ${INSTALL_TARGETS_DEFAULT_ARGS} )
install(TARGETS kwin_wayland ${INSTALL_TARGETS_DEFAULT_ARGS} )
add_subdirectory(backends)
endif()
########### install files ###############

View file

@ -126,4 +126,6 @@ private:
}
Q_DECLARE_INTERFACE(KWin::AbstractBackend, "org.kde.kwin.AbstractBackend")
#endif

View file

@ -24,7 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
namespace KWin
{
class AbstractEglBackend : public OpenGLBackend
class KWIN_EXPORT AbstractEglBackend : public OpenGLBackend
{
public:
virtual ~AbstractEglBackend();
@ -75,7 +75,7 @@ private:
QList<QByteArray> m_clientExtensions;
};
class AbstractEglTexture : public SceneOpenGL::TexturePrivate
class KWIN_EXPORT AbstractEglTexture : public SceneOpenGL::TexturePrivate
{
public:
virtual ~AbstractEglTexture();

6
backends/CMakeLists.txt Normal file
View file

@ -0,0 +1,6 @@
if(HAVE_DRM)
add_subdirectory(drm)
endif()
add_subdirectory(fbdev)
add_subdirectory(wayland)
add_subdirectory(x11)

View file

@ -0,0 +1,24 @@
set(DRM_SOURCES
drm_backend.cpp
logging.cpp
scene_qpainter_drm_backend.cpp
screens_drm.cpp
)
if(HAVE_GBM)
set(DRM_SOURCES ${DRM_SOURCES} egl_gbm_backend.cpp)
endif()
add_library(KWinWaylandDrmBackend MODULE ${DRM_SOURCES})
target_link_libraries(KWinWaylandDrmBackend kwin Libdrm::Libdrm)
if(HAVE_GBM)
target_link_libraries(KWinWaylandDrmBackend gbm::gbm)
endif()
install(
TARGETS
KWinWaylandDrmBackend
DESTINATION
${PLUGIN_INSTALL_DIR}/org.kde.kwin.waylandbackends/
)

3
backends/drm/drm.json Normal file
View file

@ -0,0 +1,3 @@
{
"input": false
}

View file

@ -48,6 +48,8 @@ class DrmOutput;
class KWIN_EXPORT DrmBackend : public AbstractBackend
{
Q_OBJECT
Q_INTERFACES(KWin::AbstractBackend)
Q_PLUGIN_METADATA(IID "org.kde.kwin.AbstractBackend" FILE "drm.json")
public:
explicit DrmBackend(QObject *parent = nullptr);
virtual ~DrmBackend();

View file

@ -0,0 +1,16 @@
set(FBDEV_SOURCES
fb_backend.cpp
logging.cpp
scene_qpainter_fb_backend.cpp
screens_fb.cpp
)
add_library(KWinWaylandFbdevBackend MODULE ${FBDEV_SOURCES})
target_link_libraries(KWinWaylandFbdevBackend kwin)
install(
TARGETS
KWinWaylandFbdevBackend
DESTINATION
${PLUGIN_INSTALL_DIR}/org.kde.kwin.waylandbackends/
)

View file

@ -30,6 +30,8 @@ namespace KWin
class KWIN_EXPORT FramebufferBackend : public AbstractBackend
{
Q_OBJECT
Q_INTERFACES(KWin::AbstractBackend)
Q_PLUGIN_METADATA(IID "org.kde.kwin.AbstractBackend" FILE "fbdev.json")
public:
explicit FramebufferBackend(QObject *parent = nullptr);
virtual ~FramebufferBackend();

View file

@ -0,0 +1,3 @@
{
"input": false
}

View file

@ -0,0 +1,23 @@
set(WAYLAND_BACKEND_SOURCES
logging.cpp
scene_qpainter_wayland_backend.cpp
screens_wayland.cpp
wayland_backend.cpp
)
if(KWIN_HAVE_EGL AND Wayland_Egl_FOUND)
set(WAYLAND_BACKEND_SOURCES ${WAYLAND_BACKEND_SOURCES} egl_wayland_backend.cpp)
endif()
add_library(KWinWaylandWaylandBackend MODULE ${WAYLAND_BACKEND_SOURCES})
target_link_libraries(KWinWaylandWaylandBackend kwin KF5::WaylandClient)
if(KWIN_HAVE_EGL AND Wayland_Egl_FOUND)
target_link_libraries(KWinWaylandWaylandBackend Wayland::Egl)
endif()
install(
TARGETS
KWinWaylandWaylandBackend
DESTINATION
${PLUGIN_INSTALL_DIR}/org.kde.kwin.waylandbackends/
)

View file

@ -0,0 +1,3 @@
{
"input": true
}

View file

@ -132,6 +132,8 @@ private:
class KWIN_EXPORT WaylandBackend : public AbstractBackend
{
Q_OBJECT
Q_INTERFACES(KWin::AbstractBackend)
Q_PLUGIN_METADATA(IID "org.kde.kwin.AbstractBackend" FILE "wayland.json")
public:
explicit WaylandBackend(QObject *parent = nullptr);
virtual ~WaylandBackend();

View file

@ -0,0 +1,19 @@
set(X11BACKEND_SOURCES
logging.cpp
scene_qpainter_x11_backend.cpp
screens_x11windowed.cpp
x11windowed_backend.cpp
)
add_library(KWinWaylandX11Backend MODULE ${X11BACKEND_SOURCES})
target_link_libraries(KWinWaylandX11Backend kwin)
if(X11_XCB_FOUND)
target_link_libraries(KWinWaylandX11Backend X11::XCB)
endif()
install(
TARGETS
KWinWaylandX11Backend
DESTINATION
${PLUGIN_INSTALL_DIR}/org.kde.kwin.waylandbackends/
)

3
backends/x11/x11.json Normal file
View file

@ -0,0 +1,3 @@
{
"input": true
}

View file

@ -206,9 +206,6 @@ void X11WindowedBackend::handleClientMessage(xcb_client_message_event_t *event)
void X11WindowedBackend::handleButtonPress(xcb_button_press_event_t *event)
{
if (!input()) {
return;
}
bool const pressed = (event->response_type & ~0x80) == XCB_BUTTON_PRESS;
if (event->detail >= XCB_BUTTON_INDEX_4 && event->detail <= 7) {
// wheel

View file

@ -37,9 +37,11 @@ namespace KWin
class KWIN_EXPORT X11WindowedBackend : public AbstractBackend
{
Q_OBJECT
Q_INTERFACES(KWin::AbstractBackend)
Q_PLUGIN_METADATA(IID "org.kde.kwin.AbstractBackend" FILE "x11.json")
Q_PROPERTY(QSize size READ size NOTIFY sizeChanged)
public:
X11WindowedBackend(QObject *parent);
X11WindowedBackend(QObject *parent = nullptr);
virtual ~X11WindowedBackend();
void init() override;

View file

@ -49,7 +49,7 @@ private Q_SLOTS:
void looseOwnership();
};
class Compositor : public QObject {
class KWIN_EXPORT Compositor : public QObject {
Q_OBJECT
public:
enum SuspendReason { NoReasonSuspend = 0, UserSuspend = 1<<0, BlockRuleSuspend = 1<<1, ScriptSuspend = 1<<2, AllReasonSuspend = 0xff };

View file

@ -51,7 +51,7 @@ namespace KWin
* fetch the position and warp pointer to set the position. It uses a timer based mouse polling and
* can provide X11 cursors through the XCursor library.
**/
class Cursor : public QObject
class KWIN_EXPORT Cursor : public QObject
{
Q_OBJECT
public:

View file

@ -28,7 +28,7 @@ namespace KWin
/**
* @brief OpenGL Backend using Egl windowing system over an X overlay window.
**/
class EglOnXBackend : public AbstractEglBackend
class KWIN_EXPORT EglOnXBackend : public AbstractEglBackend
{
public:
EglOnXBackend();

View file

@ -30,7 +30,7 @@ class QDBusServiceWatcher;
namespace KWin
{
class LogindIntegration : public QObject
class KWIN_EXPORT LogindIntegration : public QObject
{
Q_OBJECT
public:

View file

@ -21,20 +21,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "workspace.h"
#include <config-kwin.h>
// kwin
#include "backends/fbdev/fb_backend.h"
#if HAVE_DRM
#include "backends/drm/drm_backend.h"
#endif
#include "backends/wayland/wayland_backend.h"
#include "abstract_backend.h"
#include "wayland_server.h"
#include "xcbutils.h"
#include "backends/x11/x11windowed_backend.h"
// KWayland
#include <KWayland/Server/display.h>
#include <KWayland/Server/seat_interface.h>
// KDE
#include <KLocalizedString>
#include <KPluginLoader>
#include <KPluginMetaData>
// Qt
#include <qplatformdefs.h>
#include <QCommandLineParser>
@ -98,45 +95,15 @@ void ApplicationWayland::performStartup()
void ApplicationWayland::createBackend()
{
AbstractBackend *backend = nullptr;
if (m_windowed) {
if (!m_waylandDisplay.isEmpty()) {
Wayland::WaylandBackend *b = new Wayland::WaylandBackend(this);
b->setDeviceIdentifier(m_waylandDisplay);
backend = b;
AbstractBackend *backend = waylandServer()->backend();
connect(backend, &AbstractBackend::screensQueried, this, &ApplicationWayland::continueStartupWithScreens);
connect(backend, &AbstractBackend::initFailed, this,
[] () {
std::cerr << "FATAL ERROR: backend failed to initialize, exiting now" << std::endl;
::exit(1);
}
if (!backend && !m_x11Display.isEmpty()) {
KWin::X11WindowedBackend *x11Backend = new KWin::X11WindowedBackend(this);
x11Backend->setDeviceIdentifier(m_x11Display);
backend = x11Backend;
}
}
#if HAVE_DRM
if (m_drm) {
DrmBackend *b = new DrmBackend(this);
backend = b;
}
#endif
if (!m_framebuffer.isEmpty()) {
FramebufferBackend *b = new FramebufferBackend(this);
b->setDeviceIdentifier(m_framebuffer.toUtf8());
backend = b;
}
if (backend) {
connect(backend, &AbstractBackend::screensQueried, this, &ApplicationWayland::continueStartupWithScreens);
connect(backend, &AbstractBackend::initFailed, this,
[] () {
std::cerr << "FATAL ERROR: backend failed to initialize, exiting now" << std::endl;
::exit(1);
}
);
backend->setInitialWindowSize(m_backendSize);
backend->init();
} else {
std::cerr << "FATAL ERROR: could not create a backend, exiting now" << std::endl;
::exit(1);
}
);
backend->init();
}
void ApplicationWayland::continueStartupWithScreens()
@ -464,6 +431,9 @@ KWIN_EXPORT int kdemain(int argc, char * argv[])
KWin::Application::setUseLibinput(parser.isSet(libinputOption));
#endif
QString pluginName;
QSize initialWindowSize;
QByteArray deviceIdentifier;
if (parser.isSet(windowedOption) && parser.isSet(framebufferOption)) {
std::cerr << "FATAL ERROR Cannot have both --windowed and --framebuffer" << std::endl;
return 1;
@ -473,10 +443,11 @@ KWIN_EXPORT int kdemain(int argc, char * argv[])
std::cerr << "FATAL ERROR Cannot have both --windowed/--framebuffer and --drm" << std::endl;
return 1;
}
a.setDrm(parser.isSet(drmOption));
if (parser.isSet(drmOption)) {
pluginName = QStringLiteral("KWinWaylandDrmBackend");
}
#endif
a.setWindowed(parser.isSet(windowedOption));
if (parser.isSet(windowedOption)) {
bool ok = false;
const int width = parser.value(widthOption).toInt(&ok);
@ -489,20 +460,54 @@ KWIN_EXPORT int kdemain(int argc, char * argv[])
std::cerr << "FATAL ERROR incorrect value for height" << std::endl;
return 1;
}
a.setBackendSize(QSize(width, height));
initialWindowSize = QSize(width, height);
if (parser.isSet(x11DisplayOption)) {
a.setX11Display(parser.value(x11DisplayOption).toUtf8());
deviceIdentifier = parser.value(x11DisplayOption).toUtf8();
} else if (!parser.isSet(waylandDisplayOption)) {
a.setX11Display(qgetenv("DISPLAY"));
deviceIdentifier = qgetenv("DISPLAY");
}
if (parser.isSet(waylandDisplayOption)) {
a.setWaylandDisplay(parser.value(waylandDisplayOption).toUtf8());
} else if (!parser.isSet(x11DisplayOption)) {
a.setWaylandDisplay(qgetenv("WAYLAND_DISPLAY"));
if (!deviceIdentifier.isEmpty()) {
pluginName = QStringLiteral("KWinWaylandX11Backend");
} else {
if (parser.isSet(waylandDisplayOption)) {
deviceIdentifier = parser.value(waylandDisplayOption).toUtf8();
} else if (!parser.isSet(x11DisplayOption)) {
deviceIdentifier = qgetenv("WAYLAND_DISPLAY");
}
if (!deviceIdentifier.isEmpty()) {
pluginName = QStringLiteral("KWinWaylandWaylandBackend");
}
}
}
if (parser.isSet(framebufferOption)) {
a.setFramebuffer(parser.value(framebufferDeviceOption));
pluginName = QStringLiteral("KWinWaylandFbdevBackend");
deviceIdentifier = parser.value(framebufferDeviceOption).toUtf8();
}
const auto pluginCandidates = KPluginLoader::findPlugins(QStringLiteral("org.kde.kwin.waylandbackends"),
[&pluginName] (const KPluginMetaData &plugin) {
return plugin.pluginId() == pluginName;
}
);
if (pluginCandidates.isEmpty()) {
std::cerr << "FATAL ERROR: could not find a backend" << std::endl;
return 1;
}
for (const auto &candidate: pluginCandidates) {
if (qobject_cast<KWin::AbstractBackend*>(candidate.instantiate())) {
break;
}
}
if (!server->backend()) {
std::cerr << "FATAL ERROR: could not instantiate a backend" << std::endl;
return 1;
}
server->backend()->setParent(server);
if (!deviceIdentifier.isEmpty()) {
server->backend()->setDeviceIdentifier(deviceIdentifier);
}
if (initialWindowSize.isValid()) {
server->backend()->setInitialWindowSize(initialWindowSize);
}
a.setStartXwayland(parser.isSet(xwaylandOption));

View file

@ -34,24 +34,6 @@ public:
void setStartXwayland(bool start) {
m_startXWayland = start;
}
void setBackendSize(const QSize &size) {
m_backendSize = size;
}
void setWindowed(bool set) {
m_windowed = set;
}
void setX11Display(const QByteArray &display) {
m_x11Display = display;
}
void setWaylandDisplay(const QByteArray &display) {
m_waylandDisplay = display;
}
void setFramebuffer(const QString &fbdev) {
m_framebuffer = fbdev;
}
void setDrm(bool set) {
m_drm = set;
}
void setApplicationsToStart(const QStringList &applications) {
m_applicationsToStart = applications;
}
@ -67,12 +49,6 @@ private:
bool m_startXWayland = false;
int m_xcbConnectionFd = -1;
QSize m_backendSize;
bool m_windowed = false;
QByteArray m_x11Display;
QByteArray m_waylandDisplay;
QString m_framebuffer;
bool m_drm = false;
QStringList m_applicationsToStart;
};

View file

@ -45,7 +45,7 @@ enum HiddenPreviews {
class Settings;
class Options : public QObject
class KWIN_EXPORT Options : public QObject
{
Q_OBJECT
Q_ENUMS(FocusPolicy)
@ -932,7 +932,7 @@ private:
MouseCommand wheelToMouseCommand(MouseWheelCommand com, int delta) const;
};
extern Options* options;
extern KWIN_EXPORT Options* options;
} // namespace

View file

@ -370,7 +370,7 @@ private:
*
* @author Martin Gräßlin <mgraesslin@kde.org>
**/
class OpenGLBackend
class KWIN_EXPORT OpenGLBackend
{
public:
OpenGLBackend();

View file

@ -31,7 +31,7 @@ namespace Xcb {
class Shm;
}
class QPainterBackend
class KWIN_EXPORT QPainterBackend
{
public:
virtual ~QPainterBackend();

View file

@ -34,7 +34,7 @@ namespace KWin
{
class Client;
class Screens : public QObject
class KWIN_EXPORT Screens : public QObject
{
Q_OBJECT
Q_PROPERTY(int count READ count WRITE setCount NOTIFY countChanged)

7
udev.h
View file

@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef KWIN_UDEV_H
#define KWIN_UDEV_H
#include <memory>
#include <kwin_export.h>
struct udev;
struct udev_device;
@ -29,7 +30,7 @@ namespace KWin
{
class Udev;
class UdevDevice
class KWIN_EXPORT UdevDevice
{
public:
UdevDevice(udev_device *device);
@ -53,7 +54,7 @@ private:
udev_device *m_device;
};
class UdevMonitor
class KWIN_EXPORT UdevMonitor
{
public:
explicit UdevMonitor(Udev *udev);
@ -72,7 +73,7 @@ private:
udev_monitor *m_monitor;
};
class Udev
class KWIN_EXPORT Udev
{
public:
Udev();

View file

@ -28,7 +28,7 @@ class QSocketNotifier;
namespace KWin
{
class VirtualTerminal : public QObject
class KWIN_EXPORT VirtualTerminal : public QObject
{
Q_OBJECT
public:

View file

@ -1192,7 +1192,7 @@ public:
QVector<QByteArray> errorCodes;
};
class Extensions
class KWIN_EXPORT Extensions
{
public:
bool isShapeAvailable() const {