File indexing completed on 2024-11-10 04:56:46

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2013 Antonis Tsiapaliokas <kok3rs@gmail.com>
0006     SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 
0011 #include "ui_compositing.h"
0012 #include <kwin_compositing_interface.h>
0013 
0014 #include <QAction>
0015 #include <QApplication>
0016 #include <QLayout>
0017 
0018 #include <KCModule>
0019 #include <KPluginFactory>
0020 #include <KWindowSystem>
0021 
0022 #include <algorithm>
0023 #include <functional>
0024 
0025 #include "kwincompositing_setting.h"
0026 #include "kwincompositingdata.h"
0027 
0028 static bool isRunningPlasma()
0029 {
0030     return qgetenv("XDG_CURRENT_DESKTOP") == "KDE";
0031 }
0032 
0033 class KWinCompositingKCM : public KCModule
0034 {
0035     Q_OBJECT
0036 public:
0037     explicit KWinCompositingKCM(QObject *parent, const KPluginMetaData &data);
0038 
0039 public Q_SLOTS:
0040     void load() override;
0041     void save() override;
0042     void defaults() override;
0043 
0044 private Q_SLOTS:
0045     void reenableGl();
0046 
0047 private:
0048     void init();
0049     void updateUnmanagedItemStatus();
0050     bool compositingRequired() const;
0051 
0052     Ui_CompositingForm m_form;
0053 
0054     OrgKdeKwinCompositingInterface *m_compositingInterface;
0055     KWinCompositingSetting *m_settings;
0056 };
0057 
0058 static const QList<qreal> s_animationMultipliers = {8, 4, 2, 1, 0.5, 0.25, 0.125, 0};
0059 
0060 bool KWinCompositingKCM::compositingRequired() const
0061 {
0062     return m_compositingInterface->platformRequiresCompositing();
0063 }
0064 
0065 KWinCompositingKCM::KWinCompositingKCM(QObject *parent, const KPluginMetaData &data)
0066     : KCModule(parent, data)
0067     , m_compositingInterface(new OrgKdeKwinCompositingInterface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Compositor"), QDBusConnection::sessionBus(), this))
0068     , m_settings(new KWinCompositingSetting(this))
0069 {
0070     m_form.setupUi(widget());
0071 
0072     // AnimationDurationFactor should be written to the same place as the lnf to avoid conflicts
0073     m_settings->findItem("AnimationDurationFactor")->setWriteFlags(KConfigBase::Global | KConfigBase::Notify);
0074 
0075     addConfig(m_settings, widget());
0076 
0077     m_form.glCrashedWarning->setIcon(QIcon::fromTheme(QStringLiteral("dialog-warning")));
0078     QAction *reenableGlAction = new QAction(i18n("Re-enable OpenGL detection"), this);
0079     connect(reenableGlAction, &QAction::triggered, this, &KWinCompositingKCM::reenableGl);
0080     connect(reenableGlAction, &QAction::triggered, m_form.glCrashedWarning, &KMessageWidget::animatedHide);
0081     m_form.glCrashedWarning->addAction(reenableGlAction);
0082     m_form.windowThumbnailWarning->setIcon(QIcon::fromTheme(QStringLiteral("dialog-warning")));
0083 
0084     m_form.kcfg_Enabled->setVisible(!compositingRequired());
0085     m_form.kcfg_WindowsBlockCompositing->setVisible(!compositingRequired());
0086     m_form.compositingLabel->setVisible(!compositingRequired());
0087 
0088     connect(this, &KWinCompositingKCM::defaultsIndicatorsVisibleChanged, this, &KWinCompositingKCM::updateUnmanagedItemStatus);
0089 
0090     if (KWindowSystem::isPlatformWayland()) {
0091         m_form.kcfg_HiddenPreviews->setVisible(false);
0092         m_form.label_HiddenPreviews->setVisible(false);
0093     }
0094     init();
0095 }
0096 
0097 void KWinCompositingKCM::reenableGl()
0098 {
0099     m_settings->setLastFailureTimestamp(0);
0100     m_settings->save();
0101 }
0102 
0103 void KWinCompositingKCM::init()
0104 {
0105     auto currentIndexChangedSignal = static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged);
0106 
0107     // animation speed
0108     m_form.animationDurationFactor->setMaximum(s_animationMultipliers.size() - 1);
0109     connect(m_form.animationDurationFactor, &QSlider::valueChanged, this, [this]() {
0110         updateUnmanagedItemStatus();
0111         m_settings->setAnimationDurationFactor(s_animationMultipliers[m_form.animationDurationFactor->value()]);
0112     });
0113 
0114     if (isRunningPlasma()) {
0115         m_form.animationSpeedLabel->hide();
0116         m_form.animationSpeedControls->hide();
0117     }
0118 
0119     // windowThumbnail
0120     connect(m_form.kcfg_HiddenPreviews, currentIndexChangedSignal, this, [this](int index) {
0121         if (index == 2) {
0122             m_form.windowThumbnailWarning->animatedShow();
0123         } else {
0124             m_form.windowThumbnailWarning->animatedHide();
0125         }
0126     });
0127 
0128     if (m_settings->lastFailureTimestamp() > 0) {
0129         m_form.glCrashedWarning->animatedShow();
0130     }
0131 }
0132 
0133 void KWinCompositingKCM::updateUnmanagedItemStatus()
0134 {
0135     const auto animationDuration = s_animationMultipliers[m_form.animationDurationFactor->value()];
0136 
0137     const bool inPlasma = isRunningPlasma();
0138 
0139     bool changed = false;
0140     if (!inPlasma) {
0141         changed |= (animationDuration != m_settings->animationDurationFactor());
0142     }
0143     unmanagedWidgetChangeState(changed);
0144 
0145     bool defaulted = true;
0146     if (!inPlasma) {
0147         defaulted &= animationDuration == m_settings->defaultAnimationDurationFactorValue();
0148     }
0149 
0150     unmanagedWidgetDefaultState(defaulted);
0151 }
0152 
0153 void KWinCompositingKCM::load()
0154 {
0155     KCModule::load();
0156 
0157     // unmanaged items
0158     m_settings->findItem("AnimationDurationFactor")->readConfig(m_settings->config());
0159     const double multiplier = m_settings->animationDurationFactor();
0160     auto const it = std::lower_bound(s_animationMultipliers.begin(), s_animationMultipliers.end(), multiplier, std::greater<qreal>());
0161     const int index = static_cast<int>(std::distance(s_animationMultipliers.begin(), it));
0162     m_form.animationDurationFactor->setValue(index);
0163     m_form.animationDurationFactor->setDisabled(m_settings->isAnimationDurationFactorImmutable());
0164 }
0165 
0166 void KWinCompositingKCM::defaults()
0167 {
0168     KCModule::defaults();
0169 
0170     // unmanaged widgets
0171     if (!isRunningPlasma()) {
0172         // corresponds to 1.0 seconds in s_animationMultipliers
0173         m_form.animationDurationFactor->setValue(3);
0174     }
0175 }
0176 
0177 void KWinCompositingKCM::save()
0178 {
0179     if (!isRunningPlasma()) {
0180         const auto animationDuration = s_animationMultipliers[m_form.animationDurationFactor->value()];
0181         m_settings->setAnimationDurationFactor(animationDuration);
0182     }
0183     m_settings->save();
0184 
0185     KCModule::save();
0186 
0187     // This clears up old entries that are now migrated to kdeglobals
0188     KConfig("kwinrc", KConfig::NoGlobals).group(QStringLiteral("KDE")).revertToDefault("AnimationDurationFactor");
0189 
0190     // Send signal to all kwin instances
0191     QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/Compositor"),
0192                                                       QStringLiteral("org.kde.kwin.Compositing"),
0193                                                       QStringLiteral("reinit"));
0194     QDBusConnection::sessionBus().send(message);
0195 }
0196 
0197 K_PLUGIN_FACTORY_WITH_JSON(KWinCompositingConfigFactory, "kwincompositing.json",
0198                            registerPlugin<KWinCompositingKCM>();
0199                            registerPlugin<KWinCompositingData>();)
0200 
0201 #include "main.moc"