1 |
commit: e8ecf8e32790fec99329c16cb2be96ce4f5ff513 |
2 |
Author: Andreas Sturmlechner <andreas.sturmlechner <AT> gmail <DOT> com> |
3 |
AuthorDate: Thu Jun 23 17:16:16 2016 +0000 |
4 |
Commit: Michael Palimaka <kensington <AT> gentoo <DOT> org> |
5 |
CommitDate: Sat Jun 25 18:30:28 2016 +0000 |
6 |
URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=e8ecf8e3 |
7 |
|
8 |
kde-plasma/kscreen: Add fix for multiscreen config persistance |
9 |
|
10 |
Reported-by: gorg86 (forums.gentoo.org) |
11 |
|
12 |
https://forums.gentoo.org/viewtopic-t-1046956.html |
13 |
|
14 |
Upstream bug: https://bugs.kde.org/show_bug.cgi?id=346961 |
15 |
|
16 |
Package-Manager: portage-2.2.28 |
17 |
|
18 |
.../kscreen/files/kscreen-5.6.5-config-fix.patch | 159 +++++++++++++++++++++ |
19 |
kde-plasma/kscreen/kscreen-5.6.5-r1.ebuild | 40 ++++++ |
20 |
2 files changed, 199 insertions(+) |
21 |
|
22 |
diff --git a/kde-plasma/kscreen/files/kscreen-5.6.5-config-fix.patch b/kde-plasma/kscreen/files/kscreen-5.6.5-config-fix.patch |
23 |
new file mode 100644 |
24 |
index 0000000..56474aa |
25 |
--- /dev/null |
26 |
+++ b/kde-plasma/kscreen/files/kscreen-5.6.5-config-fix.patch |
27 |
@@ -0,0 +1,159 @@ |
28 |
+From: Sebastian Kügler <sebas@×××.org> |
29 |
+Date: Wed, 01 Jun 2016 14:54:16 +0000 |
30 |
+Subject: address race condition around setoperation |
31 |
+X-Git-Tag: v5.6.95 |
32 |
+X-Git-Url: http://quickgit.kde.org/?p=kscreen.git&a=commitdiff&h=17199d32f292f7c44eb8cdce5b35396d3bd19eb8 |
33 |
+--- |
34 |
+address race condition around setoperation |
35 |
+ |
36 |
+Summary: |
37 |
+Use a timer to avoid catching configChanged signals after we set |
38 |
+changes. |
39 |
+ |
40 |
+The long version: |
41 |
+ |
42 |
+TL;DR: We have a race condition when the kscreen daemon starts. It looks |
43 |
+up a known config, then applies it and subsequently resaves the config. |
44 |
+The same happens on config changes, it writes, then re-reads and then |
45 |
+re-writes the config change. |
46 |
+I've managed to prevent this from happening by adding a timer that does |
47 |
+avoids saving the config as a direct reaction to our own config changes. |
48 |
+ |
49 |
+So what happens on kded5 startup after loading the kscreen2 module: |
50 |
+ |
51 |
+- the kscreen config is requested and received |
52 |
+- the kscreen daemon (KD) looks into its config directory for a suitable |
53 |
+config file |
54 |
+(a config file is identified by a combined hash of all screen |
55 |
+attached, so unique per connected set of outputs) |
56 |
+- KD usually finds a config |
57 |
+- KD ignores configChanged events before it starts ... |
58 |
+- a KScreen::SetConfigOperation to apply the "known config" |
59 |
+- SetConfigOperation returns after a while (say 100ms later) |
60 |
+- we re-enable the change monitor |
61 |
+- we receive a configChanged signal |
62 |
+- we save the new config (usually to the existing config file) |
63 |
+ |
64 |
+I don't think this behavior is desirable. I don't see a reason why the |
65 |
+daemon should save its config right after applying it. I think this |
66 |
+causes more problems than we want, since the startup may overwrite the |
67 |
+user's config. This behavior seems to be desired by the code in KD, it's |
68 |
+already blocking configChanged signals during the SetOperation (which, |
69 |
+to be honest may result in nightmarish behavior in any way, so it might |
70 |
+be a kludge which aims too short). |
71 |
+ |
72 |
+From libkscreen perspective, SetConfigOperation::finished cannot |
73 |
+guarantee that all configChanged signals are already fired and that it's |
74 |
+safe to watch for new, independent changes now. At least on X11, we |
75 |
+simply don't know, and what we can do is wait a bit and cross fingers |
76 |
+that we're not catching our own noise. The changed signal *may* come |
77 |
+from a re-request of the edid information, but this is a bit hard to |
78 |
+track down, and not too useful, anyway, since changed Edid may affect a |
79 |
+large number of a screen's properties. |
80 |
+In the Wayland backend, that's a different story and we can prevent this |
81 |
+behavior at an earlier stage, so this timer is "probably not needed" (I |
82 |
+haven't tested that). |
83 |
+ |
84 |
+This effectively prevents KD from catching reactions to its own changes |
85 |
+and does not trigger saving the config file on every login. It still |
86 |
+reacts to changes from libkscreen, but will avoid re-saving the config a |
87 |
+few times. The timer may not be the neatest of solutions for this, but |
88 |
+it does help narrowing down the problem and may be a last resort action. |
89 |
+Most importantly, it avoids the re-writing of the config on startup and |
90 |
+plugging/unplugging a monitor effectively. |
91 |
+ |
92 |
+The timer value of 100ms is also used in kwin, which should make the |
93 |
+behavior (which is no problem in kwin) more solid. |
94 |
+ |
95 |
+CCBUG:346961 |
96 |
+CCBUG:358011 |
97 |
+ |
98 |
+Reviewers: graesslin |
99 |
+ |
100 |
+Reviewed By: graesslin |
101 |
+ |
102 |
+Subscribers: plasma-devel, #plasma |
103 |
+ |
104 |
+Tags: #plasma |
105 |
+ |
106 |
+Differential Revision: https://phabricator.kde.org/D1730 |
107 |
+--- |
108 |
+ |
109 |
+ |
110 |
+--- a/kded/daemon.cpp |
111 |
++++ b/kded/daemon.cpp |
112 |
+@@ -23,6 +23,7 @@ |
113 |
+ #include "kscreenadaptor.h" |
114 |
+ #include "debug.h" |
115 |
+ |
116 |
++#include <QElapsedTimer> |
117 |
+ #include <QTimer> |
118 |
+ #include <QAction> |
119 |
+ #include <QShortcut> |
120 |
+@@ -52,6 +53,7 @@ |
121 |
+ , m_buttonTimer(new QTimer()) |
122 |
+ , m_saveTimer(new QTimer()) |
123 |
+ , m_lidClosedTimer(new QTimer()) |
124 |
++ , m_changeBlockTimer(new QElapsedTimer()) |
125 |
+ |
126 |
+ { |
127 |
+ QMetaObject::invokeMethod(this, "requestConfig", Qt::QueuedConnection); |
128 |
+@@ -82,6 +84,7 @@ |
129 |
+ delete m_saveTimer; |
130 |
+ delete m_buttonTimer; |
131 |
+ delete m_lidClosedTimer; |
132 |
++ delete m_changeBlockTimer; |
133 |
+ |
134 |
+ Generator::destroy(); |
135 |
+ Device::destroy(); |
136 |
+@@ -112,7 +115,6 @@ |
137 |
+ m_lidClosedTimer->setInterval(1000); |
138 |
+ m_lidClosedTimer->setSingleShot(true); |
139 |
+ connect(m_lidClosedTimer, &QTimer::timeout, this, &KScreenDaemon::lidClosedTimeout); |
140 |
+- |
141 |
+ |
142 |
+ connect(Device::self(), &Device::lidClosedChanged, this, &KScreenDaemon::lidClosedChanged); |
143 |
+ connect(Device::self(), &Device::resumingFromSuspend, |
144 |
+@@ -145,6 +147,9 @@ |
145 |
+ connect(new KScreen::SetConfigOperation(config), &KScreen::SetConfigOperation::finished, |
146 |
+ [&]() { |
147 |
+ qCDebug(KSCREEN_KDED) << "Config applied"; |
148 |
++ // We enable monitoring already, but we will ignore the first signals that come |
149 |
++ // in the next 100ms, since these are likely our own changes still flushing out |
150 |
++ m_changeBlockTimer->start(); |
151 |
+ setMonitorForChanges(true); |
152 |
+ }); |
153 |
+ } |
154 |
+@@ -182,6 +187,12 @@ |
155 |
+ |
156 |
+ void KScreenDaemon::configChanged() |
157 |
+ { |
158 |
++ if (m_changeBlockTimer->isValid() && !m_changeBlockTimer->hasExpired(100)) { |
159 |
++ m_changeBlockTimer->start(); |
160 |
++ qCDebug(KSCREEN_KDED) << "Change detected, but ignoring since it's our own noise"; |
161 |
++ return; |
162 |
++ } |
163 |
++ m_changeBlockTimer->invalidate(); |
164 |
+ qCDebug(KSCREEN_KDED) << "Change detected"; |
165 |
+ // Reset timer, delay the writeback |
166 |
+ m_saveTimer->start(); |
167 |
+ |
168 |
+--- a/kded/daemon.h |
169 |
++++ b/kded/daemon.h |
170 |
+@@ -27,6 +27,7 @@ |
171 |
+ |
172 |
+ #include "generator.h" |
173 |
+ |
174 |
++class QElapsedTimer; |
175 |
+ class QTimer; |
176 |
+ |
177 |
+ namespace KScreen |
178 |
+@@ -79,6 +80,7 @@ |
179 |
+ QTimer* m_buttonTimer; |
180 |
+ QTimer* m_saveTimer; |
181 |
+ QTimer* m_lidClosedTimer; |
182 |
++ QElapsedTimer* m_changeBlockTimer; |
183 |
+ }; |
184 |
+ |
185 |
+ #endif /*KSCREN_DAEMON_H*/ |
186 |
+ |
187 |
|
188 |
diff --git a/kde-plasma/kscreen/kscreen-5.6.5-r1.ebuild b/kde-plasma/kscreen/kscreen-5.6.5-r1.ebuild |
189 |
new file mode 100644 |
190 |
index 0000000..a219d75 |
191 |
--- /dev/null |
192 |
+++ b/kde-plasma/kscreen/kscreen-5.6.5-r1.ebuild |
193 |
@@ -0,0 +1,40 @@ |
194 |
+# Copyright 1999-2016 Gentoo Foundation |
195 |
+# Distributed under the terms of the GNU General Public License v2 |
196 |
+# $Id$ |
197 |
+ |
198 |
+EAPI=6 |
199 |
+ |
200 |
+KDE_TEST="forceoptional" |
201 |
+inherit kde5 |
202 |
+ |
203 |
+DESCRIPTION="KDE Plasma screen management" |
204 |
+HOMEPAGE="https://projects.kde.org/projects/extragear/base/kscreen" |
205 |
+ |
206 |
+KEYWORDS="~amd64 ~arm ~x86" |
207 |
+IUSE="" |
208 |
+ |
209 |
+DEPEND=" |
210 |
+ $(add_frameworks_dep kconfig) |
211 |
+ $(add_frameworks_dep kconfigwidgets) |
212 |
+ $(add_frameworks_dep kcoreaddons) |
213 |
+ $(add_frameworks_dep kdbusaddons) |
214 |
+ $(add_frameworks_dep kglobalaccel) |
215 |
+ $(add_frameworks_dep ki18n) |
216 |
+ $(add_frameworks_dep kwidgetsaddons) |
217 |
+ $(add_frameworks_dep kxmlgui) |
218 |
+ $(add_plasma_dep libkscreen) |
219 |
+ $(add_qt_dep qtdbus) |
220 |
+ $(add_qt_dep qtdeclarative 'widgets') |
221 |
+ $(add_qt_dep qtgui) |
222 |
+ $(add_qt_dep qtwidgets) |
223 |
+" |
224 |
+RDEPEND="${DEPEND} |
225 |
+ $(add_plasma_dep kde-cli-tools) |
226 |
+ $(add_qt_dep qtgraphicaleffects) |
227 |
+ !kde-misc/kscreen |
228 |
+" |
229 |
+ |
230 |
+PATCHES=( "${FILESDIR}/${P}-config-fix.patch" ) |
231 |
+ |
232 |
+# bug #580440, last checked 5.6.3 |
233 |
+RESTRICT="test" |