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