diff --git a/klipper/CMakeLists.txt b/klipper/CMakeLists.txt index 0370354ba..825533db2 100644 --- a/klipper/CMakeLists.txt +++ b/klipper/CMakeLists.txt @@ -47,6 +47,7 @@ target_link_libraries(libklipper_common_static KF5::WindowSystem KF5::WidgetsAddons KF5::XmlGui + KF5::WaylandClient ${ZLIB_LIBRARY}) if (X11_FOUND) target_link_libraries(libklipper_common_static XCB::XCB) diff --git a/klipper/klipper.cpp b/klipper/klipper.cpp index 3b11c6ecc..c91e1d134 100644 --- a/klipper/klipper.cpp +++ b/klipper/klipper.cpp @@ -27,6 +27,10 @@ #include #include #include +#include +#include +#include +#include #include #include "configdialog.h" @@ -113,6 +117,7 @@ Klipper::Klipper(QObject *parent, const KSharedConfigPtr &config, KlipperMode mo , m_config(config) , m_pendingContentsCheck(false) , m_mode(mode) + , m_plasmashell(nullptr) { if (m_mode == KlipperMode::Standalone) { setenv("KSNI_NO_DBUSMENU", "1", 1); @@ -249,6 +254,18 @@ Klipper::Klipper(QObject *parent, const KSharedConfigPtr &config, KlipperMode mo m_notification->setHint(QStringLiteral("desktop-entry"), QStringLiteral("org.kde.klipper")); } }); + + if (KWindowSystem::isPlatformWayland()) { + auto registry = new KWayland::Client::Registry(this); + auto connection = KWayland::Client::ConnectionThread::fromApplication(qGuiApp); + connect(registry, &KWayland::Client::Registry::plasmaShellAnnounced, this, [registry, this](quint32 name, quint32 version) { + if (!m_plasmashell) { + m_plasmashell = registry->createPlasmaShell(name, version); + } + }); + registry->create(connection); + registry->setup(); + } } Klipper::~Klipper() @@ -384,10 +401,26 @@ void Klipper::saveSettings() const void Klipper::showPopupMenu(QMenu *menu) { Q_ASSERT(menu != nullptr); - + if (m_plasmashell) { + menu->hide(); + menu->windowHandle()->installEventFilter(this); + } menu->popup(QCursor::pos()); } +bool Klipper::eventFilter(QObject *filtered, QEvent *event) +{ + const bool ret = QObject::eventFilter(filtered, event); + auto menuWindow = qobject_cast(filtered); + if (menuWindow && event->type() == QEvent::Expose && menuWindow->isVisible()) { + auto surface = KWayland::Client::Surface::fromWindow(menuWindow); + auto plasmaSurface = m_plasmashell->createSurface(surface, menuWindow); + plasmaSurface->openUnderCursor(); + menuWindow->removeEventFilter(this); + } + return ret; +} + bool Klipper::loadHistory() { static const char failed_load_warning[] = "Failed to load history resource. Clipboard history cannot be read."; diff --git a/klipper/klipper.h b/klipper/klipper.h index 81ffa13fb..306c55538 100644 --- a/klipper/klipper.h +++ b/klipper/klipper.h @@ -31,6 +31,14 @@ class HistoryItem; class KNotification; class KSystemClipboard; +namespace KWayland +{ +namespace Client +{ +class PlasmaShell; +} +} + enum class KlipperMode { Standalone, DataEngine, @@ -65,6 +73,8 @@ public: Klipper(QObject *parent, const KSharedConfigPtr &config, KlipperMode mode = KlipperMode::Standalone); ~Klipper() override; + bool eventFilter(QObject *object, QEvent *event) override; + /** * Get clipboard history (the "document") */ @@ -223,4 +233,5 @@ private: KlipperMode m_mode; QTimer *m_saveFileTimer = nullptr; QPointer m_notification; + KWayland::Client::PlasmaShell *m_plasmashell; };