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 "touch.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 <QDBusMessage>
0022 #include <QVBoxLayout>
0023 
0024 #include "kwintouchscreendata.h"
0025 #include "kwintouchscreenedgeconfigform.h"
0026 #include "kwintouchscreenedgeeffectsettings.h"
0027 #include "kwintouchscreenscriptsettings.h"
0028 #include "kwintouchscreensettings.h"
0029 
0030 K_PLUGIN_FACTORY_WITH_JSON(KWinScreenEdgesConfigFactory, "kcm_kwintouchscreen.json", registerPlugin<KWin::KWinScreenEdgesConfig>(); registerPlugin<KWin::KWinTouchScreenData>();)
0031 
0032 namespace KWin
0033 {
0034 
0035 KWinScreenEdgesConfig::KWinScreenEdgesConfig(QObject *parent, const KPluginMetaData &data)
0036     : KCModule(parent, data)
0037     , m_form(new KWinTouchScreenEdgeConfigForm(widget()))
0038     , m_config(KSharedConfig::openConfig("kwinrc"))
0039     , m_data(new KWinTouchScreenData(this))
0040 {
0041     QVBoxLayout *layout = new QVBoxLayout(widget());
0042     layout->addWidget(m_form);
0043 
0044     monitorInit();
0045 
0046     connect(m_form, &KWinTouchScreenEdgeConfigForm::saveNeededChanged, this, &KWinScreenEdgesConfig::unmanagedWidgetChangeState);
0047     connect(m_form, &KWinTouchScreenEdgeConfigForm::defaultChanged, this, &KWinScreenEdgesConfig::unmanagedWidgetDefaultState);
0048 }
0049 
0050 KWinScreenEdgesConfig::~KWinScreenEdgesConfig()
0051 {
0052 }
0053 
0054 void KWinScreenEdgesConfig::load()
0055 {
0056     KCModule::load();
0057     m_data->settings()->load();
0058     for (KWinTouchScreenScriptSettings *setting : std::as_const(m_scriptSettings)) {
0059         setting->load();
0060     }
0061     for (KWinTouchScreenEdgeEffectSettings *setting : std::as_const(m_effectSettings)) {
0062         setting->load();
0063     }
0064 
0065     monitorLoadSettings();
0066     monitorLoadDefaultSettings();
0067     m_form->reload();
0068 }
0069 
0070 void KWinScreenEdgesConfig::save()
0071 {
0072     monitorSaveSettings();
0073     m_data->settings()->save();
0074     for (KWinTouchScreenScriptSettings *setting : std::as_const(m_scriptSettings)) {
0075         setting->save();
0076     }
0077     for (KWinTouchScreenEdgeEffectSettings *setting : std::as_const(m_effectSettings)) {
0078         setting->save();
0079     }
0080 
0081     // Reload saved settings to ScreenEdge UI
0082     monitorLoadSettings();
0083     m_form->reload();
0084 
0085     // Reload KWin.
0086     QDBusMessage message = QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reloadConfig");
0087     QDBusConnection::sessionBus().send(message);
0088     // and reconfigure the effects
0089     OrgKdeKwinEffectsInterface interface(QStringLiteral("org.kde.KWin"),
0090                                          QStringLiteral("/Effects"),
0091                                          QDBusConnection::sessionBus());
0092     interface.reconfigureEffect(QStringLiteral("windowview"));
0093     interface.reconfigureEffect(QStringLiteral("overview"));
0094     for (const auto &effectId : std::as_const(m_effects)) {
0095         interface.reconfigureEffect(effectId);
0096     }
0097 
0098     KCModule::save();
0099 }
0100 
0101 void KWinScreenEdgesConfig::defaults()
0102 {
0103     m_form->setDefaults();
0104 
0105     KCModule::defaults();
0106 }
0107 
0108 //-----------------------------------------------------------------------------
0109 // Monitor
0110 
0111 void KWinScreenEdgesConfig::monitorInit()
0112 {
0113     m_form->monitorHideEdge(ElectricTopLeft, true);
0114     m_form->monitorHideEdge(ElectricTopRight, true);
0115     m_form->monitorHideEdge(ElectricBottomRight, true);
0116     m_form->monitorHideEdge(ElectricBottomLeft, true);
0117 
0118     m_form->monitorAddItem(i18n("No Action"));
0119     m_form->monitorAddItem(i18n("Peek at Desktop"));
0120     m_form->monitorAddItem(i18n("Lock Screen"));
0121     m_form->monitorAddItem(i18n("Show KRunner"));
0122     m_form->monitorAddItem(i18n("Activity Manager"));
0123     m_form->monitorAddItem(i18n("Application Launcher"));
0124 
0125     // TODO: Find a better way to get the display name of the present windows,
0126     // Maybe install metadata.json files?
0127     const QString presentWindowsName = i18n("Present Windows");
0128     m_form->monitorAddItem(i18n("%1 - All Desktops", presentWindowsName));
0129     m_form->monitorAddItem(i18n("%1 - Current Desktop", presentWindowsName));
0130     m_form->monitorAddItem(i18n("%1 - Current Application", presentWindowsName));
0131 
0132     m_form->monitorAddItem(i18n("Overview"));
0133 
0134     m_form->monitorAddItem(i18n("Toggle window switching"));
0135     m_form->monitorAddItem(i18n("Toggle alternative window switching"));
0136 
0137     KConfigGroup config(m_config, QStringLiteral("Plugins"));
0138     const auto effects = KPackage::PackageLoader::self()->listPackages(QStringLiteral("KWin/Script"), QStringLiteral("kwin/builtin-effects/")) << KPackage::PackageLoader::self()->listPackages(QStringLiteral("KWin/Script"), QStringLiteral("kwin/effects/"));
0139 
0140     for (const KPluginMetaData &effect : effects) {
0141         if (!effect.value(QStringLiteral("X-KWin-Border-Activate"), false)) {
0142             continue;
0143         }
0144 
0145         if (!config.readEntry(effect.pluginId() + QStringLiteral("Enabled"), effect.isEnabledByDefault())) {
0146             continue;
0147         }
0148         m_effects << effect.pluginId();
0149         m_form->monitorAddItem(effect.name());
0150         m_effectSettings[effect.pluginId()] = new KWinTouchScreenEdgeEffectSettings(effect.pluginId(), this);
0151     }
0152 
0153     const QString scriptFolder = QStringLiteral("kwin/scripts/");
0154     const auto scripts = KPackage::PackageLoader::self()->listPackages(QStringLiteral("KWin/Script"), scriptFolder);
0155 
0156     for (const KPluginMetaData &script : scripts) {
0157         if (script.value(QStringLiteral("X-KWin-Border-Activate"), false) != true) {
0158             continue;
0159         }
0160 
0161         if (!config.readEntry(script.pluginId() + QStringLiteral("Enabled"), script.isEnabledByDefault())) {
0162             continue;
0163         }
0164         m_scripts << script.pluginId();
0165         m_form->monitorAddItem(script.name());
0166         m_scriptSettings[script.pluginId()] = new KWinTouchScreenScriptSettings(script.pluginId(), this);
0167     }
0168 
0169     monitorShowEvent();
0170 }
0171 
0172 void KWinScreenEdgesConfig::monitorLoadSettings()
0173 {
0174     // Load ElectricBorderActions
0175     m_form->monitorChangeEdge(ElectricTop, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->top()));
0176     m_form->monitorChangeEdge(ElectricRight, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->right()));
0177     m_form->monitorChangeEdge(ElectricBottom, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->bottom()));
0178     m_form->monitorChangeEdge(ElectricLeft, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->left()));
0179 
0180     // Load effect-specific actions:
0181 
0182     // Present Windows BorderActivateAll
0183     m_form->monitorChangeEdge(m_data->settings()->touchBorderActivateAll(), PresentWindowsAll);
0184     // PresentWindows BorderActivate
0185     m_form->monitorChangeEdge(m_data->settings()->touchBorderActivatePresentWindows(), PresentWindowsCurrent);
0186     // PresentWindows BorderActivateClass
0187     m_form->monitorChangeEdge(m_data->settings()->touchBorderActivateClass(), PresentWindowsClass);
0188 
0189     // Overview
0190     m_form->monitorChangeEdge(m_data->settings()->touchBorderActivateOverview(), Overview);
0191 
0192     // TabBox BorderActivate
0193     m_form->monitorChangeEdge(m_data->settings()->touchBorderActivateTabBox(), TabBox);
0194     // Alternative TabBox
0195     m_form->monitorChangeEdge(m_data->settings()->touchBorderAlternativeActivate(), TabBoxAlternative);
0196 
0197     // Dinamically loaded effects
0198     int lastIndex = EffectCount;
0199     for (int i = 0; i < m_effects.size(); i++) {
0200         m_form->monitorChangeEdge(m_effectSettings[m_effects[i]]->touchBorderActivate(), lastIndex);
0201         ++lastIndex;
0202     }
0203 
0204     // Scripts
0205     for (int i = 0; i < m_scripts.size(); i++) {
0206         m_form->monitorChangeEdge(m_scriptSettings[m_scripts[i]]->touchBorderActivate(), lastIndex);
0207         ++lastIndex;
0208     }
0209 }
0210 
0211 void KWinScreenEdgesConfig::monitorLoadDefaultSettings()
0212 {
0213     m_form->monitorChangeDefaultEdge(ElectricTop, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->defaultTopValue()));
0214     m_form->monitorChangeDefaultEdge(ElectricRight, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->defaultRightValue()));
0215     m_form->monitorChangeDefaultEdge(ElectricBottom, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->defaultBottomValue()));
0216     m_form->monitorChangeDefaultEdge(ElectricLeft, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->defaultLeftValue()));
0217 
0218     // Present Windows BorderActivateAll
0219     m_form->monitorChangeDefaultEdge(m_data->settings()->defaultTouchBorderActivateAllValue(), PresentWindowsAll);
0220     // PresentWindows BorderActivate
0221     m_form->monitorChangeDefaultEdge(m_data->settings()->defaultTouchBorderActivatePresentWindowsValue(), PresentWindowsCurrent);
0222     // PresentWindows BorderActivateClass
0223     m_form->monitorChangeDefaultEdge(m_data->settings()->defaultTouchBorderActivateClassValue(), PresentWindowsClass);
0224 
0225     // Overview
0226     m_form->monitorChangeDefaultEdge(m_data->settings()->defaultTouchBorderActivateOverviewValue(), Overview);
0227 
0228     // TabBox BorderActivate
0229     m_form->monitorChangeDefaultEdge(m_data->settings()->defaultTouchBorderActivateTabBoxValue(), TabBox);
0230     // Alternative TabBox
0231     m_form->monitorChangeDefaultEdge(m_data->settings()->defaultTouchBorderAlternativeActivateValue(), TabBoxAlternative);
0232 }
0233 
0234 void KWinScreenEdgesConfig::monitorSaveSettings()
0235 {
0236     // Save ElectricBorderActions
0237     m_data->settings()->setTop(KWinScreenEdgesConfig::electricBorderActionToString(m_form->selectedEdgeItem(ElectricTop)));
0238     m_data->settings()->setRight(KWinScreenEdgesConfig::electricBorderActionToString(m_form->selectedEdgeItem(ElectricRight)));
0239     m_data->settings()->setBottom(KWinScreenEdgesConfig::electricBorderActionToString(m_form->selectedEdgeItem(ElectricBottom)));
0240     m_data->settings()->setLeft(KWinScreenEdgesConfig::electricBorderActionToString(m_form->selectedEdgeItem(ElectricLeft)));
0241 
0242     // Save effect-specific actions:
0243 
0244     // Present Windows
0245     m_data->settings()->setTouchBorderActivateAll(m_form->monitorCheckEffectHasEdge(PresentWindowsAll));
0246     m_data->settings()->setTouchBorderActivatePresentWindows(m_form->monitorCheckEffectHasEdge(PresentWindowsCurrent));
0247     m_data->settings()->setTouchBorderActivateClass(m_form->monitorCheckEffectHasEdge(PresentWindowsClass));
0248 
0249     // Overview
0250     m_data->settings()->setTouchBorderActivateOverview(m_form->monitorCheckEffectHasEdge(Overview));
0251 
0252     // TabBox
0253     m_data->settings()->setTouchBorderActivateTabBox(m_form->monitorCheckEffectHasEdge(TabBox));
0254     m_data->settings()->setTouchBorderAlternativeActivate(m_form->monitorCheckEffectHasEdge(TabBoxAlternative));
0255 
0256     // Dinamically loaded effects
0257     int lastIndex = EffectCount;
0258     for (int i = 0; i < m_effects.size(); i++) {
0259         m_effectSettings[m_effects[i]]->setTouchBorderActivate(m_form->monitorCheckEffectHasEdge(lastIndex));
0260         ++lastIndex;
0261     }
0262 
0263     // Scripts
0264     for (int i = 0; i < m_scripts.size(); i++) {
0265         m_scriptSettings[m_scripts[i]]->setTouchBorderActivate(m_form->monitorCheckEffectHasEdge(lastIndex));
0266         ++lastIndex;
0267     }
0268 }
0269 
0270 void KWinScreenEdgesConfig::monitorShowEvent()
0271 {
0272     // Check if they are enabled
0273     KConfigGroup config(m_config, QStringLiteral("Plugins"));
0274 
0275     // Present Windows
0276     bool enabled = config.readEntry("windowviewEnabled", true);
0277     m_form->monitorItemSetEnabled(PresentWindowsCurrent, enabled);
0278     m_form->monitorItemSetEnabled(PresentWindowsAll, enabled);
0279 
0280     // Overview
0281     m_form->monitorItemSetEnabled(Overview, config.readEntry("overviewEnabled", true));
0282 
0283     // tabbox, depends on reasonable focus policy.
0284     KConfigGroup config2(m_config, QStringLiteral("Windows"));
0285     QString focusPolicy = config2.readEntry("FocusPolicy", QString());
0286     bool reasonable = focusPolicy != "FocusStrictlyUnderMouse" && focusPolicy != "FocusUnderMouse";
0287     m_form->monitorItemSetEnabled(TabBox, reasonable);
0288     m_form->monitorItemSetEnabled(TabBoxAlternative, reasonable);
0289 
0290     // Disable Edge if TouchEdges group entries are immutable
0291     m_form->monitorEnableEdge(ElectricTop, !m_data->settings()->isTopImmutable());
0292     m_form->monitorEnableEdge(ElectricRight, !m_data->settings()->isRightImmutable());
0293     m_form->monitorEnableEdge(ElectricBottom, !m_data->settings()->isBottomImmutable());
0294     m_form->monitorEnableEdge(ElectricLeft, !m_data->settings()->isLeftImmutable());
0295 }
0296 
0297 ElectricBorderAction KWinScreenEdgesConfig::electricBorderActionFromString(const QString &string)
0298 {
0299     QString lowerName = string.toLower();
0300     if (lowerName == QStringLiteral("showdesktop")) {
0301         return ElectricActionShowDesktop;
0302     }
0303     if (lowerName == QStringLiteral("lockscreen")) {
0304         return ElectricActionLockScreen;
0305     }
0306     if (lowerName == QStringLiteral("krunner")) {
0307         return ElectricActionKRunner;
0308     }
0309     if (lowerName == QStringLiteral("activitymanager")) {
0310         return ElectricActionActivityManager;
0311     }
0312     if (lowerName == QStringLiteral("applicationlauncher")) {
0313         return ElectricActionApplicationLauncher;
0314     }
0315     return ElectricActionNone;
0316 }
0317 
0318 QString KWinScreenEdgesConfig::electricBorderActionToString(int action)
0319 {
0320     switch (action) {
0321     case 1:
0322         return QStringLiteral("ShowDesktop");
0323     case 2:
0324         return QStringLiteral("LockScreen");
0325     case 3:
0326         return QStringLiteral("KRunner");
0327     case 4:
0328         return QStringLiteral("ActivityManager");
0329     case 5:
0330         return QStringLiteral("ApplicationLauncher");
0331     default:
0332         return QStringLiteral("None");
0333     }
0334 }
0335 
0336 } // namespace
0337 
0338 #include "touch.moc"
0339 
0340 #include "moc_touch.cpp"