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