1/********************************************************************
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
6Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
7Copyright (C) 2012 Martin Gräßlin <m.graesslin@kde.org>
8
9This program is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2 of the License, or
12(at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program. If not, see <http://www.gnu.org/licenses/>.
21*********************************************************************/
22
23#include "options.h"
24#include "config-kwin.h"
25
26#ifndef KCMRULES
27
28#include <QPalette>
29#include <QPixmap>
30#include <QProcess>
31#include <kapplication.h>
32#include <kconfig.h>
33#include <kglobal.h>
34#include <kglobalsettings.h>
35#include <klocale.h>
36
37#include "client.h"
38#include "compositingprefs.h"
39#include "settings.h"
40#include "xcbutils.h"
41#include <kwinglplatform.h>
42
43#include <X11/extensions/Xrandr.h>
44#ifndef KWIN_HAVE_OPENGLES
45#ifndef KWIN_NO_XF86VM
46#include <X11/extensions/xf86vmode.h>
47#endif
48#endif
49
50#endif //KCMRULES
51
52namespace KWin
53{
54
55#ifndef KCMRULES
56
57int currentRefreshRate()
58{
59 int rate = -1;
60 if (options->refreshRate() > 0) // use manually configured refresh rate
61 rate = options->refreshRate();
62#ifndef KWIN_HAVE_OPENGLES
63 else if (GLPlatform::instance()->driver() == Driver_NVidia) {
64#ifndef KWIN_NO_XF86VM
65 int major, event, error;
66 if (XQueryExtension(display(), "XFree86-VidModeExtension", &major, &event, &error)) {
67 XF86VidModeModeLine modeline;
68 int dotclock, vtotal;
69 if (XF86VidModeGetModeLine(display(), 0, &dotclock, &modeline)) {
70 vtotal = modeline.vtotal;
71 if (modeline.flags & 0x0010) // V_INTERLACE
72 dotclock *= 2;
73 if (modeline.flags & 0x0020) // V_DBLSCAN
74 vtotal *= 2;
75 if (modeline.htotal*vtotal) // BUG 313996
76 rate = 1000*dotclock/(modeline.htotal*vtotal); // WTF was wikipedia 1998 when I nedded it?
77 kDebug(1212) << "Vertical Refresh Rate (as detected by XF86VM): " << rate << "Hz";
78 }
79 }
80 if (rate < 1)
81#endif
82 { // modeline approach failed
83 QProcess nvidia_settings;
84 QStringList env = QProcess::systemEnvironment();
85 env << "LC_ALL=C";
86 nvidia_settings.setEnvironment(env);
87 nvidia_settings.start("nvidia-settings", QStringList() << "-t" << "-q" << "RefreshRate", QIODevice::ReadOnly);
88 nvidia_settings.waitForFinished();
89 if (nvidia_settings.exitStatus() == QProcess::NormalExit) {
90 QString reply = QString::fromLocal8Bit(nvidia_settings.readAllStandardOutput()).split(' ').first();
91 bool ok;
92 float frate = QLocale::c().toFloat(reply, &ok);
93 if (!ok)
94 rate = -1;
95 else
96 rate = qRound(frate);
97 kDebug(1212) << "Vertical Refresh Rate (as detected by nvidia-settings): " << rate << "Hz";
98 }
99 }
100 }
101#endif
102 else if (Xcb::Extensions::self()->isRandrAvailable()) {
103 XRRScreenConfiguration *config = XRRGetScreenInfo(display(), rootWindow());
104 rate = XRRConfigCurrentRate(config);
105 XRRFreeScreenConfigInfo(config);
106 }
107
108 // 0Hz or less is invalid, so we fallback to a default rate
109 if (rate <= 0)
110 rate = 60;
111 // QTimer gives us 1msec (1000Hz) at best, so we ignore anything higher;
112 // however, additional throttling prevents very high rates from taking place anyway
113 else if (rate > 1000)
114 rate = 1000;
115 kDebug(1212) << "Vertical Refresh rate " << rate << "Hz";
116 return rate;
117}
118
119Options::Options(QObject *parent)
120 : QObject(parent)
121 , m_settings(new Settings(KGlobal::config()))
122 , m_focusPolicy(ClickToFocus)
123 , m_nextFocusPrefersMouse(false)
124 , m_clickRaise(false)
125 , m_autoRaise(false)
126 , m_autoRaiseInterval(0)
127 , m_delayFocusInterval(0)
128 , m_shadeHover(false)
129 , m_shadeHoverInterval(0)
130 , m_separateScreenFocus(false)
131 , m_placement(Placement::NoPlacement)
132 , m_borderSnapZone(0)
133 , m_windowSnapZone(0)
134 , m_centerSnapZone(0)
135 , m_snapOnlyWhenOverlapping(false)
136 , m_showDesktopIsMinimizeAll(false)
137 , m_rollOverDesktops(false)
138 , m_focusStealingPreventionLevel(0)
139 , m_legacyFullscreenSupport(false)
140 , m_killPingTimeout(0)
141 , m_hideUtilityWindowsForInactive(false)
142 , m_inactiveTabsSkipTaskbar(false)
143 , m_autogroupSimilarWindows(false)
144 , m_autogroupInForeground(false)
145 , m_compositingMode(Options::defaultCompositingMode())
146 , m_useCompositing(Options::defaultUseCompositing())
147 , m_compositingInitialized(Options::defaultCompositingInitialized())
148 , m_hiddenPreviews(Options::defaultHiddenPreviews())
149 , m_unredirectFullscreen(Options::defaultUnredirectFullscreen())
150 , m_glSmoothScale(Options::defaultGlSmoothScale())
151 , m_colorCorrected(Options::defaultColorCorrected())
152 , m_xrenderSmoothScale(Options::defaultXrenderSmoothScale())
153 , m_maxFpsInterval(Options::defaultMaxFpsInterval())
154 , m_refreshRate(Options::defaultRefreshRate())
155 , m_vBlankTime(Options::defaultVBlankTime())
156 , m_glDirect(Options::defaultGlDirect())
157 , m_glStrictBinding(Options::defaultGlStrictBinding())
158 , m_glStrictBindingFollowsDriver(Options::defaultGlStrictBindingFollowsDriver())
159 , m_glLegacy(Options::defaultGlLegacy())
160 , m_glCoreProfile(Options::defaultGLCoreProfile())
161 , m_glPreferBufferSwap(Options::defaultGlPreferBufferSwap())
162 , OpTitlebarDblClick(Options::defaultOperationTitlebarDblClick())
163 , CmdActiveTitlebar1(Options::defaultCommandActiveTitlebar1())
164 , CmdActiveTitlebar2(Options::defaultCommandActiveTitlebar2())
165 , CmdActiveTitlebar3(Options::defaultCommandActiveTitlebar3())
166 , CmdInactiveTitlebar1(Options::defaultCommandInactiveTitlebar1())
167 , CmdInactiveTitlebar2(Options::defaultCommandInactiveTitlebar2())
168 , CmdInactiveTitlebar3(Options::defaultCommandInactiveTitlebar3())
169 , CmdTitlebarWheel(Options::defaultCommandTitlebarWheel())
170 , CmdWindow1(Options::defaultCommandWindow1())
171 , CmdWindow2(Options::defaultCommandWindow2())
172 , CmdWindow3(Options::defaultCommandWindow3())
173 , CmdWindowWheel(Options::defaultCommandWindowWheel())
174 , CmdAll1(Options::defaultCommandAll1())
175 , CmdAll2(Options::defaultCommandAll2())
176 , CmdAll3(Options::defaultCommandAll3())
177 , CmdAllWheel(Options::defaultCommandAllWheel())
178 , CmdAllModKey(Options::defaultKeyCmdAllModKey())
179 , electric_border_maximize(false)
180 , electric_border_tiling(false)
181 , electric_border_corner_ratio(0.0)
182 , borderless_maximized_windows(false)
183 , show_geometry_tip(false)
184 , condensed_title(false)
185 , animationSpeed(Options::defaultAnimationSpeed())
186{
187 m_settings->setDefaults();
188 syncFromKcfgc();
189}
190
191Options::~Options()
192{
193}
194
195void Options::setFocusPolicy(FocusPolicy focusPolicy)
196{
197 if (m_focusPolicy == focusPolicy) {
198 return;
199 }
200 m_focusPolicy = focusPolicy;
201 emit focusPolicyChanged();
202 if (m_focusPolicy == ClickToFocus) {
203 setAutoRaise(false);
204 setAutoRaiseInterval(0);
205 setDelayFocusInterval(0);
206 }
207}
208
209void Options::setNextFocusPrefersMouse(bool nextFocusPrefersMouse)
210{
211 if (m_nextFocusPrefersMouse == nextFocusPrefersMouse) {
212 return;
213 }
214 m_nextFocusPrefersMouse = nextFocusPrefersMouse;
215 emit nextFocusPrefersMouseChanged();
216}
217
218void Options::setClickRaise(bool clickRaise)
219{
220 if (m_autoRaise) {
221 // important: autoRaise implies ClickRaise
222 clickRaise = true;
223 }
224 if (m_clickRaise == clickRaise) {
225 return;
226 }
227 m_clickRaise = clickRaise;
228 emit clickRaiseChanged();
229}
230
231void Options::setAutoRaise(bool autoRaise)
232{
233 if (m_focusPolicy == ClickToFocus) {
234 autoRaise = false;
235 }
236 if (m_autoRaise == autoRaise) {
237 return;
238 }
239 m_autoRaise = autoRaise;
240 if (m_autoRaise) {
241 // important: autoRaise implies ClickRaise
242 setClickRaise(true);
243 }
244 emit autoRaiseChanged();
245}
246
247void Options::setAutoRaiseInterval(int autoRaiseInterval)
248{
249 if (m_focusPolicy == ClickToFocus) {
250 autoRaiseInterval = 0;
251 }
252 if (m_autoRaiseInterval == autoRaiseInterval) {
253 return;
254 }
255 m_autoRaiseInterval = autoRaiseInterval;
256 emit autoRaiseIntervalChanged();
257}
258
259void Options::setDelayFocusInterval(int delayFocusInterval)
260{
261 if (m_focusPolicy == ClickToFocus) {
262 delayFocusInterval = 0;
263 }
264 if (m_delayFocusInterval == delayFocusInterval) {
265 return;
266 }
267 m_delayFocusInterval = delayFocusInterval;
268 emit delayFocusIntervalChanged();
269}
270
271void Options::setShadeHover(bool shadeHover)
272{
273 if (m_shadeHover == shadeHover) {
274 return;
275 }
276 m_shadeHover = shadeHover;
277 emit shadeHoverChanged();
278}
279
280void Options::setShadeHoverInterval(int shadeHoverInterval)
281{
282 if (m_shadeHoverInterval == shadeHoverInterval) {
283 return;
284 }
285 m_shadeHoverInterval = shadeHoverInterval;
286 emit shadeHoverIntervalChanged();
287}
288
289void Options::setSeparateScreenFocus(bool separateScreenFocus)
290{
291 if (m_separateScreenFocus == separateScreenFocus) {
292 return;
293 }
294 m_separateScreenFocus = separateScreenFocus;
295 emit separateScreenFocusChanged(m_separateScreenFocus);
296}
297
298void Options::setPlacement(int placement)
299{
300 if (m_placement == static_cast<Placement::Policy>(placement)) {
301 return;
302 }
303 m_placement = static_cast<Placement::Policy>(placement);
304 emit placementChanged();
305}
306
307void Options::setBorderSnapZone(int borderSnapZone)
308{
309 if (m_borderSnapZone == borderSnapZone) {
310 return;
311 }
312 m_borderSnapZone = borderSnapZone;
313 emit borderSnapZoneChanged();
314}
315
316void Options::setWindowSnapZone(int windowSnapZone)
317{
318 if (m_windowSnapZone == windowSnapZone) {
319 return;
320 }
321 m_windowSnapZone = windowSnapZone;
322 emit windowSnapZoneChanged();
323}
324
325void Options::setCenterSnapZone(int centerSnapZone)
326{
327 if (m_centerSnapZone == centerSnapZone) {
328 return;
329 }
330 m_centerSnapZone = centerSnapZone;
331 emit centerSnapZoneChanged();
332}
333
334void Options::setSnapOnlyWhenOverlapping(bool snapOnlyWhenOverlapping)
335{
336 if (m_snapOnlyWhenOverlapping == snapOnlyWhenOverlapping) {
337 return;
338 }
339 m_snapOnlyWhenOverlapping = snapOnlyWhenOverlapping;
340 emit snapOnlyWhenOverlappingChanged();
341}
342
343void Options::setShowDesktopIsMinimizeAll(bool showDesktopIsMinimizeAll)
344{
345 if (m_showDesktopIsMinimizeAll == showDesktopIsMinimizeAll) {
346 return;
347 }
348 m_showDesktopIsMinimizeAll = showDesktopIsMinimizeAll;
349 emit showDesktopIsMinimizeAllChanged();
350}
351
352void Options::setRollOverDesktops(bool rollOverDesktops)
353{
354 if (m_rollOverDesktops == rollOverDesktops) {
355 return;
356 }
357 m_rollOverDesktops = rollOverDesktops;
358 emit rollOverDesktopsChanged(m_rollOverDesktops);
359}
360
361void Options::setFocusStealingPreventionLevel(int focusStealingPreventionLevel)
362{
363 if (!focusPolicyIsReasonable()) {
364 focusStealingPreventionLevel = 0;
365 }
366 if (m_focusStealingPreventionLevel == focusStealingPreventionLevel) {
367 return;
368 }
369 m_focusStealingPreventionLevel = qMax(0, qMin(4, focusStealingPreventionLevel));
370 emit focusStealingPreventionLevelChanged();
371}
372
373void Options::setLegacyFullscreenSupport(bool legacyFullscreenSupport)
374{
375 if (m_legacyFullscreenSupport == legacyFullscreenSupport) {
376 return;
377 }
378 m_legacyFullscreenSupport = legacyFullscreenSupport;
379 emit legacyFullscreenSupportChanged();
380}
381
382void Options::setOperationTitlebarDblClick(WindowOperation operationTitlebarDblClick)
383{
384 if (OpTitlebarDblClick == operationTitlebarDblClick) {
385 return;
386 }
387 OpTitlebarDblClick = operationTitlebarDblClick;
388 emit operationTitlebarDblClickChanged();
389}
390
391void Options::setCommandActiveTitlebar1(MouseCommand commandActiveTitlebar1)
392{
393 if (CmdActiveTitlebar1 == commandActiveTitlebar1) {
394 return;
395 }
396 CmdActiveTitlebar1 = commandActiveTitlebar1;
397 emit commandActiveTitlebar1Changed();
398}
399
400void Options::setCommandActiveTitlebar2(MouseCommand commandActiveTitlebar2)
401{
402 if (CmdActiveTitlebar2 == commandActiveTitlebar2) {
403 return;
404 }
405 CmdActiveTitlebar2 = commandActiveTitlebar2;
406 emit commandActiveTitlebar2Changed();
407}
408
409void Options::setCommandActiveTitlebar3(MouseCommand commandActiveTitlebar3)
410{
411 if (CmdActiveTitlebar3 == commandActiveTitlebar3) {
412 return;
413 }
414 CmdActiveTitlebar3 = commandActiveTitlebar3;
415 emit commandActiveTitlebar3Changed();
416}
417
418void Options::setCommandInactiveTitlebar1(MouseCommand commandInactiveTitlebar1)
419{
420 if (CmdInactiveTitlebar1 == commandInactiveTitlebar1) {
421 return;
422 }
423 CmdInactiveTitlebar1 = commandInactiveTitlebar1;
424 emit commandInactiveTitlebar1Changed();
425}
426
427void Options::setCommandInactiveTitlebar2(MouseCommand commandInactiveTitlebar2)
428{
429 if (CmdInactiveTitlebar2 == commandInactiveTitlebar2) {
430 return;
431 }
432 CmdInactiveTitlebar2 = commandInactiveTitlebar2;
433 emit commandInactiveTitlebar2Changed();
434}
435
436void Options::setCommandInactiveTitlebar3(MouseCommand commandInactiveTitlebar3)
437{
438 if (CmdInactiveTitlebar3 == commandInactiveTitlebar3) {
439 return;
440 }
441 CmdInactiveTitlebar3 = commandInactiveTitlebar3;
442 emit commandInactiveTitlebar3Changed();
443}
444
445void Options::setCommandWindow1(MouseCommand commandWindow1)
446{
447 if (CmdWindow1 == commandWindow1) {
448 return;
449 }
450 CmdWindow1 = commandWindow1;
451 emit commandWindow1Changed();
452}
453
454void Options::setCommandWindow2(MouseCommand commandWindow2)
455{
456 if (CmdWindow2 == commandWindow2) {
457 return;
458 }
459 CmdWindow2 = commandWindow2;
460 emit commandWindow2Changed();
461}
462
463void Options::setCommandWindow3(MouseCommand commandWindow3)
464{
465 if (CmdWindow3 == commandWindow3) {
466 return;
467 }
468 CmdWindow3 = commandWindow3;
469 emit commandWindow3Changed();
470}
471
472void Options::setCommandWindowWheel(MouseCommand commandWindowWheel)
473{
474 if (CmdWindowWheel == commandWindowWheel) {
475 return;
476 }
477 CmdWindowWheel = commandWindowWheel;
478 emit commandWindowWheelChanged();
479}
480
481void Options::setCommandAll1(MouseCommand commandAll1)
482{
483 if (CmdAll1 == commandAll1) {
484 return;
485 }
486 CmdAll1 = commandAll1;
487 emit commandAll1Changed();
488}
489
490void Options::setCommandAll2(MouseCommand commandAll2)
491{
492 if (CmdAll2 == commandAll2) {
493 return;
494 }
495 CmdAll2 = commandAll2;
496 emit commandAll2Changed();
497}
498
499void Options::setCommandAll3(MouseCommand commandAll3)
500{
501 if (CmdAll3 == commandAll3) {
502 return;
503 }
504 CmdAll3 = commandAll3;
505 emit commandAll3Changed();
506}
507
508void Options::setKeyCmdAllModKey(uint keyCmdAllModKey)
509{
510 if (CmdAllModKey == keyCmdAllModKey) {
511 return;
512 }
513 CmdAllModKey = keyCmdAllModKey;
514 emit keyCmdAllModKeyChanged();
515}
516
517void Options::setShowGeometryTip(bool showGeometryTip)
518{
519 if (show_geometry_tip == showGeometryTip) {
520 return;
521 }
522 show_geometry_tip = showGeometryTip;
523 emit showGeometryTipChanged();
524}
525
526void Options::setCondensedTitle(bool condensedTitle)
527{
528 if (condensed_title == condensedTitle) {
529 return;
530 }
531 condensed_title = condensedTitle;
532 emit condensedTitleChanged();
533}
534
535void Options::setElectricBorderMaximize(bool electricBorderMaximize)
536{
537 if (electric_border_maximize == electricBorderMaximize) {
538 return;
539 }
540 electric_border_maximize = electricBorderMaximize;
541 emit electricBorderMaximizeChanged();
542}
543
544void Options::setElectricBorderTiling(bool electricBorderTiling)
545{
546 if (electric_border_tiling == electricBorderTiling) {
547 return;
548 }
549 electric_border_tiling = electricBorderTiling;
550 emit electricBorderTilingChanged();
551}
552
553void Options::setElectricBorderCornerRatio(float electricBorderCornerRatio)
554{
555 if (electric_border_corner_ratio == electricBorderCornerRatio) {
556 return;
557 }
558 electric_border_corner_ratio = electricBorderCornerRatio;
559 emit electricBorderCornerRatioChanged();
560}
561
562void Options::setBorderlessMaximizedWindows(bool borderlessMaximizedWindows)
563{
564 if (borderless_maximized_windows == borderlessMaximizedWindows) {
565 return;
566 }
567 borderless_maximized_windows = borderlessMaximizedWindows;
568 emit borderlessMaximizedWindowsChanged();
569}
570
571void Options::setKillPingTimeout(int killPingTimeout)
572{
573 if (m_killPingTimeout == killPingTimeout) {
574 return;
575 }
576 m_killPingTimeout = killPingTimeout;
577 emit killPingTimeoutChanged();
578}
579
580void Options::setHideUtilityWindowsForInactive(bool hideUtilityWindowsForInactive)
581{
582 if (m_hideUtilityWindowsForInactive == hideUtilityWindowsForInactive) {
583 return;
584 }
585 m_hideUtilityWindowsForInactive = hideUtilityWindowsForInactive;
586 emit hideUtilityWindowsForInactiveChanged();
587}
588
589void Options::setInactiveTabsSkipTaskbar(bool inactiveTabsSkipTaskbar)
590{
591 if (m_inactiveTabsSkipTaskbar == inactiveTabsSkipTaskbar) {
592 return;
593 }
594 m_inactiveTabsSkipTaskbar = inactiveTabsSkipTaskbar;
595 emit inactiveTabsSkipTaskbarChanged();
596}
597
598void Options::setAutogroupSimilarWindows(bool autogroupSimilarWindows)
599{
600 if (m_autogroupSimilarWindows == autogroupSimilarWindows) {
601 return;
602 }
603 m_autogroupSimilarWindows = autogroupSimilarWindows;
604 emit autogroupSimilarWindowsChanged();
605}
606
607void Options::setAutogroupInForeground(bool autogroupInForeground)
608{
609 if (m_autogroupInForeground == autogroupInForeground) {
610 return;
611 }
612 m_autogroupInForeground = autogroupInForeground;
613 emit autogroupInForegroundChanged();
614}
615
616void Options::setCompositingMode(int compositingMode)
617{
618 if (m_compositingMode == static_cast<CompositingType>(compositingMode)) {
619 return;
620 }
621 m_compositingMode = static_cast<CompositingType>(compositingMode);
622 emit compositingModeChanged();
623}
624
625void Options::setUseCompositing(bool useCompositing)
626{
627 if (m_useCompositing == useCompositing) {
628 return;
629 }
630 m_useCompositing = useCompositing;
631 emit useCompositingChanged();
632}
633
634void Options::setCompositingInitialized(bool compositingInitialized)
635{
636 if (m_compositingInitialized == compositingInitialized) {
637 return;
638 }
639 m_compositingInitialized = compositingInitialized;
640 emit compositingInitializedChanged();
641}
642
643void Options::setHiddenPreviews(int hiddenPreviews)
644{
645 if (m_hiddenPreviews == static_cast<HiddenPreviews>(hiddenPreviews)) {
646 return;
647 }
648 m_hiddenPreviews = static_cast<HiddenPreviews>(hiddenPreviews);
649 emit hiddenPreviewsChanged();
650}
651
652void Options::setUnredirectFullscreen(bool unredirectFullscreen)
653{
654 if (GLPlatform::instance()->driver() == Driver_Intel)
655 unredirectFullscreen = false; // bug #252817
656 if (m_unredirectFullscreen == unredirectFullscreen) {
657 return;
658 }
659 if (GLPlatform::instance()->driver() == Driver_Intel) { // write back the value
660 KConfigGroup(KGlobal::config(), "Compositing").writeEntry("UnredirectFullscreen", false);
661 }
662 m_unredirectFullscreen = unredirectFullscreen;
663 emit unredirectFullscreenChanged();
664}
665
666void Options::setGlSmoothScale(int glSmoothScale)
667{
668 if (m_glSmoothScale == glSmoothScale) {
669 return;
670 }
671 m_glSmoothScale = glSmoothScale;
672 emit glSmoothScaleChanged();
673}
674
675void Options::setColorCorrected(bool colorCorrected)
676{
677 if (m_colorCorrected == colorCorrected) {
678 return;
679 }
680 m_colorCorrected = colorCorrected;
681 emit colorCorrectedChanged();
682}
683
684void Options::setXrenderSmoothScale(bool xrenderSmoothScale)
685{
686 if (m_xrenderSmoothScale == xrenderSmoothScale) {
687 return;
688 }
689 m_xrenderSmoothScale = xrenderSmoothScale;
690 emit xrenderSmoothScaleChanged();
691}
692
693void Options::setMaxFpsInterval(qint64 maxFpsInterval)
694{
695 if (m_maxFpsInterval == maxFpsInterval) {
696 return;
697 }
698 m_maxFpsInterval = maxFpsInterval;
699 emit maxFpsIntervalChanged();
700}
701
702void Options::setRefreshRate(uint refreshRate)
703{
704 if (m_refreshRate == refreshRate) {
705 return;
706 }
707 m_refreshRate = refreshRate;
708 emit refreshRateChanged();
709}
710
711void Options::setVBlankTime(qint64 vBlankTime)
712{
713 if (m_vBlankTime == vBlankTime) {
714 return;
715 }
716 m_vBlankTime = vBlankTime;
717 emit vBlankTimeChanged();
718}
719
720void Options::setGlDirect(bool glDirect)
721{
722 if (m_glDirect == glDirect) {
723 return;
724 }
725 m_glDirect = glDirect;
726 emit glDirectChanged();
727}
728
729void Options::setGlStrictBinding(bool glStrictBinding)
730{
731 if (m_glStrictBinding == glStrictBinding) {
732 return;
733 }
734 m_glStrictBinding = glStrictBinding;
735 emit glStrictBindingChanged();
736}
737
738void Options::setGlStrictBindingFollowsDriver(bool glStrictBindingFollowsDriver)
739{
740 if (m_glStrictBindingFollowsDriver == glStrictBindingFollowsDriver) {
741 return;
742 }
743 m_glStrictBindingFollowsDriver = glStrictBindingFollowsDriver;
744 emit glStrictBindingFollowsDriverChanged();
745}
746
747void Options::setGlLegacy(bool glLegacy)
748{
749 if (m_glLegacy == glLegacy) {
750 return;
751 }
752 m_glLegacy = glLegacy;
753 emit glLegacyChanged();
754}
755
756void Options::setGLCoreProfile(bool value)
757{
758 if (m_glCoreProfile == value) {
759 return;
760 }
761 m_glCoreProfile = value;
762 emit glCoreProfileChanged();
763}
764
765void Options::setGlPreferBufferSwap(char glPreferBufferSwap)
766{
767 if (glPreferBufferSwap == 'a') {
768 // buffer cpying is very fast with the nvidia blob
769 // but due to restrictions in DRI2 *incredibly* slow for all MESA drivers
770 // see http://www.x.org/releases/X11R7.7/doc/dri2proto/dri2proto.txt, item 2.5
771 if (GLPlatform::instance()->driver() == Driver_NVidia)
772 glPreferBufferSwap = CopyFrontBuffer;
773 else if (GLPlatform::instance()->driver() != Driver_Unknown) // undetected, finally resolved when context is initialized
774 glPreferBufferSwap = ExtendDamage;
775 }
776 if (m_glPreferBufferSwap == (GlSwapStrategy)glPreferBufferSwap) {
777 return;
778 }
779 m_glPreferBufferSwap = (GlSwapStrategy)glPreferBufferSwap;
780 emit glPreferBufferSwapChanged();
781}
782
783void Options::reparseConfiguration()
784{
785 KGlobal::config()->reparseConfiguration();
786}
787
788unsigned long Options::updateSettings()
789{
790 unsigned long changed = loadConfig();
791 // Read button tooltip animation effect from kdeglobals
792 // Since we want to allow users to enable window decoration tooltips
793 // and not kstyle tooltips and vise-versa, we don't read the
794 // "EffectNoTooltip" setting from kdeglobals.
795
796
797// QToolTip::setGloballyEnabled( d->show_tooltips );
798// KDE4 this probably needs to be done manually in clients
799
800 // Driver-specific config detection
801 setCompositingInitialized(false);
802 reloadCompositingSettings();
803
804 emit configChanged();
805
806 return changed;
807}
808
809unsigned long Options::loadConfig()
810{
811 KSharedConfig::Ptr _config = KGlobal::config();
812 m_settings->readConfig();
813 unsigned long changed = 0;
814 changed |= KDecorationOptions::updateSettings(m_settings->config()); // read decoration settings
815
816 syncFromKcfgc();
817
818 // Electric borders
819 KConfigGroup config(_config, "Windows");
820 OpTitlebarDblClick = windowOperation(config.readEntry("TitlebarDoubleClickCommand", "Maximize"), true);
821 setOpMaxButtonLeftClick(windowOperation(config.readEntry("MaximizeButtonLeftClickCommand", "Maximize"), true));
822 setOpMaxButtonMiddleClick(windowOperation(config.readEntry("MaximizeButtonMiddleClickCommand", "Maximize (vertical only)"), true));
823 setOpMaxButtonRightClick(windowOperation(config.readEntry("MaximizeButtonRightClickCommand", "Maximize (horizontal only)"), true));
824
825 // Mouse bindings
826 config = KConfigGroup(_config, "MouseBindings");
827 // TODO: add properties for missing options
828 CmdTitlebarWheel = mouseWheelCommand(config.readEntry("CommandTitlebarWheel", "Switch to Window Tab to the Left/Right"));
829 CmdAllModKey = (config.readEntry("CommandAllKey", "Alt") == "Meta") ? Qt::Key_Meta : Qt::Key_Alt;
830 CmdAllWheel = mouseWheelCommand(config.readEntry("CommandAllWheel", "Nothing"));
831 setCommandActiveTitlebar1(mouseCommand(config.readEntry("CommandActiveTitlebar1", "Raise"), true));
832 setCommandActiveTitlebar2(mouseCommand(config.readEntry("CommandActiveTitlebar2", "Start Window Tab Drag"), true));
833 setCommandActiveTitlebar3(mouseCommand(config.readEntry("CommandActiveTitlebar3", "Operations menu"), true));
834 setCommandInactiveTitlebar1(mouseCommand(config.readEntry("CommandInactiveTitlebar1", "Activate and raise"), true));
835 setCommandInactiveTitlebar2(mouseCommand(config.readEntry("CommandInactiveTitlebar2", "Start Window Tab Drag"), true));
836 setCommandInactiveTitlebar3(mouseCommand(config.readEntry("CommandInactiveTitlebar3", "Operations menu"), true));
837 setCommandWindow1(mouseCommand(config.readEntry("CommandWindow1", "Activate, raise and pass click"), false));
838 setCommandWindow2(mouseCommand(config.readEntry("CommandWindow2", "Activate and pass click"), false));
839 setCommandWindow3(mouseCommand(config.readEntry("CommandWindow3", "Activate and pass click"), false));
840 setCommandWindowWheel(mouseCommand(config.readEntry("CommandWindowWheel", "Scroll"), false));
841 setCommandAll1(mouseCommand(config.readEntry("CommandAll1", "Move"), false));
842 setCommandAll2(mouseCommand(config.readEntry("CommandAll2", "Toggle raise and lower"), false));
843 setCommandAll3(mouseCommand(config.readEntry("CommandAll3", "Resize"), false));
844
845 // TODO: should they be moved into reloadCompositingSettings?
846 config = KConfigGroup(_config, "Compositing");
847 setMaxFpsInterval(1 * 1000 * 1000 * 1000 / config.readEntry("MaxFPS", Options::defaultMaxFps()));
848 setRefreshRate(config.readEntry("RefreshRate", Options::defaultRefreshRate()));
849 setVBlankTime(config.readEntry("VBlankTime", Options::defaultVBlankTime()) * 1000); // config in micro, value in nano resolution
850
851 return changed;
852}
853
854void Options::syncFromKcfgc()
855{
856 setShowGeometryTip(m_settings->geometryTip());
857 setCondensedTitle(m_settings->condensedTitle());
858 setFocusPolicy(m_settings->focusPolicy());
859 setNextFocusPrefersMouse(m_settings->nextFocusPrefersMouse());
860 setSeparateScreenFocus(m_settings->separateScreenFocus());
861 setRollOverDesktops(m_settings->rollOverDesktops());
862 setLegacyFullscreenSupport(m_settings->legacyFullscreenSupport());
863 setFocusStealingPreventionLevel(m_settings->focusStealingPreventionLevel());
864
865#ifdef KWIN_BUILD_DECORATIONS
866 setPlacement(m_settings->placement());
867#else
868 setPlacement(Placement::Maximizing);
869#endif
870
871 setAutoRaise(m_settings->autoRaise());
872 setAutoRaiseInterval(m_settings->autoRaiseInterval());
873 setDelayFocusInterval(m_settings->delayFocusInterval());
874 setShadeHover(m_settings->shadeHover());
875 setShadeHoverInterval(m_settings->shadeHoverInterval());
876 setClickRaise(m_settings->clickRaise());
877 setBorderSnapZone(m_settings->borderSnapZone());
878 setWindowSnapZone(m_settings->windowSnapZone());
879 setCenterSnapZone(m_settings->centerSnapZone());
880 setSnapOnlyWhenOverlapping(m_settings->snapOnlyWhenOverlapping());
881 setKillPingTimeout(m_settings->killPingTimeout());
882 setHideUtilityWindowsForInactive(m_settings->hideUtilityWindowsForInactive());
883 setInactiveTabsSkipTaskbar(m_settings->inactiveTabsSkipTaskbar());
884 setAutogroupSimilarWindows(m_settings->autogroupSimilarWindows());
885 setAutogroupInForeground(m_settings->autogroupInForeground());
886 setShowDesktopIsMinimizeAll(m_settings->showDesktopIsMinimizeAll());
887 setBorderlessMaximizedWindows(m_settings->borderlessMaximizedWindows());
888 setElectricBorderMaximize(m_settings->electricBorderMaximize());
889 setElectricBorderTiling(m_settings->electricBorderTiling());
890 setElectricBorderCornerRatio(m_settings->electricBorderCornerRatio());
891
892}
893
894bool Options::loadCompositingConfig (bool force)
895{
896 KSharedConfig::Ptr _config = KGlobal::config();
897 KConfigGroup config(_config, "Compositing");
898
899 bool useCompositing = false;
900 CompositingType compositingMode = NoCompositing;
901 QString compositingBackend = config.readEntry("Backend", "OpenGL");
902 if (compositingBackend == "XRender")
903 compositingMode = XRenderCompositing;
904 else
905 compositingMode = OpenGLCompositing;
906
907 if (const char *c = getenv("KWIN_COMPOSE")) {
908 switch(c[0]) {
909 case 'O':
910 kDebug(1212) << "Compositing forced to OpenGL mode by environment variable";
911 compositingMode = OpenGLCompositing;
912 useCompositing = true;
913 break;
914 case 'X':
915 kDebug(1212) << "Compositing forced to XRender mode by environment variable";
916 compositingMode = XRenderCompositing;
917 useCompositing = true;
918 break;
919 case 'N':
920 if (getenv("KDE_FAILSAFE"))
921 kDebug(1212) << "Compositing disabled forcefully by KDE failsafe mode";
922 else
923 kDebug(1212) << "Compositing disabled forcefully by environment variable";
924 compositingMode = NoCompositing;
925 break;
926 default:
927 kDebug(1212) << "Unknown KWIN_COMPOSE mode set, ignoring";
928 break;
929 }
930 }
931 setCompositingMode(compositingMode);
932
933 if (m_compositingMode == NoCompositing) {
934 setUseCompositing(false);
935 return false; // do not even detect compositing preferences if explicitly disabled
936 }
937
938 // it's either enforced by env or by initial resume from "suspend" or we check the settings
939 setUseCompositing(useCompositing || force || config.readEntry("Enabled", Options::defaultUseCompositing()));
940
941 if (!m_useCompositing)
942 return false; // not enforced or necessary and not "enabled" by settings
943 return true;
944}
945
946void Options::reloadCompositingSettings(bool force)
947{
948 if (!loadCompositingConfig(force)) {
949 return;
950 }
951 // from now on we've an initial setup and don't have to reload settings on compositing activation
952 // see Workspace::setupCompositing(), composite.cpp
953 setCompositingInitialized(true);
954
955 // Compositing settings
956 CompositingPrefs prefs;
957 if (compositingMode() == OpenGLCompositing) {
958 prefs.detect();
959 }
960
961 KSharedConfig::Ptr _config = KGlobal::config();
962 KConfigGroup config(_config, "Compositing");
963
964 setGlDirect(prefs.enableDirectRendering());
965 setGlSmoothScale(qBound(-1, config.readEntry("GLTextureFilter", Options::defaultGlSmoothScale()), 2));
966 setGlStrictBindingFollowsDriver(!config.hasKey("GLStrictBinding"));
967 if (!isGlStrictBindingFollowsDriver()) {
968 setGlStrictBinding(config.readEntry("GLStrictBinding", Options::defaultGlStrictBinding()));
969 }
970 setGlLegacy(config.readEntry("GLLegacy", Options::defaultGlLegacy()));
971 setGLCoreProfile(config.readEntry("GLCore", Options::defaultGLCoreProfile()));
972
973 char c = 0;
974 const QString s = config.readEntry("GLPreferBufferSwap", QString(Options::defaultGlPreferBufferSwap()));
975 if (!s.isEmpty())
976 c = s.at(0).toAscii();
977 if (c != 'a' && c != 'c' && c != 'p' && c != 'e')
978 c = 0;
979 setGlPreferBufferSwap(c);
980
981 setColorCorrected(config.readEntry("GLColorCorrection", Options::defaultColorCorrected()));
982
983 m_xrenderSmoothScale = config.readEntry("XRenderSmoothScale", false);
984
985 HiddenPreviews previews = Options::defaultHiddenPreviews();
986 // 4 - off, 5 - shown, 6 - always, other are old values
987 int hps = config.readEntry("HiddenPreviews", 5);
988 if (hps == 4)
989 previews = HiddenPreviewsNever;
990 else if (hps == 5)
991 previews = HiddenPreviewsShown;
992 else if (hps == 6)
993 previews = HiddenPreviewsAlways;
994 setHiddenPreviews(previews);
995
996 setUnredirectFullscreen(config.readEntry("UnredirectFullscreen", Options::defaultUnredirectFullscreen()));
997 // TOOD: add setter
998 animationSpeed = qBound(0, config.readEntry("AnimationSpeed", Options::defaultAnimationSpeed()), 6);
999}
1000
1001// restricted should be true for operations that the user may not be able to repeat
1002// if the window is moved out of the workspace (e.g. if the user moves a window
1003// by the titlebar, and moves it too high beneath Kicker at the top edge, they
1004// may not be able to move it back, unless they know about Alt+LMB)
1005Options::WindowOperation Options::windowOperation(const QString &name, bool restricted)
1006{
1007 if (name == "Move")
1008 return restricted ? MoveOp : UnrestrictedMoveOp;
1009 else if (name == "Resize")
1010 return restricted ? ResizeOp : UnrestrictedResizeOp;
1011 else if (name == "Maximize")
1012 return MaximizeOp;
1013 else if (name == "Minimize")
1014 return MinimizeOp;
1015 else if (name == "Close")
1016 return CloseOp;
1017 else if (name == "OnAllDesktops")
1018 return OnAllDesktopsOp;
1019 else if (name == "Shade")
1020 return ShadeOp;
1021 else if (name == "Operations")
1022 return OperationsOp;
1023 else if (name == "Maximize (vertical only)")
1024 return VMaximizeOp;
1025 else if (name == "Maximize (horizontal only)")
1026 return HMaximizeOp;
1027 else if (name == "Lower")
1028 return LowerOp;
1029 return NoOp;
1030}
1031
1032Options::MouseCommand Options::mouseCommand(const QString &name, bool restricted)
1033{
1034 QString lowerName = name.toLower();
1035 if (lowerName == "raise") return MouseRaise;
1036 if (lowerName == "lower") return MouseLower;
1037 if (lowerName == "operations menu") return MouseOperationsMenu;
1038 if (lowerName == "toggle raise and lower") return MouseToggleRaiseAndLower;
1039 if (lowerName == "activate and raise") return MouseActivateAndRaise;
1040 if (lowerName == "activate and lower") return MouseActivateAndLower;
1041 if (lowerName == "activate") return MouseActivate;
1042 if (lowerName == "activate, raise and pass click") return MouseActivateRaiseAndPassClick;
1043 if (lowerName == "activate and pass click") return MouseActivateAndPassClick;
1044 if (lowerName == "scroll") return MouseNothing;
1045 if (lowerName == "activate and scroll") return MouseActivateAndPassClick;
1046 if (lowerName == "activate, raise and scroll") return MouseActivateRaiseAndPassClick;
1047 if (lowerName == "activate, raise and move")
1048 return restricted ? MouseActivateRaiseAndMove : MouseActivateRaiseAndUnrestrictedMove;
1049 if (lowerName == "move") return restricted ? MouseMove : MouseUnrestrictedMove;
1050 if (lowerName == "resize") return restricted ? MouseResize : MouseUnrestrictedResize;
1051 if (lowerName == "shade") return MouseShade;
1052 if (lowerName == "minimize") return MouseMinimize;
1053 if (lowerName == "start window tab drag") return MouseDragTab;
1054 if (lowerName == "close") return MouseClose;
1055 if (lowerName == "increase opacity") return MouseOpacityMore;
1056 if (lowerName == "decrease opacity") return MouseOpacityLess;
1057 if (lowerName == "nothing") return MouseNothing;
1058 return MouseNothing;
1059}
1060
1061Options::MouseWheelCommand Options::mouseWheelCommand(const QString &name)
1062{
1063 QString lowerName = name.toLower();
1064 if (lowerName == "raise/lower") return MouseWheelRaiseLower;
1065 if (lowerName == "shade/unshade") return MouseWheelShadeUnshade;
1066 if (lowerName == "maximize/restore") return MouseWheelMaximizeRestore;
1067 if (lowerName == "above/below") return MouseWheelAboveBelow;
1068 if (lowerName == "previous/next desktop") return MouseWheelPreviousNextDesktop;
1069 if (lowerName == "change opacity") return MouseWheelChangeOpacity;
1070 if (lowerName == "switch to window tab to the left/right") return MouseWheelChangeCurrentTab;
1071 if (lowerName == "nothing") return MouseWheelNothing;
1072 return MouseWheelChangeCurrentTab;
1073}
1074
1075bool Options::showGeometryTip() const
1076{
1077 return show_geometry_tip;
1078}
1079
1080bool Options::condensedTitle() const
1081{
1082 return condensed_title;
1083}
1084
1085Options::MouseCommand Options::wheelToMouseCommand(MouseWheelCommand com, int delta) const
1086{
1087 switch(com) {
1088 case MouseWheelRaiseLower:
1089 return delta > 0 ? MouseRaise : MouseLower;
1090 case MouseWheelShadeUnshade:
1091 return delta > 0 ? MouseSetShade : MouseUnsetShade;
1092 case MouseWheelMaximizeRestore:
1093 return delta > 0 ? MouseMaximize : MouseRestore;
1094 case MouseWheelAboveBelow:
1095 return delta > 0 ? MouseAbove : MouseBelow;
1096 case MouseWheelPreviousNextDesktop:
1097 return delta > 0 ? MousePreviousDesktop : MouseNextDesktop;
1098 case MouseWheelChangeOpacity:
1099 return delta > 0 ? MouseOpacityMore : MouseOpacityLess;
1100 case MouseWheelChangeCurrentTab:
1101 return delta > 0 ? MousePreviousTab : MouseNextTab;
1102 default:
1103 return MouseNothing;
1104 }
1105}
1106#endif
1107
1108double Options::animationTimeFactor() const
1109{
1110 const double factors[] = { 0, 0.2, 0.5, 1, 2, 4, 20 };
1111 return factors[ animationSpeed ];
1112}
1113
1114} // namespace
1115