diff --git a/qml/CMakeLists.txt b/qml/CMakeLists.txt --- a/qml/CMakeLists.txt +++ b/qml/CMakeLists.txt @@ -1,2 +1,4 @@ install( DIRECTORY outline/plasma DESTINATION ${DATA_INSTALL_DIR}/${KWIN_NAME}/outline ) install( DIRECTORY virtualkeyboard DESTINATION ${DATA_INSTALL_DIR}/${KWIN_NAME} ) + +add_subdirectory(kwinqml) diff --git a/qml/kwinqml/CMakeLists.txt b/qml/kwinqml/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/qml/kwinqml/CMakeLists.txt @@ -0,0 +1,17 @@ +set(kwinqmlplugin_SRCS + kwinqml.cpp + kwinplugin.cpp +) + +install(FILES qmldir DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/kwin/app) + +add_library(kwinqmlplugin SHARED ${kwinqmlplugin_SRCS}) + +target_link_libraries(kwinqmlplugin + Qt5::Qml + Qt5::Quick + KF5::WaylandClient + KF5::WaylandServer +) + +install(TARGETS kwinqmlplugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/kwin/app) diff --git a/qml/kwinqml/kwinplugin.h b/qml/kwinqml/kwinplugin.h new file mode 100644 --- /dev/null +++ b/qml/kwinqml/kwinplugin.h @@ -0,0 +1,16 @@ +#ifndef KWINPLUGIN_H +#define KWINPLUGIN_H + +#include +#include + +class KWinPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + + public: + void registerTypes(const char *uri) override; +}; + +#endif //KWINPLUGIN_H diff --git a/qml/kwinqml/kwinplugin.cpp b/qml/kwinqml/kwinplugin.cpp new file mode 100644 --- /dev/null +++ b/qml/kwinqml/kwinplugin.cpp @@ -0,0 +1,10 @@ +#include "kwinplugin.h" +#include "kwinqml.h" +#include + +void KWinPlugin::registerTypes(const char *uri) +{ + Q_ASSERT(uri == QLatin1String("org.kde.kwin.app")); + qmlRegisterType(uri, 1, 0,"KWinApp"); +} + diff --git a/qml/kwinqml/kwinqml.h b/qml/kwinqml/kwinqml.h new file mode 100644 --- /dev/null +++ b/qml/kwinqml/kwinqml.h @@ -0,0 +1,46 @@ +#include +#include + +namespace KWayland +{ +namespace Server +{ +class Display; +class SeatInterface; +class ShellInterface; +} +} + +class KWinQml : public QQuickItem +{ + Q_OBJECT + Q_PROPERTY(QString socketName READ socketName WRITE setSocketName NOTIFY socketNameChanged) + +public: + KWinQml(); + ~KWinQml() override; + + void setSocketName(const QString socketName) + { + m_name = "kwin-plasma-emulator-0"; + emit socketNameChanged(socketName); + } + + QString socketName() const + { + return m_name; + } + + Q_INVOKABLE void start(); + +signals: + void socketNameChanged(QString); + +private: + QString m_name; + KWayland::Server::Display *m_display = nullptr; + KWayland::Server::SeatInterface *m_seat = nullptr; + KWayland::Server::ShellInterface *m_shell = nullptr; + +}; + diff --git a/qml/kwinqml/kwinqml.cpp b/qml/kwinqml/kwinqml.cpp new file mode 100644 --- /dev/null +++ b/qml/kwinqml/kwinqml.cpp @@ -0,0 +1,63 @@ +#include "kwinqml.h" +#include +#include +#include +#include +#include +#include + +// system +#include +#include +#include + +using namespace KWayland::Server; + +KWinQml::KWinQml() +{ +} + +KWinQml::~KWinQml() +{ +} +void KWinQml::start() +{ + Q_ASSERT(!m_display); + m_display = new Display(this); + m_display->start(Display::StartMode::ConnectClientsOnly); + m_display->createShm(); + m_display->createCompositor()->create(); + m_seat = m_display->createSeat(m_display); + m_seat->setHasTouch(true); + m_seat->create(); + m_shell = m_display->createShell(m_display); + // output + auto output = m_display->createOutput(m_display); + const QSize size(height(), width()); + output->setGlobalPosition(QPoint(0, 0)); + output->setPhysicalSize(size / 3.8); + output->addMode(size); + output->create(); + + int sx[2]; + if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sx) < 0) { + QCoreApplication::instance()->exit(1); + return; + } + m_display->createClient(sx[0]); + int socket = dup(sx[1]); + if (socket == -1) { + QCoreApplication::instance()->exit(1); + return; + } + QProcess *kwinWayland = new QProcess(this); + kwinWayland->setProcessChannelMode(QProcess::ForwardedChannels); + QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); + environment.insert(QStringLiteral("QT_QPA_PLATFORM"), QStringLiteral("wayland")); + environment.insert(QStringLiteral("WAYLAND_SOCKET"), QString::fromUtf8(QByteArray::number(socket))); + kwinWayland->setProcessEnvironment(environment); + //TODO: Start Kwin_wayland here + QStringList arguments; + arguments << "--xwayland"; + kwinWayland->start("kwin_wayland", arguments); +} diff --git a/qml/kwinqml/qmldir b/qml/kwinqml/qmldir new file mode 100644 --- /dev/null +++ b/qml/kwinqml/qmldir @@ -0,0 +1,2 @@ +module org.kde.kwin.app +plugin kwinqmlplugin