File indexing completed on 2024-11-10 04:56:41
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #include <config-kwin.h> 0010 0011 #include "appmenu.h" 0012 #include "compositor.h" 0013 #include "decorationbridge.h" 0014 #include "settings.h" 0015 #include "virtualdesktops.h" 0016 #include "workspace.h" 0017 0018 #include <KConfigGroup> 0019 #include <KDecoration2/DecorationSettings> 0020 0021 #include <QFontDatabase> 0022 0023 namespace KWin 0024 { 0025 namespace Decoration 0026 { 0027 SettingsImpl::SettingsImpl(KDecoration2::DecorationSettings *parent) 0028 : QObject() 0029 , DecorationSettingsPrivate(parent) 0030 , m_borderSize(KDecoration2::BorderSize::Normal) 0031 { 0032 readSettings(); 0033 0034 auto c = connect(Compositor::self(), &Compositor::compositingToggled, 0035 parent, &KDecoration2::DecorationSettings::alphaChannelSupportedChanged); 0036 connect(VirtualDesktopManager::self(), &VirtualDesktopManager::countChanged, this, [parent](uint previous, uint current) { 0037 if (previous != 1 && current != 1) { 0038 return; 0039 } 0040 Q_EMIT parent->onAllDesktopsAvailableChanged(current > 1); 0041 }); 0042 // prevent changes in Decoration due to Compositor being destroyed 0043 connect(Compositor::self(), &Compositor::aboutToDestroy, this, [c]() { 0044 disconnect(c); 0045 }); 0046 connect(Workspace::self(), &Workspace::configChanged, this, &SettingsImpl::readSettings); 0047 connect(Workspace::self()->decorationBridge(), &DecorationBridge::metaDataLoaded, this, &SettingsImpl::readSettings); 0048 } 0049 0050 SettingsImpl::~SettingsImpl() = default; 0051 0052 bool SettingsImpl::isAlphaChannelSupported() const 0053 { 0054 return Compositor::self()->compositing(); 0055 } 0056 0057 bool SettingsImpl::isOnAllDesktopsAvailable() const 0058 { 0059 return VirtualDesktopManager::self()->count() > 1; 0060 } 0061 0062 bool SettingsImpl::isCloseOnDoubleClickOnMenu() const 0063 { 0064 return m_closeDoubleClickMenu; 0065 } 0066 0067 static QHash<KDecoration2::DecorationButtonType, QChar> s_buttonNames; 0068 static void initButtons() 0069 { 0070 if (!s_buttonNames.isEmpty()) { 0071 return; 0072 } 0073 s_buttonNames[KDecoration2::DecorationButtonType::Menu] = QChar('M'); 0074 s_buttonNames[KDecoration2::DecorationButtonType::ApplicationMenu] = QChar('N'); 0075 s_buttonNames[KDecoration2::DecorationButtonType::OnAllDesktops] = QChar('S'); 0076 s_buttonNames[KDecoration2::DecorationButtonType::ContextHelp] = QChar('H'); 0077 s_buttonNames[KDecoration2::DecorationButtonType::Minimize] = QChar('I'); 0078 s_buttonNames[KDecoration2::DecorationButtonType::Maximize] = QChar('A'); 0079 s_buttonNames[KDecoration2::DecorationButtonType::Close] = QChar('X'); 0080 s_buttonNames[KDecoration2::DecorationButtonType::KeepAbove] = QChar('F'); 0081 s_buttonNames[KDecoration2::DecorationButtonType::KeepBelow] = QChar('B'); 0082 s_buttonNames[KDecoration2::DecorationButtonType::Shade] = QChar('L'); 0083 s_buttonNames[KDecoration2::DecorationButtonType::Spacer] = QChar('_'); 0084 } 0085 0086 static QString buttonsToString(const QList<KDecoration2::DecorationButtonType> &buttons) 0087 { 0088 auto buttonToString = [](KDecoration2::DecorationButtonType button) -> QChar { 0089 const auto it = s_buttonNames.constFind(button); 0090 if (it != s_buttonNames.constEnd()) { 0091 return it.value(); 0092 } 0093 return QChar(); 0094 }; 0095 QString ret; 0096 for (auto button : buttons) { 0097 ret.append(buttonToString(button)); 0098 } 0099 return ret; 0100 } 0101 0102 QList<KDecoration2::DecorationButtonType> SettingsImpl::readDecorationButtons(const KConfigGroup &config, 0103 const char *key, 0104 const QList<KDecoration2::DecorationButtonType> &defaultValue) const 0105 { 0106 initButtons(); 0107 auto buttonsFromString = [](const QString &buttons) -> QList<KDecoration2::DecorationButtonType> { 0108 QList<KDecoration2::DecorationButtonType> ret; 0109 for (auto it = buttons.begin(); it != buttons.end(); ++it) { 0110 for (auto it2 = s_buttonNames.constBegin(); it2 != s_buttonNames.constEnd(); ++it2) { 0111 if (it2.value() == (*it)) { 0112 ret << it2.key(); 0113 } 0114 } 0115 } 0116 return ret; 0117 }; 0118 return buttonsFromString(config.readEntry(key, buttonsToString(defaultValue))); 0119 } 0120 0121 static KDecoration2::BorderSize stringToSize(const QString &name) 0122 { 0123 static const QMap<QString, KDecoration2::BorderSize> s_sizes = QMap<QString, KDecoration2::BorderSize>({{QStringLiteral("None"), KDecoration2::BorderSize::None}, 0124 {QStringLiteral("NoSides"), KDecoration2::BorderSize::NoSides}, 0125 {QStringLiteral("Tiny"), KDecoration2::BorderSize::Tiny}, 0126 {QStringLiteral("Normal"), KDecoration2::BorderSize::Normal}, 0127 {QStringLiteral("Large"), KDecoration2::BorderSize::Large}, 0128 {QStringLiteral("VeryLarge"), KDecoration2::BorderSize::VeryLarge}, 0129 {QStringLiteral("Huge"), KDecoration2::BorderSize::Huge}, 0130 {QStringLiteral("VeryHuge"), KDecoration2::BorderSize::VeryHuge}, 0131 {QStringLiteral("Oversized"), KDecoration2::BorderSize::Oversized}}); 0132 auto it = s_sizes.constFind(name); 0133 if (it == s_sizes.constEnd()) { 0134 // non sense values are interpreted just like normal 0135 return KDecoration2::BorderSize::Normal; 0136 } 0137 return it.value(); 0138 } 0139 0140 void SettingsImpl::readSettings() 0141 { 0142 KConfigGroup config = kwinApp()->config()->group(QStringLiteral("org.kde.kdecoration2")); 0143 const auto &left = readDecorationButtons(config, "ButtonsOnLeft", QList<KDecoration2::DecorationButtonType>({KDecoration2::DecorationButtonType::Menu, KDecoration2::DecorationButtonType::OnAllDesktops})); 0144 if (left != m_leftButtons) { 0145 m_leftButtons = left; 0146 Q_EMIT decorationSettings()->decorationButtonsLeftChanged(m_leftButtons); 0147 } 0148 const auto &right = readDecorationButtons(config, "ButtonsOnRight", QList<KDecoration2::DecorationButtonType>({KDecoration2::DecorationButtonType::ContextHelp, KDecoration2::DecorationButtonType::Minimize, KDecoration2::DecorationButtonType::Maximize, KDecoration2::DecorationButtonType::Close})); 0149 if (right != m_rightButtons) { 0150 m_rightButtons = right; 0151 Q_EMIT decorationSettings()->decorationButtonsRightChanged(m_rightButtons); 0152 } 0153 Workspace::self()->applicationMenu()->setViewEnabled(left.contains(KDecoration2::DecorationButtonType::ApplicationMenu) || right.contains(KDecoration2::DecorationButtonType::ApplicationMenu)); 0154 const bool close = config.readEntry("CloseOnDoubleClickOnMenu", false); 0155 if (close != m_closeDoubleClickMenu) { 0156 m_closeDoubleClickMenu = close; 0157 Q_EMIT decorationSettings()->closeOnDoubleClickOnMenuChanged(m_closeDoubleClickMenu); 0158 } 0159 m_autoBorderSize = config.readEntry("BorderSizeAuto", true); 0160 0161 auto size = stringToSize(config.readEntry("BorderSize", QStringLiteral("Normal"))); 0162 if (m_autoBorderSize) { 0163 /* Falls back to Normal border size, if the plugin does not provide a valid recommendation. */ 0164 size = stringToSize(Workspace::self()->decorationBridge()->recommendedBorderSize()); 0165 } 0166 if (size != m_borderSize) { 0167 m_borderSize = size; 0168 Q_EMIT decorationSettings()->borderSizeChanged(m_borderSize); 0169 } 0170 const QFont font = QFontDatabase::systemFont(QFontDatabase::TitleFont); 0171 if (font != m_font) { 0172 m_font = font; 0173 Q_EMIT decorationSettings()->fontChanged(m_font); 0174 } 0175 0176 Q_EMIT decorationSettings()->reconfigured(); 0177 } 0178 0179 } 0180 } 0181 0182 #include "moc_settings.cpp"