1 /*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2008 Martin Gräßlin <mgraesslin@kde.org>
6 SPDX-FileCopyrightText: 2009 Lucas Murray <lmurray@undefinedfire.com>
7 SPDX-FileCopyrightText: 2020 Cyril Rossi <cyril.rossi@enioka.com>
8
9 SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12 #include "main.h"
13 #include <effect_builtins.h>
14 #include <kwin_effects_interface.h>
15
16 #include <KAboutData>
17 #include <KConfigGroup>
18 #include <KLocalizedString>
19 #include <KPluginFactory>
20 #include <KPackage/Package>
21 #include <KPackage/PackageLoader>
22 #include <QtDBus>
23 #include <QVBoxLayout>
24
25 #include "kwinscreenedgeconfigform.h"
26 #include "kwinscreenedgedata.h"
27 #include "kwinscreenedgesettings.h"
28 #include "kwinscreenedgescriptsettings.h"
29
30 K_PLUGIN_FACTORY(KWinScreenEdgesConfigFactory, registerPlugin<KWin::KWinScreenEdgesConfig>(); registerPlugin<KWin::KWinScreenEdgeData>();)
31
32 namespace KWin
33 {
34
KWinScreenEdgesConfig(QWidget * parent,const QVariantList & args)35 KWinScreenEdgesConfig::KWinScreenEdgesConfig(QWidget *parent, const QVariantList &args)
36 : KCModule(parent, args)
37 , m_form(new KWinScreenEdgesConfigForm(this))
38 , m_config(KSharedConfig::openConfig("kwinrc"))
39 , m_data(new KWinScreenEdgeData(this))
40 {
41 QVBoxLayout *layout = new QVBoxLayout(this);
42 layout->addWidget(m_form);
43
44 addConfig(m_data->settings(), m_form);
45
46 monitorInit();
47
48 connect(this, &KWinScreenEdgesConfig::defaultsIndicatorsVisibleChanged, m_form, &KWinScreenEdgesConfigForm::setDefaultsIndicatorsVisible);
49 connect(m_form, &KWinScreenEdgesConfigForm::saveNeededChanged, this, &KWinScreenEdgesConfig::unmanagedWidgetChangeState);
50 connect(m_form, &KWinScreenEdgesConfigForm::defaultChanged, this, &KWinScreenEdgesConfig::unmanagedWidgetDefaultState);
51 }
52
~KWinScreenEdgesConfig()53 KWinScreenEdgesConfig::~KWinScreenEdgesConfig()
54 {
55 }
56
load()57 void KWinScreenEdgesConfig::load()
58 {
59 KCModule::load();
60 m_data->settings()->load();
61 for (KWinScreenEdgeScriptSettings *setting : qAsConst(m_scriptSettings)) {
62 setting->load();
63 }
64
65 monitorLoadSettings();
66 monitorLoadDefaultSettings();
67 m_form->setElectricBorderCornerRatio(m_data->settings()->electricBorderCornerRatio());
68 m_form->setDefaultElectricBorderCornerRatio(m_data->settings()->defaultElectricBorderCornerRatioValue());
69 m_form->reload();
70 }
71
save()72 void KWinScreenEdgesConfig::save()
73 {
74 monitorSaveSettings();
75 m_data->settings()->setElectricBorderCornerRatio(m_form->electricBorderCornerRatio());
76 m_data->settings()->save();
77 for (KWinScreenEdgeScriptSettings *setting : qAsConst(m_scriptSettings)) {
78 setting->save();
79 }
80
81 // Reload saved settings to ScreenEdge UI
82 monitorLoadSettings();
83 m_form->setElectricBorderCornerRatio(m_data->settings()->electricBorderCornerRatio());
84 m_form->reload();
85
86 // Reload KWin.
87 QDBusMessage message = QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reloadConfig");
88 QDBusConnection::sessionBus().send(message);
89 // and reconfigure the effects
90 OrgKdeKwinEffectsInterface interface(QStringLiteral("org.kde.KWin"),
91 QStringLiteral("/Effects"),
92 QDBusConnection::sessionBus());
93 interface.reconfigureEffect(BuiltInEffects::nameForEffect(BuiltInEffect::Overview));
94 interface.reconfigureEffect(BuiltInEffects::nameForEffect(BuiltInEffect::PresentWindows));
95 interface.reconfigureEffect(BuiltInEffects::nameForEffect(BuiltInEffect::DesktopGrid));
96
97 KCModule::save();
98 }
99
defaults()100 void KWinScreenEdgesConfig::defaults()
101 {
102 m_form->setDefaults();
103
104 KCModule::defaults();
105 }
106
showEvent(QShowEvent * e)107 void KWinScreenEdgesConfig::showEvent(QShowEvent *e)
108 {
109 KCModule::showEvent(e);
110
111 monitorShowEvent();
112 }
113
114 // Copied from kcmkwin/kwincompositing/main.cpp
effectEnabled(const BuiltInEffect & effect,const KConfigGroup & cfg) const115 bool KWinScreenEdgesConfig::effectEnabled(const BuiltInEffect &effect, const KConfigGroup &cfg) const
116 {
117 return cfg.readEntry(BuiltInEffects::nameForEffect(effect) + "Enabled", BuiltInEffects::enabledByDefault(effect));
118 }
119
120 //-----------------------------------------------------------------------------
121 // Monitor
122
monitorInit()123 void KWinScreenEdgesConfig::monitorInit()
124 {
125 m_form->monitorAddItem(i18n("No Action"));
126 m_form->monitorAddItem(i18n("Show Desktop"));
127 m_form->monitorAddItem(i18n("Lock Screen"));
128 m_form->monitorAddItem(i18n("Show KRunner"));
129 m_form->monitorAddItem(i18n("Activity Manager"));
130 m_form->monitorAddItem(i18n("Application Launcher"));
131
132 // Add the effects
133 const QString presentWindowsName = BuiltInEffects::effectData(BuiltInEffect::PresentWindows).displayName;
134 m_form->monitorAddItem(i18n("%1 - All Desktops", presentWindowsName));
135 m_form->monitorAddItem(i18n("%1 - Current Desktop", presentWindowsName));
136 m_form->monitorAddItem(i18n("%1 - Current Application", presentWindowsName));
137 m_form->monitorAddItem(BuiltInEffects::effectData(BuiltInEffect::DesktopGrid).displayName);
138
139 m_form->monitorAddItem(i18n("Toggle window switching"));
140 m_form->monitorAddItem(i18n("Toggle alternative window switching"));
141
142 m_form->monitorAddItem(i18n("Toggle Overview"));
143
144 const QString scriptFolder = QStringLiteral("kwin/scripts/");
145 const auto scripts = KPackage::PackageLoader::self()->listPackages(QStringLiteral("KWin/Script"), scriptFolder);
146
147 KConfigGroup config(m_config, "Plugins");
148 for (const KPluginMetaData &script: scripts) {
149 if (script.value(QStringLiteral("X-KWin-Border-Activate")) != QLatin1String("true")) {
150 continue;
151 }
152
153 if (!config.readEntry(script.pluginId() + QStringLiteral("Enabled"), script.isEnabledByDefault())) {
154 continue;
155 }
156 m_scripts << script.pluginId();
157 m_form->monitorAddItem(script.name());
158 m_scriptSettings[script.pluginId()] = new KWinScreenEdgeScriptSettings(script.pluginId(), this);
159 }
160
161 monitorShowEvent();
162 }
163
monitorLoadSettings()164 void KWinScreenEdgesConfig::monitorLoadSettings()
165 {
166 // Load ElectricBorderActions
167 m_form->monitorChangeEdge(ElectricTop, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->top()));
168 m_form->monitorChangeEdge(ElectricTopRight, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->topRight()));
169 m_form->monitorChangeEdge(ElectricRight, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->right()));
170 m_form->monitorChangeEdge(ElectricBottomRight, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->bottomRight()));
171 m_form->monitorChangeEdge(ElectricBottom, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->bottom()));
172 m_form->monitorChangeEdge(ElectricBottomLeft, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->bottomLeft()));
173 m_form->monitorChangeEdge(ElectricLeft, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->left()));
174 m_form->monitorChangeEdge(ElectricTopLeft, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->topLeft()));
175
176 // Load effect-specific actions:
177
178 // PresentWindows BorderActivateAll
179 m_form->monitorChangeEdge(m_data->settings()->borderActivateAll(), PresentWindowsAll);
180
181 // PresentWindows BorderActivate
182 m_form->monitorChangeEdge(m_data->settings()->borderActivatePresentWindows(), PresentWindowsCurrent);
183
184 // PresentWindows BorderActivateClass
185 m_form->monitorChangeEdge(m_data->settings()->borderActivateClass(), PresentWindowsClass);
186
187 // Desktop Grid
188 m_form->monitorChangeEdge(m_data->settings()->borderActivateDesktopGrid(), DesktopGrid);
189
190 // TabBox
191 m_form->monitorChangeEdge(m_data->settings()->borderActivateTabBox(), TabBox);
192 // Alternative TabBox
193 m_form->monitorChangeEdge(m_data->settings()->borderAlternativeActivate(), TabBoxAlternative);
194
195 // Overview
196 m_form->monitorChangeEdge(m_data->settings()->borderActivateOverview(), Overview);
197
198 // Scripts
199 for (int i = 0; i < m_scripts.size(); i++) {
200 int index = EffectCount + i;
201 m_form->monitorChangeEdge(m_scriptSettings[m_scripts[i]]->borderActivate(), index);
202 }
203 }
204
monitorLoadDefaultSettings()205 void KWinScreenEdgesConfig::monitorLoadDefaultSettings()
206 {
207 // Load ElectricBorderActions
208 m_form->monitorChangeDefaultEdge(ElectricTop, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->defaultTopValue()));
209 m_form->monitorChangeDefaultEdge(ElectricTopRight, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->defaultTopRightValue()));
210 m_form->monitorChangeDefaultEdge(ElectricRight, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->defaultRightValue()));
211 m_form->monitorChangeDefaultEdge(ElectricBottomRight, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->defaultBottomRightValue()));
212 m_form->monitorChangeDefaultEdge(ElectricBottom, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->defaultBottomValue()));
213 m_form->monitorChangeDefaultEdge(ElectricBottomLeft, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->defaultBottomLeftValue()));
214 m_form->monitorChangeDefaultEdge(ElectricLeft, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->defaultLeftValue()));
215 m_form->monitorChangeDefaultEdge(ElectricTopLeft, KWinScreenEdgesConfig::electricBorderActionFromString(m_data->settings()->defaultTopLeftValue()));
216
217 // Load effect-specific actions:
218
219 // PresentWindows BorderActivateAll
220 m_form->monitorChangeDefaultEdge(m_data->settings()->defaultBorderActivateAllValue(), PresentWindowsAll);
221
222 // PresentWindows BorderActivate
223 m_form->monitorChangeDefaultEdge(m_data->settings()->defaultBorderActivatePresentWindowsValue(), PresentWindowsCurrent);
224
225 // PresentWindows BorderActivateClass
226 m_form->monitorChangeDefaultEdge(m_data->settings()->defaultBorderActivateClassValue(), PresentWindowsClass);
227
228 // Desktop Grid
229 m_form->monitorChangeDefaultEdge(m_data->settings()->defaultBorderActivateDesktopGridValue(), DesktopGrid);
230
231 // TabBox
232 m_form->monitorChangeDefaultEdge(m_data->settings()->defaultBorderActivateTabBoxValue(), TabBox);
233 // Alternative TabBox
234 m_form->monitorChangeDefaultEdge(m_data->settings()->defaultBorderAlternativeActivateValue(), TabBoxAlternative);
235
236 // Overview
237 m_form->monitorChangeDefaultEdge(m_data->settings()->defaultBorderActivateOverviewValue(), Overview);
238 }
239
monitorSaveSettings()240 void KWinScreenEdgesConfig::monitorSaveSettings()
241 {
242 // Save ElectricBorderActions
243 m_data->settings()->setTop(KWinScreenEdgesConfig::electricBorderActionToString(m_form->selectedEdgeItem(ElectricTop)));
244 m_data->settings()->setTopRight(KWinScreenEdgesConfig::electricBorderActionToString(m_form->selectedEdgeItem(ElectricTopRight)));
245 m_data->settings()->setRight(KWinScreenEdgesConfig::electricBorderActionToString(m_form->selectedEdgeItem(ElectricRight)));
246 m_data->settings()->setBottomRight(KWinScreenEdgesConfig::electricBorderActionToString(m_form->selectedEdgeItem(ElectricBottomRight)));
247 m_data->settings()->setBottom(KWinScreenEdgesConfig::electricBorderActionToString(m_form->selectedEdgeItem(ElectricBottom)));
248 m_data->settings()->setBottomLeft(KWinScreenEdgesConfig::electricBorderActionToString(m_form->selectedEdgeItem(ElectricBottomLeft)));
249 m_data->settings()->setLeft(KWinScreenEdgesConfig::electricBorderActionToString(m_form->selectedEdgeItem(ElectricLeft)));
250 m_data->settings()->setTopLeft(KWinScreenEdgesConfig::electricBorderActionToString(m_form->selectedEdgeItem(ElectricTopLeft)));
251
252 // Save effect-specific actions:
253
254 // Present Windows
255 m_data->settings()->setBorderActivateAll(m_form->monitorCheckEffectHasEdge(PresentWindowsAll));
256 m_data->settings()->setBorderActivatePresentWindows(m_form->monitorCheckEffectHasEdge(PresentWindowsCurrent));
257 m_data->settings()->setBorderActivateClass(m_form->monitorCheckEffectHasEdge(PresentWindowsClass));
258
259 // Desktop Grid
260 m_data->settings()->setBorderActivateDesktopGrid(m_form->monitorCheckEffectHasEdge(DesktopGrid));
261
262 // TabBox
263 m_data->settings()->setBorderActivateTabBox(m_form->monitorCheckEffectHasEdge(TabBox));
264 m_data->settings()->setBorderAlternativeActivate(m_form->monitorCheckEffectHasEdge(TabBoxAlternative));
265
266 // Overview
267 m_data->settings()->setBorderActivateOverview(m_form->monitorCheckEffectHasEdge(Overview));
268
269 // Scripts
270 for (int i = 0; i < m_scripts.size(); i++) {
271 int index = EffectCount + i;
272 m_scriptSettings[m_scripts[i]]->setBorderActivate(m_form->monitorCheckEffectHasEdge(index));
273 }
274 }
275
monitorShowEvent()276 void KWinScreenEdgesConfig::monitorShowEvent()
277 {
278 // Check if they are enabled
279 KConfigGroup config(m_config, "Plugins");
280
281 // Present Windows
282 bool enabled = effectEnabled(BuiltInEffect::PresentWindows, config);
283 m_form->monitorItemSetEnabled(PresentWindowsCurrent, enabled);
284 m_form->monitorItemSetEnabled(PresentWindowsAll, enabled);
285
286 // Desktop Grid
287 enabled = effectEnabled(BuiltInEffect::DesktopGrid, config);
288 m_form->monitorItemSetEnabled(DesktopGrid, enabled);
289
290 // Overview
291 enabled = effectEnabled(BuiltInEffect::Overview, config);
292 m_form->monitorItemSetEnabled(Overview, enabled);
293
294 // tabbox, depends on reasonable focus policy.
295 KConfigGroup config2(m_config, "Windows");
296 QString focusPolicy = config2.readEntry("FocusPolicy", QString());
297 bool reasonable = focusPolicy != "FocusStrictlyUnderMouse" && focusPolicy != "FocusUnderMouse";
298 m_form->monitorItemSetEnabled(TabBox, reasonable);
299 m_form->monitorItemSetEnabled(TabBoxAlternative, reasonable);
300
301 // Disable Edge if ElectricBorders group entries are immutable
302 m_form->monitorEnableEdge(ElectricTop, !m_data->settings()->isTopImmutable());
303 m_form->monitorEnableEdge(ElectricTopRight, !m_data->settings()->isTopRightImmutable());
304 m_form->monitorEnableEdge(ElectricRight, !m_data->settings()->isRightImmutable());
305 m_form->monitorEnableEdge(ElectricBottomRight, !m_data->settings()->isBottomRightImmutable());
306 m_form->monitorEnableEdge(ElectricBottom, !m_data->settings()->isBottomImmutable());
307 m_form->monitorEnableEdge(ElectricBottomLeft, !m_data->settings()->isBottomLeftImmutable());
308 m_form->monitorEnableEdge(ElectricLeft, !m_data->settings()->isLeftImmutable());
309 m_form->monitorEnableEdge(ElectricTopLeft, !m_data->settings()->isTopLeftImmutable());
310
311 // Disable ElectricBorderCornerRatio if entry is immutable
312 m_form->setElectricBorderCornerRatioEnabled(!m_data->settings()->isElectricBorderCornerRatioImmutable());
313 }
314
electricBorderActionFromString(const QString & string)315 ElectricBorderAction KWinScreenEdgesConfig::electricBorderActionFromString(const QString &string)
316 {
317 QString lowerName = string.toLower();
318 if (lowerName == QStringLiteral("showdesktop")) {
319 return ElectricActionShowDesktop;
320 }
321 if (lowerName == QStringLiteral("lockscreen")) {
322 return ElectricActionLockScreen;
323 }
324 if (lowerName == QStringLiteral("krunner")) {
325 return ElectricActionKRunner;
326 }
327 if (lowerName == QStringLiteral("activitymanager")) {
328 return ElectricActionActivityManager;
329 }
330 if (lowerName == QStringLiteral("applicationlauncher")) {
331 return ElectricActionApplicationLauncher;
332 }
333 return ElectricActionNone;
334 }
335
electricBorderActionToString(int action)336 QString KWinScreenEdgesConfig::electricBorderActionToString(int action)
337 {
338 switch (action) {
339 case 1:
340 return QStringLiteral("ShowDesktop");
341 case 2:
342 return QStringLiteral("LockScreen");
343 case 3:
344 return QStringLiteral("KRunner");
345 case 4:
346 return QStringLiteral("ActivityManager");
347 case 5:
348 return QStringLiteral("ApplicationLauncher");
349 default:
350 return QStringLiteral("None");
351 }
352 }
353
354 } // namespace
355
356 #include "main.moc"
357