KWin
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
main.cpp
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2009 Martin Gräßlin <mgraesslin@kde.org>
6 SPDX-FileCopyrightText: 2020 Cyril Rossi <cyril.rossi@enioka.com>
7 SPDX-FileCopyrightText: 2023 Ismael Asensio <isma.af@gmail.com>
8
9 SPDX-License-Identifier: GPL-2.0-or-later
10*/
11#include "main.h"
12#include <kwin_effects_interface.h>
13
14// Qt
15#include <QDBusConnection>
16#include <QDBusMessage>
17#include <QDialog>
18#include <QDialogButtonBox>
19#include <QHBoxLayout>
20#include <QPointer>
21#include <QPushButton>
22#include <QSpacerItem>
23#include <QStandardItemModel>
24#include <QStandardPaths>
25#include <QTabWidget>
26#include <QVBoxLayout>
27
28// KDE
29#include <KLocalizedString>
30#include <KNSWidgets/Button>
31#include <KPluginFactory>
32#include <KTitleWidget>
33// Plasma
34#include <KPackage/Package>
35#include <KPackage/PackageLoader>
36
37// own
38#include "kwinpluginssettings.h"
40#include "kwintabboxdata.h"
41#include "kwintabboxsettings.h"
42#include "layoutpreview.h"
43#include "shortcutsettings.h"
44
45K_PLUGIN_FACTORY_WITH_JSON(KWinTabBoxConfigFactory, "kcm_kwintabbox.json", registerPlugin<KWin::KWinTabBoxConfig>(); registerPlugin<KWin::TabBox::KWinTabboxData>();)
46
47namespace KWin
48{
49
50using namespace TabBox;
51
52KWinTabBoxConfig::KWinTabBoxConfig(QObject *parent, const KPluginMetaData &data)
53 : KCModule(parent, data)
54 , m_config(KSharedConfig::openConfig("kwinrc"))
55 , m_data(new KWinTabboxData(this))
56{
57 QTabWidget *tabWidget = new QTabWidget(widget());
58 m_primaryTabBoxUi = new KWinTabBoxConfigForm(KWinTabBoxConfigForm::TabboxType::Main,
59 m_data->tabBoxConfig(),
60 m_data->shortcutConfig(),
61 tabWidget);
62 m_alternativeTabBoxUi = new KWinTabBoxConfigForm(KWinTabBoxConfigForm::TabboxType::Alternative,
63 m_data->tabBoxAlternativeConfig(),
64 m_data->shortcutConfig(),
65 tabWidget);
66 tabWidget->addTab(m_primaryTabBoxUi, i18n("Main"));
67 tabWidget->addTab(m_alternativeTabBoxUi, i18n("Alternative"));
68
69 KNSWidgets::Button *ghnsButton = new KNSWidgets::Button(i18n("Get New Task Switchers..."), QStringLiteral("kwinswitcher.knsrc"), widget());
70 connect(ghnsButton, &KNSWidgets::Button::dialogFinished, this, [this](auto changedEntries) {
71 if (!changedEntries.isEmpty()) {
72 initLayoutLists();
73 }
74 });
75
76 QHBoxLayout *buttonBar = new QHBoxLayout();
77 QSpacerItem *buttonBarSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
78 buttonBar->addItem(buttonBarSpacer);
79 buttonBar->addWidget(ghnsButton);
80
81 QVBoxLayout *layout = new QVBoxLayout(widget());
82 KTitleWidget *infoLabel = new KTitleWidget(tabWidget);
83 infoLabel->setText(i18n("Focus policy settings limit the functionality of navigating through windows."),
84 KTitleWidget::InfoMessage);
85 infoLabel->setIcon(KTitleWidget::InfoMessage, KTitleWidget::ImageLeft);
86 layout->addWidget(infoLabel, 0);
87 layout->addWidget(tabWidget, 1);
88 layout->addLayout(buttonBar);
89 widget()->setLayout(layout);
90
91 addConfig(m_data->tabBoxConfig(), m_primaryTabBoxUi);
92 addConfig(m_data->tabBoxAlternativeConfig(), m_alternativeTabBoxUi);
93
94 initLayoutLists();
95
96 createConnections(m_primaryTabBoxUi);
97 createConnections(m_alternativeTabBoxUi);
98
99 // check focus policy - we don't offer configs for unreasonable focus policies
100 KConfigGroup config(m_config, QStringLiteral("Windows"));
101 QString policy = config.readEntry("FocusPolicy", "ClickToFocus");
102 if ((policy == "FocusUnderMouse") || (policy == "FocusStrictlyUnderMouse")) {
103 tabWidget->setEnabled(false);
104 infoLabel->show();
105 } else {
106 infoLabel->hide();
107 }
108}
109
110KWinTabBoxConfig::~KWinTabBoxConfig()
111{
112}
113
114static QList<KPackage::Package> availableLnFPackages()
115{
116 QList<KPackage::Package> packages;
117 QStringList paths;
118 const QStringList dataPaths = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
119
120 for (const QString &path : dataPaths) {
121 QDir dir(path + QLatin1String("/plasma/look-and-feel"));
122 paths << dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
123 }
124
125 const auto &p = paths;
126 for (const QString &path : p) {
127 KPackage::Package pkg = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Plasma/LookAndFeel"));
128 pkg.setPath(path);
129 pkg.setFallbackPackage(KPackage::Package());
130 if (!pkg.filePath("defaults").isEmpty()) {
131 KSharedConfigPtr conf = KSharedConfig::openConfig(pkg.filePath("defaults"));
132 KConfigGroup cg = KConfigGroup(conf, QStringLiteral("kwinrc"));
133 cg = KConfigGroup(&cg, QStringLiteral("WindowSwitcher"));
134 if (!cg.readEntry("LayoutName", QString()).isEmpty()) {
135 packages << pkg;
136 }
137 }
138 }
139
140 return packages;
141}
142
143void KWinTabBoxConfig::initLayoutLists()
144{
145 QList<KPluginMetaData> offers = KPackage::PackageLoader::self()->listPackages("KWin/WindowSwitcher");
146 QStandardItemModel *model = new QStandardItemModel;
147
148 auto addToModel = [model](const QString &name, const QString &pluginId, const QString &path) {
149 QStandardItem *item = new QStandardItem(name);
150 item->setData(pluginId, Qt::UserRole);
151 item->setData(path, KWinTabBoxConfigForm::LayoutPath);
152 item->setData(true, KWinTabBoxConfigForm::AddonEffect);
153 model->appendRow(item);
154 };
155
156 const auto lnfPackages = availableLnFPackages();
157 for (const auto &package : lnfPackages) {
158 const auto &metaData = package.metadata();
159 const QString switcherFile = package.filePath("windowswitcher", QStringLiteral("WindowSwitcher.qml"));
160 if (switcherFile.isEmpty()) {
161 // Skip lnfs that don't actually ship a switcher
162 continue;
163 }
164
165 addToModel(metaData.name(), metaData.pluginId(), switcherFile);
166 }
167
168 for (const auto &offer : offers) {
169 const QString pluginName = offer.pluginId();
170 const QString scriptFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation,
171 QLatin1String("kwin/tabbox/") + pluginName + QLatin1String("/contents/ui/main.qml"));
172 if (scriptFile.isEmpty()) {
173 qWarning() << "scriptfile is null" << pluginName;
174 continue;
175 }
176
177 addToModel(offer.name(), pluginName, scriptFile);
178 }
179
180 model->sort(0);
181
182 m_primaryTabBoxUi->setEffectComboModel(model);
183 m_alternativeTabBoxUi->setEffectComboModel(model);
184}
185
186void KWinTabBoxConfig::createConnections(KWinTabBoxConfigForm *form)
187{
188 connect(form, &KWinTabBoxConfigForm::effectConfigButtonClicked, this, &KWinTabBoxConfig::configureEffectClicked);
189 connect(form, &KWinTabBoxConfigForm::configChanged, this, &KWinTabBoxConfig::updateUnmanagedState);
190
191 connect(this, &KWinTabBoxConfig::defaultsIndicatorsVisibleChanged, form, [form, this]() {
192 form->setDefaultIndicatorVisible(defaultsIndicatorsVisible());
193 });
194}
195
196void KWinTabBoxConfig::updateUnmanagedState()
197{
198 const bool isNeedSave = m_data->tabBoxConfig()->isSaveNeeded()
199 || m_data->tabBoxAlternativeConfig()->isSaveNeeded()
200 || m_data->shortcutConfig()->isSaveNeeded();
201
202 unmanagedWidgetChangeState(isNeedSave);
203
204 const bool isDefault = m_data->tabBoxConfig()->isDefaults()
205 && m_data->tabBoxAlternativeConfig()->isDefaults()
206 && m_data->shortcutConfig()->isDefaults();
207
208 unmanagedWidgetDefaultState(isDefault);
209}
210
211void KWinTabBoxConfig::load()
212{
213 KCModule::load();
214
215 m_data->tabBoxConfig()->load();
216 m_data->tabBoxAlternativeConfig()->load();
217 m_data->shortcutConfig()->load();
218
219 m_data->pluginsConfig()->load();
220
221 m_primaryTabBoxUi->updateUiFromConfig();
222 m_alternativeTabBoxUi->updateUiFromConfig();
223
224 updateUnmanagedState();
225}
226
227void KWinTabBoxConfig::save()
228{
229 // effects
230 const bool highlightWindows = m_primaryTabBoxUi->highlightWindows() || m_alternativeTabBoxUi->highlightWindows();
231
232 // activate effects if they are used otherwise deactivate them.
233 m_data->pluginsConfig()->setHighlightwindowEnabled(highlightWindows);
234 m_data->pluginsConfig()->save();
235
236 m_data->tabBoxConfig()->save();
237 m_data->tabBoxAlternativeConfig()->save();
238 m_data->shortcutConfig()->save();
239
240 KCModule::save();
241 updateUnmanagedState();
242
243 // Reload KWin.
244 QDBusMessage message = QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reloadConfig");
245 QDBusConnection::sessionBus().send(message);
246}
247
248void KWinTabBoxConfig::defaults()
249{
250 m_data->tabBoxConfig()->setDefaults();
251 m_data->tabBoxAlternativeConfig()->setDefaults();
252 m_data->shortcutConfig()->setDefaults();
253
254 m_primaryTabBoxUi->updateUiFromConfig();
255 m_alternativeTabBoxUi->updateUiFromConfig();
256
257 KCModule::defaults();
258 updateUnmanagedState();
259}
260void KWinTabBoxConfig::configureEffectClicked()
261{
262 auto form = qobject_cast<KWinTabBoxConfigForm *>(sender());
263 Q_ASSERT(form);
264
265 if (form->effectComboCurrentData(KWinTabBoxConfigForm::AddonEffect).toBool()) {
266 // Show the preview for addon effect
267 new LayoutPreview(form->effectComboCurrentData(KWinTabBoxConfigForm::LayoutPath).toString(),
268 form->config()->showDesktopMode(),
269 this);
270 }
271}
272
273} // namespace
274
275#include "main.moc"
276
277#include "moc_main.cpp"
K_PLUGIN_FACTORY_WITH_JSON(KCMKWinDecorationFactory, "kcm_kwindecoration.json", registerPlugin< KCMKWinDecoration >();registerPlugin< KWinDecorationData >();) namespace
Definition kcm.cpp:29