File indexing completed on 2024-11-10 04:57:52

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 1999, 2000 Matthias Ettrich <ettrich@kde.org>
0006     SPDX-FileCopyrightText: 2003 Lubos Lunak <l.lunak@kde.org>
0007     SPDX-FileCopyrightText: 2012 Martin Gräßlin <m.graesslin@kde.org>
0008 
0009     SPDX-License-Identifier: GPL-2.0-or-later
0010 */
0011 #include "options.h"
0012 
0013 #include "config-kwin.h"
0014 
0015 #include "utils/common.h"
0016 
0017 #ifndef KCMRULES
0018 
0019 #include <QProcess>
0020 
0021 #include "settings.h"
0022 #include "workspace.h"
0023 #include <QOpenGLContext>
0024 
0025 #endif // KCMRULES
0026 
0027 namespace KWin
0028 {
0029 
0030 #ifndef KCMRULES
0031 
0032 Options::Options(QObject *parent)
0033     : QObject(parent)
0034     , m_settings(new Settings(kwinApp()->config()))
0035     , m_focusPolicy(ClickToFocus)
0036     , m_nextFocusPrefersMouse(false)
0037     , m_clickRaise(false)
0038     , m_autoRaise(false)
0039     , m_autoRaiseInterval(0)
0040     , m_delayFocusInterval(0)
0041     , m_shadeHover(false)
0042     , m_shadeHoverInterval(0)
0043     , m_separateScreenFocus(false)
0044     , m_activeMouseScreen(false)
0045     , m_placement(PlacementNone)
0046     , m_activationDesktopPolicy(Options::defaultActivationDesktopPolicy())
0047     , m_borderSnapZone(0)
0048     , m_windowSnapZone(0)
0049     , m_centerSnapZone(0)
0050     , m_snapOnlyWhenOverlapping(false)
0051     , m_rollOverDesktops(false)
0052     , m_focusStealingPreventionLevel(0)
0053     , m_killPingTimeout(0)
0054     , m_hideUtilityWindowsForInactive(false)
0055     , m_xwaylandCrashPolicy(Options::defaultXwaylandCrashPolicy())
0056     , m_xwaylandMaxCrashCount(Options::defaultXwaylandMaxCrashCount())
0057     , m_xwaylandEavesdrops(Options::defaultXwaylandEavesdrops())
0058     , m_compositingMode(Options::defaultCompositingMode())
0059     , m_useCompositing(Options::defaultUseCompositing())
0060     , m_hiddenPreviews(Options::defaultHiddenPreviews())
0061     , m_glSmoothScale(Options::defaultGlSmoothScale())
0062     , m_glStrictBinding(Options::defaultGlStrictBinding())
0063     , m_glStrictBindingFollowsDriver(Options::defaultGlStrictBindingFollowsDriver())
0064     , m_glPreferBufferSwap(Options::defaultGlPreferBufferSwap())
0065     , m_glPlatformInterface(Options::defaultGlPlatformInterface())
0066     , m_windowsBlockCompositing(true)
0067     , OpTitlebarDblClick(Options::defaultOperationTitlebarDblClick())
0068     , CmdActiveTitlebar1(Options::defaultCommandActiveTitlebar1())
0069     , CmdActiveTitlebar2(Options::defaultCommandActiveTitlebar2())
0070     , CmdActiveTitlebar3(Options::defaultCommandActiveTitlebar3())
0071     , CmdInactiveTitlebar1(Options::defaultCommandInactiveTitlebar1())
0072     , CmdInactiveTitlebar2(Options::defaultCommandInactiveTitlebar2())
0073     , CmdInactiveTitlebar3(Options::defaultCommandInactiveTitlebar3())
0074     , CmdTitlebarWheel(Options::defaultCommandTitlebarWheel())
0075     , CmdWindow1(Options::defaultCommandWindow1())
0076     , CmdWindow2(Options::defaultCommandWindow2())
0077     , CmdWindow3(Options::defaultCommandWindow3())
0078     , CmdWindowWheel(Options::defaultCommandWindowWheel())
0079     , CmdAll1(Options::defaultCommandAll1())
0080     , CmdAll2(Options::defaultCommandAll2())
0081     , CmdAll3(Options::defaultCommandAll3())
0082     , CmdAllWheel(Options::defaultCommandAllWheel())
0083     , CmdAllModKey(Options::defaultKeyCmdAllModKey())
0084     , electric_border_maximize(false)
0085     , electric_border_tiling(false)
0086     , electric_border_corner_ratio(0.0)
0087     , borderless_maximized_windows(false)
0088     , condensed_title(false)
0089 {
0090     m_settings->setDefaults();
0091 
0092     loadConfig();
0093 
0094     m_configWatcher = KConfigWatcher::create(m_settings->sharedConfig());
0095     connect(m_configWatcher.data(), &KConfigWatcher::configChanged, this, [this](const KConfigGroup &group, const QByteArrayList &names) {
0096         if (group.name() == QLatin1String("KDE") && names.contains(QByteArrayLiteral("AnimationDurationFactor"))) {
0097             m_settings->load();
0098             Q_EMIT animationSpeedChanged();
0099         } else if (group.name() == QLatin1String("Xwayland")) {
0100             workspace()->reconfigure();
0101         }
0102     });
0103 }
0104 
0105 Options::~Options()
0106 {
0107 }
0108 
0109 void Options::setFocusPolicy(FocusPolicy focusPolicy)
0110 {
0111     if (m_focusPolicy == focusPolicy) {
0112         return;
0113     }
0114     m_focusPolicy = focusPolicy;
0115     Q_EMIT focusPolicyChanged();
0116     if (m_focusPolicy == ClickToFocus) {
0117         setAutoRaise(false);
0118         setAutoRaiseInterval(0);
0119         setDelayFocusInterval(0);
0120     }
0121 }
0122 
0123 void Options::setNextFocusPrefersMouse(bool nextFocusPrefersMouse)
0124 {
0125     if (m_nextFocusPrefersMouse == nextFocusPrefersMouse) {
0126         return;
0127     }
0128     m_nextFocusPrefersMouse = nextFocusPrefersMouse;
0129     Q_EMIT nextFocusPrefersMouseChanged();
0130 }
0131 
0132 void Options::setXwaylandCrashPolicy(XwaylandCrashPolicy crashPolicy)
0133 {
0134     if (m_xwaylandCrashPolicy == crashPolicy) {
0135         return;
0136     }
0137     m_xwaylandCrashPolicy = crashPolicy;
0138     Q_EMIT xwaylandCrashPolicyChanged();
0139 }
0140 
0141 void Options::setXwaylandMaxCrashCount(int maxCrashCount)
0142 {
0143     if (m_xwaylandMaxCrashCount == maxCrashCount) {
0144         return;
0145     }
0146     m_xwaylandMaxCrashCount = maxCrashCount;
0147     Q_EMIT xwaylandMaxCrashCountChanged();
0148 }
0149 
0150 void Options::setXwaylandEavesdrops(XwaylandEavesdropsMode mode)
0151 {
0152     if (m_xwaylandEavesdrops == mode) {
0153         return;
0154     }
0155     m_xwaylandEavesdrops = mode;
0156     Q_EMIT xwaylandEavesdropsChanged();
0157 }
0158 
0159 void Options::setClickRaise(bool clickRaise)
0160 {
0161     if (m_autoRaise) {
0162         // important: autoRaise implies ClickRaise
0163         clickRaise = true;
0164     }
0165     if (m_clickRaise == clickRaise) {
0166         return;
0167     }
0168     m_clickRaise = clickRaise;
0169     Q_EMIT clickRaiseChanged();
0170 }
0171 
0172 void Options::setAutoRaise(bool autoRaise)
0173 {
0174     if (m_focusPolicy == ClickToFocus) {
0175         autoRaise = false;
0176     }
0177     if (m_autoRaise == autoRaise) {
0178         return;
0179     }
0180     m_autoRaise = autoRaise;
0181     if (m_autoRaise) {
0182         // important: autoRaise implies ClickRaise
0183         setClickRaise(true);
0184     }
0185     Q_EMIT autoRaiseChanged();
0186 }
0187 
0188 void Options::setAutoRaiseInterval(int autoRaiseInterval)
0189 {
0190     if (m_focusPolicy == ClickToFocus) {
0191         autoRaiseInterval = 0;
0192     }
0193     if (m_autoRaiseInterval == autoRaiseInterval) {
0194         return;
0195     }
0196     m_autoRaiseInterval = autoRaiseInterval;
0197     Q_EMIT autoRaiseIntervalChanged();
0198 }
0199 
0200 void Options::setDelayFocusInterval(int delayFocusInterval)
0201 {
0202     if (m_focusPolicy == ClickToFocus) {
0203         delayFocusInterval = 0;
0204     }
0205     if (m_delayFocusInterval == delayFocusInterval) {
0206         return;
0207     }
0208     m_delayFocusInterval = delayFocusInterval;
0209     Q_EMIT delayFocusIntervalChanged();
0210 }
0211 
0212 void Options::setShadeHover(bool shadeHover)
0213 {
0214     if (m_shadeHover == shadeHover) {
0215         return;
0216     }
0217     m_shadeHover = shadeHover;
0218     Q_EMIT shadeHoverChanged();
0219 }
0220 
0221 void Options::setShadeHoverInterval(int shadeHoverInterval)
0222 {
0223     if (m_shadeHoverInterval == shadeHoverInterval) {
0224         return;
0225     }
0226     m_shadeHoverInterval = shadeHoverInterval;
0227     Q_EMIT shadeHoverIntervalChanged();
0228 }
0229 
0230 void Options::setSeparateScreenFocus(bool separateScreenFocus)
0231 {
0232     if (m_separateScreenFocus == separateScreenFocus) {
0233         return;
0234     }
0235     m_separateScreenFocus = separateScreenFocus;
0236     Q_EMIT separateScreenFocusChanged(m_separateScreenFocus);
0237 }
0238 
0239 void Options::setActiveMouseScreen(bool activeMouseScreen)
0240 {
0241     if (m_activeMouseScreen == activeMouseScreen) {
0242         return;
0243     }
0244     m_activeMouseScreen = activeMouseScreen;
0245     Q_EMIT activeMouseScreenChanged();
0246 }
0247 
0248 void Options::setPlacement(PlacementPolicy placement)
0249 {
0250     if (m_placement == placement) {
0251         return;
0252     }
0253     m_placement = placement;
0254     Q_EMIT placementChanged();
0255 }
0256 
0257 void Options::setActivationDesktopPolicy(ActivationDesktopPolicy activationDesktopPolicy)
0258 {
0259     if (m_activationDesktopPolicy == activationDesktopPolicy) {
0260         return;
0261     }
0262     m_activationDesktopPolicy = activationDesktopPolicy;
0263     Q_EMIT activationDesktopPolicyChanged();
0264 }
0265 
0266 void Options::setBorderSnapZone(int borderSnapZone)
0267 {
0268     if (m_borderSnapZone == borderSnapZone) {
0269         return;
0270     }
0271     m_borderSnapZone = borderSnapZone;
0272     Q_EMIT borderSnapZoneChanged();
0273 }
0274 
0275 void Options::setWindowSnapZone(int windowSnapZone)
0276 {
0277     if (m_windowSnapZone == windowSnapZone) {
0278         return;
0279     }
0280     m_windowSnapZone = windowSnapZone;
0281     Q_EMIT windowSnapZoneChanged();
0282 }
0283 
0284 void Options::setCenterSnapZone(int centerSnapZone)
0285 {
0286     if (m_centerSnapZone == centerSnapZone) {
0287         return;
0288     }
0289     m_centerSnapZone = centerSnapZone;
0290     Q_EMIT centerSnapZoneChanged();
0291 }
0292 
0293 void Options::setSnapOnlyWhenOverlapping(bool snapOnlyWhenOverlapping)
0294 {
0295     if (m_snapOnlyWhenOverlapping == snapOnlyWhenOverlapping) {
0296         return;
0297     }
0298     m_snapOnlyWhenOverlapping = snapOnlyWhenOverlapping;
0299     Q_EMIT snapOnlyWhenOverlappingChanged();
0300 }
0301 
0302 void Options::setRollOverDesktops(bool rollOverDesktops)
0303 {
0304     if (m_rollOverDesktops == rollOverDesktops) {
0305         return;
0306     }
0307     m_rollOverDesktops = rollOverDesktops;
0308     Q_EMIT rollOverDesktopsChanged(m_rollOverDesktops);
0309 }
0310 
0311 void Options::setFocusStealingPreventionLevel(int focusStealingPreventionLevel)
0312 {
0313     if (!focusPolicyIsReasonable()) {
0314         focusStealingPreventionLevel = 0;
0315     }
0316     if (m_focusStealingPreventionLevel == focusStealingPreventionLevel) {
0317         return;
0318     }
0319     m_focusStealingPreventionLevel = std::max(0, std::min(4, focusStealingPreventionLevel));
0320     Q_EMIT focusStealingPreventionLevelChanged();
0321 }
0322 
0323 void Options::setOperationTitlebarDblClick(WindowOperation operationTitlebarDblClick)
0324 {
0325     if (OpTitlebarDblClick == operationTitlebarDblClick) {
0326         return;
0327     }
0328     OpTitlebarDblClick = operationTitlebarDblClick;
0329     Q_EMIT operationTitlebarDblClickChanged();
0330 }
0331 
0332 void Options::setOperationMaxButtonLeftClick(WindowOperation op)
0333 {
0334     if (opMaxButtonLeftClick == op) {
0335         return;
0336     }
0337     opMaxButtonLeftClick = op;
0338     Q_EMIT operationMaxButtonLeftClickChanged();
0339 }
0340 
0341 void Options::setOperationMaxButtonRightClick(WindowOperation op)
0342 {
0343     if (opMaxButtonRightClick == op) {
0344         return;
0345     }
0346     opMaxButtonRightClick = op;
0347     Q_EMIT operationMaxButtonRightClickChanged();
0348 }
0349 
0350 void Options::setOperationMaxButtonMiddleClick(WindowOperation op)
0351 {
0352     if (opMaxButtonMiddleClick == op) {
0353         return;
0354     }
0355     opMaxButtonMiddleClick = op;
0356     Q_EMIT operationMaxButtonMiddleClickChanged();
0357 }
0358 
0359 void Options::setCommandActiveTitlebar1(MouseCommand commandActiveTitlebar1)
0360 {
0361     if (CmdActiveTitlebar1 == commandActiveTitlebar1) {
0362         return;
0363     }
0364     CmdActiveTitlebar1 = commandActiveTitlebar1;
0365     Q_EMIT commandActiveTitlebar1Changed();
0366 }
0367 
0368 void Options::setCommandActiveTitlebar2(MouseCommand commandActiveTitlebar2)
0369 {
0370     if (CmdActiveTitlebar2 == commandActiveTitlebar2) {
0371         return;
0372     }
0373     CmdActiveTitlebar2 = commandActiveTitlebar2;
0374     Q_EMIT commandActiveTitlebar2Changed();
0375 }
0376 
0377 void Options::setCommandActiveTitlebar3(MouseCommand commandActiveTitlebar3)
0378 {
0379     if (CmdActiveTitlebar3 == commandActiveTitlebar3) {
0380         return;
0381     }
0382     CmdActiveTitlebar3 = commandActiveTitlebar3;
0383     Q_EMIT commandActiveTitlebar3Changed();
0384 }
0385 
0386 void Options::setCommandInactiveTitlebar1(MouseCommand commandInactiveTitlebar1)
0387 {
0388     if (CmdInactiveTitlebar1 == commandInactiveTitlebar1) {
0389         return;
0390     }
0391     CmdInactiveTitlebar1 = commandInactiveTitlebar1;
0392     Q_EMIT commandInactiveTitlebar1Changed();
0393 }
0394 
0395 void Options::setCommandInactiveTitlebar2(MouseCommand commandInactiveTitlebar2)
0396 {
0397     if (CmdInactiveTitlebar2 == commandInactiveTitlebar2) {
0398         return;
0399     }
0400     CmdInactiveTitlebar2 = commandInactiveTitlebar2;
0401     Q_EMIT commandInactiveTitlebar2Changed();
0402 }
0403 
0404 void Options::setCommandInactiveTitlebar3(MouseCommand commandInactiveTitlebar3)
0405 {
0406     if (CmdInactiveTitlebar3 == commandInactiveTitlebar3) {
0407         return;
0408     }
0409     CmdInactiveTitlebar3 = commandInactiveTitlebar3;
0410     Q_EMIT commandInactiveTitlebar3Changed();
0411 }
0412 
0413 void Options::setCommandWindow1(MouseCommand commandWindow1)
0414 {
0415     if (CmdWindow1 == commandWindow1) {
0416         return;
0417     }
0418     CmdWindow1 = commandWindow1;
0419     Q_EMIT commandWindow1Changed();
0420 }
0421 
0422 void Options::setCommandWindow2(MouseCommand commandWindow2)
0423 {
0424     if (CmdWindow2 == commandWindow2) {
0425         return;
0426     }
0427     CmdWindow2 = commandWindow2;
0428     Q_EMIT commandWindow2Changed();
0429 }
0430 
0431 void Options::setCommandWindow3(MouseCommand commandWindow3)
0432 {
0433     if (CmdWindow3 == commandWindow3) {
0434         return;
0435     }
0436     CmdWindow3 = commandWindow3;
0437     Q_EMIT commandWindow3Changed();
0438 }
0439 
0440 void Options::setCommandWindowWheel(MouseCommand commandWindowWheel)
0441 {
0442     if (CmdWindowWheel == commandWindowWheel) {
0443         return;
0444     }
0445     CmdWindowWheel = commandWindowWheel;
0446     Q_EMIT commandWindowWheelChanged();
0447 }
0448 
0449 void Options::setCommandAll1(MouseCommand commandAll1)
0450 {
0451     if (CmdAll1 == commandAll1) {
0452         return;
0453     }
0454     CmdAll1 = commandAll1;
0455     Q_EMIT commandAll1Changed();
0456 }
0457 
0458 void Options::setCommandAll2(MouseCommand commandAll2)
0459 {
0460     if (CmdAll2 == commandAll2) {
0461         return;
0462     }
0463     CmdAll2 = commandAll2;
0464     Q_EMIT commandAll2Changed();
0465 }
0466 
0467 void Options::setCommandAll3(MouseCommand commandAll3)
0468 {
0469     if (CmdAll3 == commandAll3) {
0470         return;
0471     }
0472     CmdAll3 = commandAll3;
0473     Q_EMIT commandAll3Changed();
0474 }
0475 
0476 void Options::setKeyCmdAllModKey(uint keyCmdAllModKey)
0477 {
0478     if (CmdAllModKey == keyCmdAllModKey) {
0479         return;
0480     }
0481     CmdAllModKey = keyCmdAllModKey;
0482     Q_EMIT keyCmdAllModKeyChanged();
0483 }
0484 
0485 void Options::setCondensedTitle(bool condensedTitle)
0486 {
0487     if (condensed_title == condensedTitle) {
0488         return;
0489     }
0490     condensed_title = condensedTitle;
0491     Q_EMIT condensedTitleChanged();
0492 }
0493 
0494 void Options::setElectricBorderMaximize(bool electricBorderMaximize)
0495 {
0496     if (electric_border_maximize == electricBorderMaximize) {
0497         return;
0498     }
0499     electric_border_maximize = electricBorderMaximize;
0500     Q_EMIT electricBorderMaximizeChanged();
0501 }
0502 
0503 void Options::setElectricBorderTiling(bool electricBorderTiling)
0504 {
0505     if (electric_border_tiling == electricBorderTiling) {
0506         return;
0507     }
0508     electric_border_tiling = electricBorderTiling;
0509     Q_EMIT electricBorderTilingChanged();
0510 }
0511 
0512 void Options::setElectricBorderCornerRatio(float electricBorderCornerRatio)
0513 {
0514     if (electric_border_corner_ratio == electricBorderCornerRatio) {
0515         return;
0516     }
0517     electric_border_corner_ratio = electricBorderCornerRatio;
0518     Q_EMIT electricBorderCornerRatioChanged();
0519 }
0520 
0521 void Options::setBorderlessMaximizedWindows(bool borderlessMaximizedWindows)
0522 {
0523     if (borderless_maximized_windows == borderlessMaximizedWindows) {
0524         return;
0525     }
0526     borderless_maximized_windows = borderlessMaximizedWindows;
0527     Q_EMIT borderlessMaximizedWindowsChanged();
0528 }
0529 
0530 void Options::setKillPingTimeout(int killPingTimeout)
0531 {
0532     if (m_killPingTimeout == killPingTimeout) {
0533         return;
0534     }
0535     m_killPingTimeout = killPingTimeout;
0536     Q_EMIT killPingTimeoutChanged();
0537 }
0538 
0539 void Options::setHideUtilityWindowsForInactive(bool hideUtilityWindowsForInactive)
0540 {
0541     if (m_hideUtilityWindowsForInactive == hideUtilityWindowsForInactive) {
0542         return;
0543     }
0544     m_hideUtilityWindowsForInactive = hideUtilityWindowsForInactive;
0545     Q_EMIT hideUtilityWindowsForInactiveChanged();
0546 }
0547 
0548 void Options::setCompositingMode(int compositingMode)
0549 {
0550     if (m_compositingMode == static_cast<CompositingType>(compositingMode)) {
0551         return;
0552     }
0553     m_compositingMode = static_cast<CompositingType>(compositingMode);
0554     Q_EMIT compositingModeChanged();
0555 }
0556 
0557 void Options::setUseCompositing(bool useCompositing)
0558 {
0559     if (m_useCompositing == useCompositing) {
0560         return;
0561     }
0562     m_useCompositing = useCompositing;
0563     Q_EMIT useCompositingChanged();
0564 }
0565 
0566 void Options::setHiddenPreviews(int hiddenPreviews)
0567 {
0568     if (m_hiddenPreviews == static_cast<HiddenPreviews>(hiddenPreviews)) {
0569         return;
0570     }
0571     m_hiddenPreviews = static_cast<HiddenPreviews>(hiddenPreviews);
0572     Q_EMIT hiddenPreviewsChanged();
0573 }
0574 
0575 void Options::setGlSmoothScale(int glSmoothScale)
0576 {
0577     if (m_glSmoothScale == glSmoothScale) {
0578         return;
0579     }
0580     m_glSmoothScale = glSmoothScale;
0581     Q_EMIT glSmoothScaleChanged();
0582 }
0583 
0584 void Options::setGlStrictBinding(bool glStrictBinding)
0585 {
0586     if (m_glStrictBinding == glStrictBinding) {
0587         return;
0588     }
0589     m_glStrictBinding = glStrictBinding;
0590     Q_EMIT glStrictBindingChanged();
0591 }
0592 
0593 void Options::setGlStrictBindingFollowsDriver(bool glStrictBindingFollowsDriver)
0594 {
0595     if (m_glStrictBindingFollowsDriver == glStrictBindingFollowsDriver) {
0596         return;
0597     }
0598     m_glStrictBindingFollowsDriver = glStrictBindingFollowsDriver;
0599     Q_EMIT glStrictBindingFollowsDriverChanged();
0600 }
0601 
0602 void Options::setWindowsBlockCompositing(bool value)
0603 {
0604     if (m_windowsBlockCompositing == value) {
0605         return;
0606     }
0607     m_windowsBlockCompositing = value;
0608     Q_EMIT windowsBlockCompositingChanged();
0609 }
0610 
0611 void Options::setGlPreferBufferSwap(char glPreferBufferSwap)
0612 {
0613     if (m_glPreferBufferSwap == (GlSwapStrategy)glPreferBufferSwap) {
0614         return;
0615     }
0616     m_glPreferBufferSwap = (GlSwapStrategy)glPreferBufferSwap;
0617     Q_EMIT glPreferBufferSwapChanged();
0618 }
0619 
0620 bool Options::allowTearing() const
0621 {
0622     return m_allowTearing;
0623 }
0624 
0625 void Options::setAllowTearing(bool allow)
0626 {
0627     if (allow != m_allowTearing) {
0628         m_allowTearing = allow;
0629         Q_EMIT allowTearingChanged();
0630     }
0631 }
0632 
0633 void Options::setGlPlatformInterface(OpenGLPlatformInterface interface)
0634 {
0635     // check environment variable
0636     const QByteArray envOpenGLInterface(qgetenv("KWIN_OPENGL_INTERFACE"));
0637     if (!envOpenGLInterface.isEmpty()) {
0638         if (qstrcmp(envOpenGLInterface, "egl") == 0) {
0639             qCDebug(KWIN_CORE) << "Forcing EGL native interface through environment variable";
0640             interface = EglPlatformInterface;
0641         } else if (qstrcmp(envOpenGLInterface, "glx") == 0) {
0642             qCDebug(KWIN_CORE) << "Forcing GLX native interface through environment variable";
0643             interface = GlxPlatformInterface;
0644         }
0645     }
0646     if (kwinApp()->shouldUseWaylandForCompositing() && interface == GlxPlatformInterface) {
0647         // Glx is impossible on Wayland, enforce egl
0648         qCDebug(KWIN_CORE) << "Forcing EGL native interface for Wayland mode";
0649         interface = EglPlatformInterface;
0650     }
0651 #if !HAVE_GLX
0652     qCDebug(KWIN_CORE) << "Forcing EGL native interface as compiled without GLX support";
0653     interface = EglPlatformInterface;
0654 #endif
0655     if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) {
0656         qCDebug(KWIN_CORE) << "Forcing EGL native interface as Qt uses OpenGL ES";
0657         interface = EglPlatformInterface;
0658     } else if (qstrcmp(qgetenv("KWIN_COMPOSE"), "O2ES") == 0) {
0659         qCDebug(KWIN_CORE) << "Forcing EGL native interface as OpenGL ES requested through KWIN_COMPOSE environment variable.";
0660         interface = EglPlatformInterface;
0661     }
0662 
0663     if (m_glPlatformInterface == interface) {
0664         return;
0665     }
0666     m_glPlatformInterface = interface;
0667     Q_EMIT glPlatformInterfaceChanged();
0668 }
0669 
0670 void Options::reparseConfiguration()
0671 {
0672     m_settings->config()->reparseConfiguration();
0673 }
0674 
0675 void Options::updateSettings()
0676 {
0677     loadConfig();
0678 
0679     Q_EMIT configChanged();
0680 }
0681 
0682 void Options::loadConfig()
0683 {
0684     m_settings->load();
0685 
0686     syncFromKcfgc();
0687 
0688     // Electric borders
0689     KConfigGroup config(m_settings->config(), QStringLiteral("Windows"));
0690     OpTitlebarDblClick = windowOperation(config.readEntry("TitlebarDoubleClickCommand", "Maximize"), true);
0691     setOperationMaxButtonLeftClick(windowOperation(config.readEntry("MaximizeButtonLeftClickCommand", "Maximize"), true));
0692     setOperationMaxButtonMiddleClick(windowOperation(config.readEntry("MaximizeButtonMiddleClickCommand", "Maximize (vertical only)"), true));
0693     setOperationMaxButtonRightClick(windowOperation(config.readEntry("MaximizeButtonRightClickCommand", "Maximize (horizontal only)"), true));
0694 
0695     // Mouse bindings
0696     config = KConfigGroup(m_settings->config(), QStringLiteral("MouseBindings"));
0697     // TODO: add properties for missing options
0698     CmdTitlebarWheel = mouseWheelCommand(config.readEntry("CommandTitlebarWheel", "Nothing"));
0699     CmdAllModKey = (config.readEntry("CommandAllKey", "Meta") == QStringLiteral("Meta")) ? Qt::Key_Meta : Qt::Key_Alt;
0700     CmdAllWheel = mouseWheelCommand(config.readEntry("CommandAllWheel", "Nothing"));
0701     setCommandActiveTitlebar1(mouseCommand(config.readEntry("CommandActiveTitlebar1", "Raise"), true));
0702     setCommandActiveTitlebar2(mouseCommand(config.readEntry("CommandActiveTitlebar2", "Nothing"), true));
0703     setCommandActiveTitlebar3(mouseCommand(config.readEntry("CommandActiveTitlebar3", "Operations menu"), true));
0704     setCommandInactiveTitlebar1(mouseCommand(config.readEntry("CommandInactiveTitlebar1", "Activate and raise"), true));
0705     setCommandInactiveTitlebar2(mouseCommand(config.readEntry("CommandInactiveTitlebar2", "Nothing"), true));
0706     setCommandInactiveTitlebar3(mouseCommand(config.readEntry("CommandInactiveTitlebar3", "Operations menu"), true));
0707     setCommandWindow1(mouseCommand(config.readEntry("CommandWindow1", "Activate, raise and pass click"), false));
0708     setCommandWindow2(mouseCommand(config.readEntry("CommandWindow2", "Activate and pass click"), false));
0709     setCommandWindow3(mouseCommand(config.readEntry("CommandWindow3", "Activate and pass click"), false));
0710     setCommandWindowWheel(mouseCommand(config.readEntry("CommandWindowWheel", "Scroll"), false));
0711     setCommandAll1(mouseCommand(config.readEntry("CommandAll1", "Move"), false));
0712     setCommandAll2(mouseCommand(config.readEntry("CommandAll2", "Toggle raise and lower"), false));
0713     setCommandAll3(mouseCommand(config.readEntry("CommandAll3", "Resize"), false));
0714 
0715     // Modifier Only Shortcuts
0716     config = KConfigGroup(m_settings->config(), QStringLiteral("ModifierOnlyShortcuts"));
0717     m_modifierOnlyShortcuts.clear();
0718     if (config.hasKey("Shift")) {
0719         m_modifierOnlyShortcuts.insert(Qt::ShiftModifier, config.readEntry("Shift", QStringList()));
0720     }
0721     if (config.hasKey("Control")) {
0722         m_modifierOnlyShortcuts.insert(Qt::ControlModifier, config.readEntry("Control", QStringList()));
0723     }
0724     if (config.hasKey("Alt")) {
0725         m_modifierOnlyShortcuts.insert(Qt::AltModifier, config.readEntry("Alt", QStringList()));
0726     }
0727     m_modifierOnlyShortcuts.insert(Qt::MetaModifier, config.readEntry("Meta", QStringList{QStringLiteral("org.kde.plasmashell"), QStringLiteral("/PlasmaShell"), QStringLiteral("org.kde.PlasmaShell"), QStringLiteral("activateLauncherMenu")}));
0728 
0729     // Compositing
0730     config = KConfigGroup(m_settings->config(), QStringLiteral("Compositing"));
0731     bool useCompositing = false;
0732     CompositingType compositingMode = NoCompositing;
0733     QString compositingBackend = config.readEntry("Backend", "OpenGL");
0734     if (compositingBackend == "QPainter") {
0735         compositingMode = QPainterCompositing;
0736     } else {
0737         compositingMode = OpenGLCompositing;
0738     }
0739 
0740     if (const char *c = getenv("KWIN_COMPOSE")) {
0741         switch (c[0]) {
0742         case 'O':
0743             qCDebug(KWIN_CORE) << "Compositing forced to OpenGL mode by environment variable";
0744             compositingMode = OpenGLCompositing;
0745             useCompositing = true;
0746             break;
0747         case 'Q':
0748             qCDebug(KWIN_CORE) << "Compositing forced to QPainter mode by environment variable";
0749             compositingMode = QPainterCompositing;
0750             useCompositing = true;
0751             break;
0752         case 'N':
0753             if (getenv("KDE_FAILSAFE")) {
0754                 qCDebug(KWIN_CORE) << "Compositing disabled forcefully by KDE failsafe mode";
0755             } else {
0756                 qCDebug(KWIN_CORE) << "Compositing disabled forcefully by environment variable";
0757             }
0758             compositingMode = NoCompositing;
0759             break;
0760         default:
0761             qCDebug(KWIN_CORE) << "Unknown KWIN_COMPOSE mode set, ignoring";
0762             break;
0763         }
0764     }
0765     setCompositingMode(compositingMode);
0766     setUseCompositing(useCompositing || config.readEntry("Enabled", Options::defaultUseCompositing()));
0767 
0768     setGlSmoothScale(std::clamp(config.readEntry("GLTextureFilter", Options::defaultGlSmoothScale()), -1, 2));
0769     setGlStrictBindingFollowsDriver(!config.hasKey("GLStrictBinding"));
0770     if (!isGlStrictBindingFollowsDriver()) {
0771         setGlStrictBinding(config.readEntry("GLStrictBinding", Options::defaultGlStrictBinding()));
0772     }
0773 
0774     char c = 0;
0775     const QString s = config.readEntry("GLPreferBufferSwap", QString(QLatin1Char(Options::defaultGlPreferBufferSwap())));
0776     if (!s.isEmpty()) {
0777         c = s.at(0).toLatin1();
0778     }
0779     if (c != 'a' && c != 'c' && c != 'p' && c != 'e') {
0780         c = Options::defaultGlPreferBufferSwap();
0781     }
0782     setGlPreferBufferSwap(c);
0783 
0784     HiddenPreviews previews = Options::defaultHiddenPreviews();
0785     // 4 - off, 5 - shown, 6 - always, other are old values
0786     int hps = config.readEntry("HiddenPreviews", 5);
0787     if (hps == 4) {
0788         previews = HiddenPreviewsNever;
0789     } else if (hps == 5) {
0790         previews = HiddenPreviewsShown;
0791     } else if (hps == 6) {
0792         previews = HiddenPreviewsAlways;
0793     }
0794     setHiddenPreviews(previews);
0795 
0796     auto interfaceToKey = [](OpenGLPlatformInterface interface) {
0797         switch (interface) {
0798         case GlxPlatformInterface:
0799             return QStringLiteral("glx");
0800         case EglPlatformInterface:
0801             return QStringLiteral("egl");
0802         default:
0803             return QString();
0804         }
0805     };
0806     auto keyToInterface = [](const QString &key) {
0807         if (key == QStringLiteral("glx")) {
0808             return GlxPlatformInterface;
0809         } else if (key == QStringLiteral("egl")) {
0810             return EglPlatformInterface;
0811         }
0812         return defaultGlPlatformInterface();
0813     };
0814     setGlPlatformInterface(keyToInterface(config.readEntry("GLPlatformInterface", interfaceToKey(m_glPlatformInterface))));
0815 }
0816 
0817 void Options::syncFromKcfgc()
0818 {
0819     setCondensedTitle(m_settings->condensedTitle());
0820     setFocusPolicy(m_settings->focusPolicy());
0821     setNextFocusPrefersMouse(m_settings->nextFocusPrefersMouse());
0822     setSeparateScreenFocus(m_settings->separateScreenFocus());
0823     setActiveMouseScreen(m_settings->activeMouseScreen());
0824     setRollOverDesktops(m_settings->rollOverDesktops());
0825     setFocusStealingPreventionLevel(m_settings->focusStealingPreventionLevel());
0826     setActivationDesktopPolicy(m_settings->activationDesktopPolicy());
0827     setXwaylandCrashPolicy(m_settings->xwaylandCrashPolicy());
0828     setXwaylandMaxCrashCount(m_settings->xwaylandMaxCrashCount());
0829     setXwaylandEavesdrops(XwaylandEavesdropsMode(m_settings->xwaylandEavesdrops()));
0830     setPlacement(m_settings->placement());
0831     setAutoRaise(m_settings->autoRaise());
0832     setAutoRaiseInterval(m_settings->autoRaiseInterval());
0833     setDelayFocusInterval(m_settings->delayFocusInterval());
0834     setShadeHover(m_settings->shadeHover());
0835     setShadeHoverInterval(m_settings->shadeHoverInterval());
0836     setClickRaise(m_settings->clickRaise());
0837     setBorderSnapZone(m_settings->borderSnapZone());
0838     setWindowSnapZone(m_settings->windowSnapZone());
0839     setCenterSnapZone(m_settings->centerSnapZone());
0840     setSnapOnlyWhenOverlapping(m_settings->snapOnlyWhenOverlapping());
0841     setKillPingTimeout(m_settings->killPingTimeout());
0842     setHideUtilityWindowsForInactive(m_settings->hideUtilityWindowsForInactive());
0843     setBorderlessMaximizedWindows(m_settings->borderlessMaximizedWindows());
0844     setElectricBorderMaximize(m_settings->electricBorderMaximize());
0845     setElectricBorderTiling(m_settings->electricBorderTiling());
0846     setElectricBorderCornerRatio(m_settings->electricBorderCornerRatio());
0847     setWindowsBlockCompositing(m_settings->windowsBlockCompositing());
0848     setAllowTearing(m_settings->allowTearing());
0849 }
0850 
0851 // restricted should be true for operations that the user may not be able to repeat
0852 // if the window is moved out of the workspace (e.g. if the user moves a window
0853 // by the titlebar, and moves it too high beneath Kicker at the top edge, they
0854 // may not be able to move it back, unless they know about Meta+LMB)
0855 Options::WindowOperation Options::windowOperation(const QString &name, bool restricted)
0856 {
0857     if (name == QStringLiteral("Move")) {
0858         return restricted ? MoveOp : UnrestrictedMoveOp;
0859     } else if (name == QStringLiteral("Resize")) {
0860         return restricted ? ResizeOp : UnrestrictedResizeOp;
0861     } else if (name == QStringLiteral("Maximize")) {
0862         return MaximizeOp;
0863     } else if (name == QStringLiteral("Minimize")) {
0864         return MinimizeOp;
0865     } else if (name == QStringLiteral("Close")) {
0866         return CloseOp;
0867     } else if (name == QStringLiteral("OnAllDesktops")) {
0868         return OnAllDesktopsOp;
0869     } else if (name == QStringLiteral("Shade")) {
0870         return ShadeOp;
0871     } else if (name == QStringLiteral("Operations")) {
0872         return OperationsOp;
0873     } else if (name == QStringLiteral("Maximize (vertical only)")) {
0874         return VMaximizeOp;
0875     } else if (name == QStringLiteral("Maximize (horizontal only)")) {
0876         return HMaximizeOp;
0877     } else if (name == QStringLiteral("Lower")) {
0878         return LowerOp;
0879     }
0880     return NoOp;
0881 }
0882 
0883 Options::MouseCommand Options::mouseCommand(const QString &name, bool restricted)
0884 {
0885     QString lowerName = name.toLower();
0886     if (lowerName == QStringLiteral("raise")) {
0887         return MouseRaise;
0888     }
0889     if (lowerName == QStringLiteral("lower")) {
0890         return MouseLower;
0891     }
0892     if (lowerName == QStringLiteral("operations menu")) {
0893         return MouseOperationsMenu;
0894     }
0895     if (lowerName == QStringLiteral("toggle raise and lower")) {
0896         return MouseToggleRaiseAndLower;
0897     }
0898     if (lowerName == QStringLiteral("activate and raise")) {
0899         return MouseActivateAndRaise;
0900     }
0901     if (lowerName == QStringLiteral("activate and lower")) {
0902         return MouseActivateAndLower;
0903     }
0904     if (lowerName == QStringLiteral("activate")) {
0905         return MouseActivate;
0906     }
0907     if (lowerName == QStringLiteral("activate, raise and pass click")) {
0908         return MouseActivateRaiseAndPassClick;
0909     }
0910     if (lowerName == QStringLiteral("activate and pass click")) {
0911         return MouseActivateAndPassClick;
0912     }
0913     if (lowerName == QStringLiteral("scroll")) {
0914         return MouseNothing;
0915     }
0916     if (lowerName == QStringLiteral("activate and scroll")) {
0917         return MouseActivateAndPassClick;
0918     }
0919     if (lowerName == QStringLiteral("activate, raise and scroll")) {
0920         return MouseActivateRaiseAndPassClick;
0921     }
0922     if (lowerName == QStringLiteral("activate, raise and move")) {
0923         return restricted ? MouseActivateRaiseAndMove : MouseActivateRaiseAndUnrestrictedMove;
0924     }
0925     if (lowerName == QStringLiteral("move")) {
0926         return restricted ? MouseMove : MouseUnrestrictedMove;
0927     }
0928     if (lowerName == QStringLiteral("resize")) {
0929         return restricted ? MouseResize : MouseUnrestrictedResize;
0930     }
0931     if (lowerName == QStringLiteral("shade")) {
0932         return MouseShade;
0933     }
0934     if (lowerName == QStringLiteral("minimize")) {
0935         return MouseMinimize;
0936     }
0937     if (lowerName == QStringLiteral("close")) {
0938         return MouseClose;
0939     }
0940     if (lowerName == QStringLiteral("increase opacity")) {
0941         return MouseOpacityMore;
0942     }
0943     if (lowerName == QStringLiteral("decrease opacity")) {
0944         return MouseOpacityLess;
0945     }
0946     if (lowerName == QStringLiteral("nothing")) {
0947         return MouseNothing;
0948     }
0949     return MouseNothing;
0950 }
0951 
0952 Options::MouseWheelCommand Options::mouseWheelCommand(const QString &name)
0953 {
0954     QString lowerName = name.toLower();
0955     if (lowerName == QStringLiteral("raise/lower")) {
0956         return MouseWheelRaiseLower;
0957     }
0958     if (lowerName == QStringLiteral("shade/unshade")) {
0959         return MouseWheelShadeUnshade;
0960     }
0961     if (lowerName == QStringLiteral("maximize/restore")) {
0962         return MouseWheelMaximizeRestore;
0963     }
0964     if (lowerName == QStringLiteral("above/below")) {
0965         return MouseWheelAboveBelow;
0966     }
0967     if (lowerName == QStringLiteral("previous/next desktop")) {
0968         return MouseWheelPreviousNextDesktop;
0969     }
0970     if (lowerName == QStringLiteral("change opacity")) {
0971         return MouseWheelChangeOpacity;
0972     }
0973     if (lowerName == QStringLiteral("nothing")) {
0974         return MouseWheelNothing;
0975     }
0976     return MouseWheelNothing;
0977 }
0978 
0979 bool Options::condensedTitle() const
0980 {
0981     return condensed_title;
0982 }
0983 
0984 Options::MouseCommand Options::wheelToMouseCommand(MouseWheelCommand com, int delta) const
0985 {
0986     switch (com) {
0987     case MouseWheelRaiseLower:
0988         return delta > 0 ? MouseRaise : MouseLower;
0989     case MouseWheelShadeUnshade:
0990         return delta > 0 ? MouseSetShade : MouseUnsetShade;
0991     case MouseWheelMaximizeRestore:
0992         return delta > 0 ? MouseMaximize : MouseRestore;
0993     case MouseWheelAboveBelow:
0994         return delta > 0 ? MouseAbove : MouseBelow;
0995     case MouseWheelPreviousNextDesktop:
0996         return delta > 0 ? MousePreviousDesktop : MouseNextDesktop;
0997     case MouseWheelChangeOpacity:
0998         return delta > 0 ? MouseOpacityMore : MouseOpacityLess;
0999     default:
1000         return MouseNothing;
1001     }
1002 }
1003 #endif
1004 
1005 double Options::animationTimeFactor() const
1006 {
1007 #ifndef KCMRULES
1008     return m_settings->animationDurationFactor();
1009 #else
1010     return 0;
1011 #endif
1012 }
1013 
1014 Options::WindowOperation Options::operationMaxButtonClick(Qt::MouseButtons button) const
1015 {
1016     return button == Qt::RightButton ? opMaxButtonRightClick : button == Qt::MiddleButton ? opMaxButtonMiddleClick
1017                                                                                           : opMaxButtonLeftClick;
1018 }
1019 
1020 QStringList Options::modifierOnlyDBusShortcut(Qt::KeyboardModifier mod) const
1021 {
1022     return m_modifierOnlyShortcuts.value(mod);
1023 }
1024 
1025 bool Options::isUseCompositing() const
1026 {
1027     return m_useCompositing;
1028 }
1029 
1030 } // namespace
1031 
1032 #include "moc_options.cpp"