diff --git a/applets/colorpicker/CMakeLists.txt b/applets/colorpicker/CMakeLists.txt index 80b9d61eb..67dc74926 100644 --- a/applets/colorpicker/CMakeLists.txt +++ b/applets/colorpicker/CMakeLists.txt @@ -1,14 +1,14 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH}) plasma_install_package(package org.kde.plasma.colorpicker) set(colorpickerplugin_SRCS plugin/grabwidget.cpp plugin/colorpickerplugin.cpp ) install(FILES plugin/qmldir DESTINATION ${QML_INSTALL_DIR}/org/kde/plasma/private/colorpicker) add_library(colorpickerplugin SHARED ${colorpickerplugin_SRCS}) -target_link_libraries(colorpickerplugin Qt5::Gui Qt5::Qml Qt5::Widgets) +target_link_libraries(colorpickerplugin Qt5::DBus Qt5::Gui Qt5::Qml Qt5::Widgets KF5::WindowSystem) install(TARGETS colorpickerplugin DESTINATION ${QML_INSTALL_DIR}/org/kde/plasma/private/colorpicker) diff --git a/applets/colorpicker/plugin/grabwidget.cpp b/applets/colorpicker/plugin/grabwidget.cpp index 719a1ef6b..e53fdecf7 100644 --- a/applets/colorpicker/plugin/grabwidget.cpp +++ b/applets/colorpicker/plugin/grabwidget.cpp @@ -1,83 +1,175 @@ /* * Copyright 2015 Kai Uwe Broulik * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see */ #include "grabwidget.h" #include +#include +#include +#include +#include +#include +#include #include #include #include #include #include #include -GrabWidget::GrabWidget(QObject *parent) +#include + +Q_DECLARE_METATYPE(QColor) + +QDBusArgument &operator<< (QDBusArgument &argument, const QColor &color) +{ + argument.beginStructure(); + argument << color.rgba(); + argument.endStructure(); + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, QColor &color) +{ + argument.beginStructure(); + QRgb rgba; + argument >> rgba; + argument.endStructure(); + color = QColor::fromRgba(rgba); + return argument; +} + +Grabber::Grabber(QObject *parent) : QObject(parent) - , m_grabWidget(new QWidget(nullptr, Qt::BypassWindowManagerHint)) { - m_grabWidget->move(-5000, -5000); } -GrabWidget::~GrabWidget() +Grabber::~Grabber() = default; + +void Grabber::setColor(const QColor &color) { - delete m_grabWidget; + if (m_color == color) { + return; + } + m_color = color; + emit colorChanged(); } -QColor GrabWidget::currentColor() const +X11Grabber::X11Grabber(QObject *parent) + : Grabber(parent) + , m_grabWidget(new QWidget(nullptr, Qt::BypassWindowManagerHint)) { - return m_currentColor; + m_grabWidget->move(-5000, -5000); } -void GrabWidget::pick() +X11Grabber::~X11Grabber() +{ + delete m_grabWidget; +} + +void X11Grabber::pick() { // TODO pretend the mouse went somewhere else to prevent the tooltip from spawning m_grabWidget->show(); m_grabWidget->installEventFilter(this); m_grabWidget->grabMouse(Qt::CrossCursor); } -void GrabWidget::copyToClipboard(const QString &text) -{ - QApplication::clipboard()->setText(text); -} - -bool GrabWidget::eventFilter(QObject *watched, QEvent *event) +bool X11Grabber::eventFilter(QObject *watched, QEvent *event) { if (watched == m_grabWidget && event->type() == QEvent::MouseButtonRelease) { m_grabWidget->removeEventFilter(this); m_grabWidget->hide(); m_grabWidget->releaseMouse(); QMouseEvent *me = static_cast(event); const QPoint pos = me->globalPos(); // the grabbed pixmap will contain all screens, not just the primary one // originally we traversed all screens looking for where the mouse is // but this isn't neccessarily apparently const QPixmap pixmap = qApp->primaryScreen()->grabWindow(0); const QPoint localPos = pos * qApp->devicePixelRatio(); - m_currentColor = QColor(pixmap.toImage().pixel(localPos)); - emit currentColorChanged(); + setColor(QColor(pixmap.toImage().pixel(localPos))); } return QObject::eventFilter(watched, event); } + +KWinWaylandGrabber::KWinWaylandGrabber(QObject *parent) + : Grabber(parent) +{ + qDBusRegisterMetaType(); +} + +KWinWaylandGrabber::~KWinWaylandGrabber() = default; + +void KWinWaylandGrabber::pick() +{ + QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KWin"), + QStringLiteral("/ColorPicker"), + QStringLiteral("org.kde.kwin.ColorPicker"), + QStringLiteral("pick")); + auto call = QDBusConnection::sessionBus().asyncCall(msg); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, + [this] (QDBusPendingCallWatcher *watcher) { + watcher->deleteLater(); + QDBusPendingReply reply = *watcher; + if (!reply.isError()) { + setColor(reply.value()); + } + } + ); +} + +GrabWidget::GrabWidget(QObject *parent) + : QObject(parent) +{ + if (KWindowSystem::isPlatformX11()) { + m_grabber = new X11Grabber(this); + } else if (KWindowSystem::isPlatformWayland()) { + m_grabber = new KWinWaylandGrabber(this); + } + if (m_grabber) { + connect(m_grabber, &Grabber::colorChanged, this, &GrabWidget::currentColorChanged); + } +} + +GrabWidget::~GrabWidget() = default; + +QColor GrabWidget::currentColor() const +{ + return m_grabber ? m_grabber->color() : QColor(); +} + +void GrabWidget::pick() +{ + if (m_grabber) { + m_grabber->pick(); + } +} + +void GrabWidget::copyToClipboard(const QString &text) +{ + QApplication::clipboard()->setText(text); +} diff --git a/applets/colorpicker/plugin/grabwidget.h b/applets/colorpicker/plugin/grabwidget.h index d8e46e693..3fedb2307 100644 --- a/applets/colorpicker/plugin/grabwidget.h +++ b/applets/colorpicker/plugin/grabwidget.h @@ -1,57 +1,101 @@ /* * Copyright 2015 Kai Uwe Broulik * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see */ #ifndef GRABWIDGET_H #define GRABWIDGET_H #include #include class QWidget; +class Grabber : public QObject +{ + Q_OBJECT +public: + virtual ~Grabber(); + + virtual void pick() = 0; + + QColor color() const { + return m_color; + } + +Q_SIGNALS: + void colorChanged(); + +protected: + void setColor(const QColor &color); + explicit Grabber(QObject *parent = nullptr); + +private: + QColor m_color; +}; + +class X11Grabber : public Grabber +{ + Q_OBJECT +public: + explicit X11Grabber(QObject *parent = nullptr); + virtual ~X11Grabber(); + + void pick() override; + +protected: + virtual bool eventFilter(QObject *watched, QEvent *event) override; + +private: + QWidget *m_grabWidget; +}; + +class KWinWaylandGrabber : public Grabber +{ + Q_OBJECT +public: + explicit KWinWaylandGrabber(QObject *parent = nullptr); + virtual ~KWinWaylandGrabber(); + + void pick() override; +}; + class GrabWidget : public QObject { Q_OBJECT Q_PROPERTY(QColor currentColor READ currentColor NOTIFY currentColorChanged) public: explicit GrabWidget(QObject *parent = nullptr); virtual ~GrabWidget(); QColor currentColor() const; Q_INVOKABLE void pick(); Q_INVOKABLE void copyToClipboard(const QString &text); signals: void currentColorChanged(); -protected: - virtual bool eventFilter(QObject *watched, QEvent *event) override; - private: - QWidget *m_grabWidget; - - QColor m_currentColor; + Grabber *m_grabber = nullptr; }; #endif // GRABWIDGET_H