File indexing completed on 2024-11-10 04:56:51
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2008 Martin Gräßlin <mgraesslin@kde.org> 0006 SPDX-FileCopyrightText: 2009 Lucas Murray <lmurray@undefinedfire.com> 0007 SPDX-FileCopyrightText: 2020 Cyril Rossi <cyril.rossi@enioka.com> 0008 0009 SPDX-License-Identifier: GPL-2.0-or-later 0010 */ 0011 0012 #include "main.h" 0013 #include <kwin_effects_interface.h> 0014 0015 #include <KConfigGroup> 0016 #include <KLocalizedString> 0017 #include <KPackage/Package> 0018 #include <KPackage/PackageLoader> 0019 #include <KPluginFactory> 0020 #include <QDBusConnection> 0021 #include <QVBoxLayout> 0022 0023 #include "kwinscreenedgeconfigform.h" 0024 #include "kwinscreenedgedata.h" 0025 #include "kwinscreenedgeeffectsettings.h" 0026 #include "kwinscreenedgescriptsettings.h" 0027 #include "kwinscreenedgesettings.h" 0028 0029 K_PLUGIN_FACTORY_WITH_JSON(KWinScreenEdgesConfigFactory, "kcm_kwinscreenedges.json", registerPlugin<KWin::KWinScreenEdgesConfig>(); registerPlugin<KWin::KWinScreenEdgeData>();) 0030 0031 namespace KWin 0032 { 0033 0034 KWinScreenEdgesConfig::KWinScreenEdgesConfig(QObject *parent, const KPluginMetaData &data) 0035 : KCModule(parent, data) 0036 , m_form(new KWinScreenEdgesConfigForm(widget())) 0037 , m_config(KSharedConfig::openConfig("kwinrc")) 0038 , m_data(new KWinScreenEdgeData(this)) 0039 { 0040 QVBoxLayout *layout = new QVBoxLayout(widget()); 0041 layout->addWidget(m_form); 0042 0043 addConfig(m_data->settings(), m_form); 0044 0045 monitorInit(); 0046 0047 connect(this, &KWinScreenEdgesConfig::defaultsIndicatorsVisibleChanged, m_form, [this]() { 0048 m_form->setDefaultsIndicatorsVisible(defaultsIndicatorsVisible()); 0049 }); 0050 connect(m_form, &KWinScreenEdgesConfigForm::saveNeededChanged, this, &KWinScreenEdgesConfig::unmanagedWidgetChangeState); 0051 connect(m_form, &KWinScreenEdgesConfigForm::defaultChanged, this, &KWinScreenEdgesConfig::unmanagedWidgetDefaultState); 0052 } 0053 0054 KWinScreenEdgesConfig::~KWinScreenEdgesConfig() 0055 { 0056 } 0057 0058 void KWinScreenEdgesConfig::load() 0059 { 0060 KCModule::load(); 0061 m_data->settings()->load(); 0062 for (KWinScreenEdgeScriptSettings *setting : std::as_const(m_scriptSettings)) { 0063 setting->load(); 0064 } 0065 for (KWinScreenEdgeEffectSettings *setting : std::as_const(m_effectSettings)) { 0066 setting->load(); 0067 } 0068 0069 monitorLoadSettings(); 0070 monitorLoadDefaultSettings(); 0071 m_form->setRemainActiveOnFullscreen(m_data->settings()->remainActiveOnFullscreen()); 0072 m_form->setElectricBorderCornerRatio(m_data->settings()->electricBorderCornerRatio()); 0073 m_form->setDefaultElectricBorderCornerRatio(m_data->settings()->defaultElectricBorderCornerRatioValue()); 0074 m_form->reload(); 0075 } 0076 0077 void KWinScreenEdgesConfig::save() 0078 { 0079 monitorSaveSettings(); 0080 m_data->settings()->setRemainActiveOnFullscreen(m_form->remainActiveOnFullscreen()); 0081 m_data->settings()->setElectricBorderCornerRatio(m_form->electricBorderCornerRatio()); 0082 m_data->settings()->save(); 0083 for (KWinScreenEdgeScriptSettings *setting : std::as_const(m_scriptSettings)) { 0084 setting->save(); 0085 } 0086 for (KWinScreenEdgeEffectSettings *setting : std::as_const(m_effectSettings)) { 0087 setting->save(); 0088 } 0089 0090 // Reload saved settings to ScreenEdge UI 0091 monitorLoadSettings(); 0092 m_form->setElectricBorderCornerRatio(m_data->settings()->electricBorderCornerRatio()); 0093 m_form->setRemainActiveOnFullscreen(m_data->settings()->remainActiveOnFullscreen()); 0094 m_form->reload(); 0095 0096 // Reload KWin. 0097 QDBusMessage message = QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reloadConfig"); 0098 QDBusConnection::sessionBus().send(message); 0099 // and reconfigure the effects 0100 OrgKdeKwinEffectsInterface interface(QStringLiteral("org.kde.KWin"), 0101 QStringLiteral("/Effects"), 0102 QDBusConnection::sessionBus()); 0103 0104 interface.reconfigureEffect(QStringLiteral("overview")); 0105 interface.reconfigureEffect(QStringLiteral("windowview")); 0106 0107 for (const auto &effectId : std::as_const(m_effects)) { 0108 interface.reconfigureEffect(effectId); 0109 } 0110 0111 KCModule::save(); 0112 } 0113 0114 void KWinScreenEdgesConfig::defaults() 0115 { 0116 m_form->setDefaults(); 0117 0118 KCModule::defaults(); 0119 } 0120 0121 //----------------------------------------------------------------------------- 0122 // Monitor 0123 0124 static QList<KPluginMetaData> listBuiltinEffects() 0125 { 0126 const QString rootDirectory = QStandardPaths::locate(QStandardPaths::GenericDataLocation, 0127 QStringLiteral("kwin/builtin-effects"), 0128 QStandardPaths::LocateDirectory); 0129 0130 QList<KPluginMetaData> ret; 0131 0132 const QStringList nameFilters{QStringLiteral("*.json")}; 0133 QDirIterator it(rootDirectory, nameFilters, QDir::Files); 0134 while (it.hasNext()) { 0135 it.next(); 0136 if (const KPluginMetaData metaData = KPluginMetaData::fromJsonFile(it.filePath()); metaData.isValid()) { 0137 ret.append(metaData); 0138 } 0139 } 0140 0141 return ret; 0142 } 0143 0144 static QList<KPluginMetaData> listScriptedEffects() 0145 { 0146 return KPackage::PackageLoader::self()->listPackages(QStringLiteral("KWin/Effect"), QStringLiteral("kwin/effects/")); 0147 } 0148 0149 void KWinScreenEdgesConfig::monitorInit() 0150 { 0151 m_form->monitorAddItem(i18n("No Action")); 0152 m_form->monitorAddItem(i18n("Peek at Desktop")); 0153 m_form->monitorAddItem(i18n("Lock Screen")); 0154 m_form->monitorAddItem(i18n("Show KRunner")); 0155 m_form->monitorAddItem(i18n("Activity Manager")); 0156 m_form->monitorAddItem(i18n("Application Launcher")); 0157 0158 // TODO: Find a better way to get the display name of the present windows, 0159 // Maybe install metadata.json files? 0160 const QString presentWindowsName = i18n("Present Windows"); 0161 m_form->monitorAddItem(i18n("%1 - All Desktops", presentWindowsName)); 0162 m_form->monitorAddItem(i18n("%1 - Current Desktop", presentWindowsName)); 0163 m_form->monitorAddItem(i18n("%1 - Current Application", presentWindowsName)); 0164 0165 m_form->monitorAddItem(i18n("Overview")); 0166 0167 m_form->monitorAddItem(i18n("Toggle window switching")); 0168 m_form->monitorAddItem(i18n("Toggle alternative window switching")); 0169 0170 KConfigGroup config(m_config, QStringLiteral("Plugins")); 0171 const auto effects = listBuiltinEffects() << listScriptedEffects(); 0172 0173 for (const KPluginMetaData &effect : effects) { 0174 if (!effect.value(QStringLiteral("X-KWin-Border-Activate"), false)) { 0175 continue; 0176 } 0177 0178 if (!config.readEntry(effect.pluginId() + QStringLiteral("Enabled"), effect.isEnabledByDefault())) { 0179 continue; 0180 } 0181 m_effects << effect.pluginId(); 0182 m_form->monitorAddItem(effect.name()); 0183 m_effectSettings[effect.pluginId()] = new KWinScreenEdgeEffectSettings(effect.pluginId(), this); 0184 } 0185 0186 const QString scriptFolder = QStringLiteral("kwin/scripts/"); 0187 const auto scripts = KPackage::PackageLoader::self()->listPackages(QStringLiteral("KWin/Script"), scriptFolder); 0188 0189 for (const KPluginMetaData &script : scripts) { 0190 if (script.value(QStringLiteral("X-KWin-Border-Activate"), false) != true) { 0191 continue; 0192 } 0193 0194 if (!config.readEntry(script.pluginId() + QStringLiteral("Enabled"), script.isEnabledByDefault())) { 0195 continue; 0196 } 0197 m_scripts << script.pluginId(); 0198 m_form->monitorAddItem(script.name()); 0199 m_scriptSettings[script.pluginId()] = new KWinScreenEdgeScriptSettings(script.pluginId(), this); 0200 } 0201 0202 monitorShowEvent(); 0203 } 0204 0205 void KWinScreenEdgesConfig::monitorLoadSettings() 0206 { 0207 // Load ElectricBorderActions 0208 m_form->monitorChangeEdge(ElectricTop, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->top())); 0209 m_form->monitorChangeEdge(ElectricTopRight, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->topRight())); 0210 m_form->monitorChangeEdge(ElectricRight, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->right())); 0211 m_form->monitorChangeEdge(ElectricBottomRight, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->bottomRight())); 0212 m_form->monitorChangeEdge(ElectricBottom, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->bottom())); 0213 m_form->monitorChangeEdge(ElectricBottomLeft, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->bottomLeft())); 0214 m_form->monitorChangeEdge(ElectricLeft, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->left())); 0215 m_form->monitorChangeEdge(ElectricTopLeft, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->topLeft())); 0216 0217 // Load effect-specific actions: 0218 0219 // PresentWindows BorderActivateAll 0220 m_form->monitorChangeEdge(m_data->settings()->borderActivateAll(), PresentWindowsAll); 0221 0222 // PresentWindows BorderActivate 0223 m_form->monitorChangeEdge(m_data->settings()->borderActivatePresentWindows(), PresentWindowsCurrent); 0224 0225 // PresentWindows BorderActivateClass 0226 m_form->monitorChangeEdge(m_data->settings()->borderActivateClass(), PresentWindowsClass); 0227 0228 // Overview 0229 m_form->monitorChangeEdge(m_data->settings()->borderActivateOverview(), Overview); 0230 0231 // TabBox 0232 m_form->monitorChangeEdge(m_data->settings()->borderActivateTabBox(), TabBox); 0233 // Alternative TabBox 0234 m_form->monitorChangeEdge(m_data->settings()->borderAlternativeActivate(), TabBoxAlternative); 0235 0236 // Dinamically loaded effects 0237 int lastIndex = EffectCount; 0238 for (int i = 0; i < m_effects.size(); i++) { 0239 m_form->monitorChangeEdge(m_effectSettings[m_effects[i]]->borderActivate(), lastIndex); 0240 ++lastIndex; 0241 } 0242 0243 // Scripts 0244 for (int i = 0; i < m_scripts.size(); i++) { 0245 m_form->monitorChangeEdge(m_scriptSettings[m_scripts[i]]->borderActivate(), lastIndex); 0246 ++lastIndex; 0247 } 0248 } 0249 0250 void KWinScreenEdgesConfig::monitorLoadDefaultSettings() 0251 { 0252 // Load ElectricBorderActions 0253 m_form->monitorChangeDefaultEdge(ElectricTop, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->defaultTopValue())); 0254 m_form->monitorChangeDefaultEdge(ElectricTopRight, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->defaultTopRightValue())); 0255 m_form->monitorChangeDefaultEdge(ElectricRight, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->defaultRightValue())); 0256 m_form->monitorChangeDefaultEdge(ElectricBottomRight, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->defaultBottomRightValue())); 0257 m_form->monitorChangeDefaultEdge(ElectricBottom, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->defaultBottomValue())); 0258 m_form->monitorChangeDefaultEdge(ElectricBottomLeft, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->defaultBottomLeftValue())); 0259 m_form->monitorChangeDefaultEdge(ElectricLeft, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->defaultLeftValue())); 0260 m_form->monitorChangeDefaultEdge(ElectricTopLeft, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->defaultTopLeftValue())); 0261 0262 // Load effect-specific actions: 0263 0264 // PresentWindows BorderActivateAll 0265 m_form->monitorChangeDefaultEdge(m_data->settings()->defaultBorderActivateAllValue(), PresentWindowsAll); 0266 0267 // PresentWindows BorderActivate 0268 m_form->monitorChangeDefaultEdge(m_data->settings()->defaultBorderActivatePresentWindowsValue(), PresentWindowsCurrent); 0269 0270 // PresentWindows BorderActivateClass 0271 m_form->monitorChangeDefaultEdge(m_data->settings()->defaultBorderActivateClassValue(), PresentWindowsClass); 0272 0273 // Overview 0274 m_form->monitorChangeDefaultEdge(m_data->settings()->defaultBorderActivateOverviewValue(), Overview); 0275 0276 // TabBox 0277 m_form->monitorChangeDefaultEdge(m_data->settings()->defaultBorderActivateTabBoxValue(), TabBox); 0278 // Alternative TabBox 0279 m_form->monitorChangeDefaultEdge(m_data->settings()->defaultBorderAlternativeActivateValue(), TabBoxAlternative); 0280 } 0281 0282 void KWinScreenEdgesConfig::monitorSaveSettings() 0283 { 0284 // Save ElectricBorderActions 0285 m_data->settings()->setTop(KWinScreenEdgesConfig::electricBorderActionToString(m_form->selectedEdgeItem(ElectricTop))); 0286 m_data->settings()->setTopRight(KWinScreenEdgesConfig::electricBorderActionToString(m_form->selectedEdgeItem(ElectricTopRight))); 0287 m_data->settings()->setRight(KWinScreenEdgesConfig::electricBorderActionToString(m_form->selectedEdgeItem(ElectricRight))); 0288 m_data->settings()->setBottomRight(KWinScreenEdgesConfig::electricBorderActionToString(m_form->selectedEdgeItem(ElectricBottomRight))); 0289 m_data->settings()->setBottom(KWinScreenEdgesConfig::electricBorderActionToString(m_form->selectedEdgeItem(ElectricBottom))); 0290 m_data->settings()->setBottomLeft(KWinScreenEdgesConfig::electricBorderActionToString(m_form->selectedEdgeItem(ElectricBottomLeft))); 0291 m_data->settings()->setLeft(KWinScreenEdgesConfig::electricBorderActionToString(m_form->selectedEdgeItem(ElectricLeft))); 0292 m_data->settings()->setTopLeft(KWinScreenEdgesConfig::electricBorderActionToString(m_form->selectedEdgeItem(ElectricTopLeft))); 0293 0294 // Save effect-specific actions: 0295 0296 // Present Windows 0297 m_data->settings()->setBorderActivateAll(m_form->monitorCheckEffectHasEdge(PresentWindowsAll)); 0298 m_data->settings()->setBorderActivatePresentWindows(m_form->monitorCheckEffectHasEdge(PresentWindowsCurrent)); 0299 m_data->settings()->setBorderActivateClass(m_form->monitorCheckEffectHasEdge(PresentWindowsClass)); 0300 0301 // Overview 0302 m_data->settings()->setBorderActivateOverview(m_form->monitorCheckEffectHasEdge(Overview)); 0303 0304 // TabBox 0305 m_data->settings()->setBorderActivateTabBox(m_form->monitorCheckEffectHasEdge(TabBox)); 0306 m_data->settings()->setBorderAlternativeActivate(m_form->monitorCheckEffectHasEdge(TabBoxAlternative)); 0307 0308 // Dinamically loaded effects 0309 int lastIndex = EffectCount; 0310 for (int i = 0; i < m_effects.size(); i++) { 0311 m_effectSettings[m_effects[i]]->setBorderActivate(m_form->monitorCheckEffectHasEdge(lastIndex)); 0312 ++lastIndex; 0313 } 0314 0315 // Scripts 0316 for (int i = 0; i < m_scripts.size(); i++) { 0317 m_scriptSettings[m_scripts[i]]->setBorderActivate(m_form->monitorCheckEffectHasEdge(lastIndex)); 0318 ++lastIndex; 0319 } 0320 } 0321 0322 void KWinScreenEdgesConfig::monitorShowEvent() 0323 { 0324 // Check if they are enabled 0325 KConfigGroup config(m_config, QStringLiteral("Plugins")); 0326 0327 // Present Windows 0328 bool enabled = config.readEntry("windowviewEnabled", true); 0329 m_form->monitorItemSetEnabled(PresentWindowsCurrent, enabled); 0330 m_form->monitorItemSetEnabled(PresentWindowsAll, enabled); 0331 0332 // Overview 0333 m_form->monitorItemSetEnabled(Overview, config.readEntry("overviewEnabled", true)); 0334 0335 // tabbox, depends on reasonable focus policy. 0336 KConfigGroup config2(m_config, QStringLiteral("Windows")); 0337 QString focusPolicy = config2.readEntry("FocusPolicy", QString()); 0338 bool reasonable = focusPolicy != "FocusStrictlyUnderMouse" && focusPolicy != "FocusUnderMouse"; 0339 m_form->monitorItemSetEnabled(TabBox, reasonable); 0340 m_form->monitorItemSetEnabled(TabBoxAlternative, reasonable); 0341 0342 // Disable Edge if ElectricBorders group entries are immutable 0343 m_form->monitorEnableEdge(ElectricTop, !m_data->settings()->isTopImmutable()); 0344 m_form->monitorEnableEdge(ElectricTopRight, !m_data->settings()->isTopRightImmutable()); 0345 m_form->monitorEnableEdge(ElectricRight, !m_data->settings()->isRightImmutable()); 0346 m_form->monitorEnableEdge(ElectricBottomRight, !m_data->settings()->isBottomRightImmutable()); 0347 m_form->monitorEnableEdge(ElectricBottom, !m_data->settings()->isBottomImmutable()); 0348 m_form->monitorEnableEdge(ElectricBottomLeft, !m_data->settings()->isBottomLeftImmutable()); 0349 m_form->monitorEnableEdge(ElectricLeft, !m_data->settings()->isLeftImmutable()); 0350 m_form->monitorEnableEdge(ElectricTopLeft, !m_data->settings()->isTopLeftImmutable()); 0351 0352 // Disable ElectricBorderCornerRatio if entry is immutable 0353 m_form->setElectricBorderCornerRatioEnabled(!m_data->settings()->isElectricBorderCornerRatioImmutable()); 0354 } 0355 0356 ElectricBorderAction KWinScreenEdgesConfig::electricBorderActionFromString(const QString &string) 0357 { 0358 QString lowerName = string.toLower(); 0359 if (lowerName == QStringLiteral("showdesktop")) { 0360 return ElectricActionShowDesktop; 0361 } 0362 if (lowerName == QStringLiteral("lockscreen")) { 0363 return ElectricActionLockScreen; 0364 } 0365 if (lowerName == QStringLiteral("krunner")) { 0366 return ElectricActionKRunner; 0367 } 0368 if (lowerName == QStringLiteral("activitymanager")) { 0369 return ElectricActionActivityManager; 0370 } 0371 if (lowerName == QStringLiteral("applicationlauncher")) { 0372 return ElectricActionApplicationLauncher; 0373 } 0374 return ElectricActionNone; 0375 } 0376 0377 QString KWinScreenEdgesConfig::electricBorderActionToString(int action) 0378 { 0379 switch (action) { 0380 case 1: 0381 return QStringLiteral("ShowDesktop"); 0382 case 2: 0383 return QStringLiteral("LockScreen"); 0384 case 3: 0385 return QStringLiteral("KRunner"); 0386 case 4: 0387 return QStringLiteral("ActivityManager"); 0388 case 5: 0389 return QStringLiteral("ApplicationLauncher"); 0390 default: 0391 return QStringLiteral("None"); 0392 } 0393 } 0394 0395 } // namespace 0396 0397 #include "main.moc" 0398 0399 #include "moc_main.cpp"