File indexing completed on 2024-11-10 04:56:58
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #include "colorpicker.h" 0010 #include "core/rendertarget.h" 0011 #include "core/renderviewport.h" 0012 #include "effect/effecthandler.h" 0013 #include "opengl/glutils.h" 0014 #include "opengl/glutils_funcs.h" 0015 #include <KLocalizedString> 0016 #include <QDBusConnection> 0017 #include <QDBusMetaType> 0018 0019 Q_DECLARE_METATYPE(QColor) 0020 0021 QDBusArgument &operator<<(QDBusArgument &argument, const QColor &color) 0022 { 0023 argument.beginStructure(); 0024 argument << color.rgba(); 0025 argument.endStructure(); 0026 return argument; 0027 } 0028 0029 const QDBusArgument &operator>>(const QDBusArgument &argument, QColor &color) 0030 { 0031 argument.beginStructure(); 0032 QRgb rgba; 0033 argument >> rgba; 0034 argument.endStructure(); 0035 color = QColor::fromRgba(rgba); 0036 return argument; 0037 } 0038 0039 namespace KWin 0040 { 0041 0042 bool ColorPickerEffect::supported() 0043 { 0044 return effects->isOpenGLCompositing(); 0045 } 0046 0047 ColorPickerEffect::ColorPickerEffect() 0048 : m_scheduledPosition(QPoint(-1, -1)) 0049 { 0050 qDBusRegisterMetaType<QColor>(); 0051 QDBusConnection::sessionBus().registerObject(QStringLiteral("/ColorPicker"), this, QDBusConnection::ExportScriptableContents); 0052 } 0053 0054 ColorPickerEffect::~ColorPickerEffect() = default; 0055 0056 void ColorPickerEffect::paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion ®ion, Output *screen) 0057 { 0058 effects->paintScreen(renderTarget, viewport, mask, region, screen); 0059 0060 const QRectF geo = viewport.renderRect(); 0061 if (m_scheduledPosition != QPoint(-1, -1) && exclusiveContains(geo, m_scheduledPosition)) { 0062 std::array<float, 4> data; 0063 constexpr GLsizei PIXEL_SIZE = 1; 0064 const QPoint texturePosition = viewport.mapToRenderTarget(m_scheduledPosition).toPoint(); 0065 0066 glReadPixels(texturePosition.x(), renderTarget.size().height() - texturePosition.y() - PIXEL_SIZE, PIXEL_SIZE, PIXEL_SIZE, GL_RGBA, GL_FLOAT, data.data()); 0067 QVector3D sRGB = 255 * renderTarget.colorDescription().mapTo(QVector3D(data[0], data[1], data[2]), ColorDescription::sRGB); 0068 QDBusConnection::sessionBus().send(m_replyMessage.createReply(QColor(sRGB.x(), sRGB.y(), sRGB.z()))); 0069 m_picking = false; 0070 m_scheduledPosition = QPoint(-1, -1); 0071 } 0072 } 0073 0074 QColor ColorPickerEffect::pick() 0075 { 0076 if (!calledFromDBus()) { 0077 return QColor(); 0078 } 0079 if (m_picking) { 0080 sendErrorReply(QDBusError::Failed, "Color picking is already in progress"); 0081 return QColor(); 0082 } 0083 m_picking = true; 0084 m_replyMessage = message(); 0085 setDelayedReply(true); 0086 showInfoMessage(); 0087 effects->startInteractivePositionSelection( 0088 [this](const QPointF &p) { 0089 hideInfoMessage(); 0090 if (p == QPointF(-1, -1)) { 0091 // error condition 0092 QDBusConnection::sessionBus().send(m_replyMessage.createErrorReply(QStringLiteral("org.kde.kwin.ColorPicker.Error.Cancelled"), "Color picking got cancelled")); 0093 m_picking = false; 0094 } else { 0095 m_scheduledPosition = p; 0096 effects->addRepaintFull(); 0097 } 0098 }); 0099 return QColor(); 0100 } 0101 0102 void ColorPickerEffect::showInfoMessage() 0103 { 0104 effects->showOnScreenMessage(i18n("Select a position for color picking with left click or enter.\nEscape or right click to cancel."), QStringLiteral("color-picker")); 0105 } 0106 0107 void ColorPickerEffect::hideInfoMessage() 0108 { 0109 effects->hideOnScreenMessage(); 0110 } 0111 0112 bool ColorPickerEffect::isActive() const 0113 { 0114 return m_picking && ((m_scheduledPosition != QPoint(-1, -1))) && !effects->isScreenLocked(); 0115 } 0116 0117 } // namespace 0118 0119 #include "moc_colorpicker.cpp"