Merge lp:~lukas-kde/unity8/superKeyPressFix into lp:unity8
- superKeyPressFix
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Daniel d'Andrada | ||||
Approved revision: | 2662 | ||||
Merged at revision: | 2727 | ||||
Proposed branch: | lp:~lukas-kde/unity8/superKeyPressFix | ||||
Merge into: | lp:unity8 | ||||
Diff against target: |
244 lines (+87/-18) 4 files modified
plugins/Utils/ElapsedTimer.h (+1/-1) plugins/Utils/Timer.cpp (+5/-2) plugins/Utils/Timer.h (+5/-6) tests/plugins/Utils/WindowInputMonitorTest.cpp (+76/-9) |
||||
To merge this branch: | bzr merge lp:~lukas-kde/unity8/superKeyPressFix | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Unity8 CI Bot | continuous-integration | Approve | |
Albert Astals Cid (community) | Abstain | ||
Daniel d'Andrada (community) | Approve | ||
Review via email: mp+307977@code.launchpad.net |
Commit message
Fix the Super key not invoking the dash scope home
Description of the change
Fix the Super key not invoking the dash scope home
lp:1607427 - super key not showing scopes home
Do not lie about a timer running, when it's not
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2658
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
SUCCESS: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Albert Astals Cid (aacid) wrote : | # |
I don't see how this makes a difference
Previously we had single shot, which means the timeout signal gets emitted and then it stops itself, so basically we get emitActivatedIf
Now we have no single show but we still stop the timer when emitActivatedIf
So basically the same is happening before and after the patch?
Daniel d'Andrada (dandrader) wrote : | # |
Yeah, I also don't get it. A timer being singleshot means that it times out only once and then stops itself. Unlike a regular timer which will timeout every QTimer::interval() milliseconds until you manually stop() it.
Lukáš Tinkl (lukas-kde) wrote : | # |
Yeah, the core of this problem seems to be the fact that even a single shot timer, although it fires only once, is never stopped.
The fake timer was doing a manual stop() in that case; if you remove this discrepancy, then the regression test passes with this branch, and fails in the real environment - resulting in the bug, as described in lp:1607427.
In other words, the functionality works exactly once - and then stops working. The key press handler has this:
...
&& !m_activationTi
meaning that if the timer is never stopped, it will never register any subsequent Super key presses.
Lukáš Tinkl (lukas-kde) wrote : | # |
Also, without this branch, any long press of the Super key would break this
Albert Astals Cid (aacid) wrote : | # |
I think the problem lies in the Timer wrapping, i'll suggest a different MR in a few minutes
Daniel d'Andrada (dandrader) wrote : | # |
On 10/10/2016 10:33, Lukáš Tinkl wrote:
> Yeah, the core of this problem seems to be the fact that even a single shot timer, although it fires only once, is never stopped.
>
> The fake timer was doing a manual stop() in that case; if you remove this discrepancy, then the regression test passes with this branch, and fails in the real environment - resulting in the bug, as described in lp:1607427.
>
> In other words, the functionality works exactly once - and then stops working. The key press handler has this:
>
> ...
> && !m_activationTi
>
> meaning that if the timer is never stopped, it will never register any subsequent Super key presses.
That's all very strange. qtimer.cpp has this:
"""
void QTimer:
{
if (e->timerId() == id) {
if (single)
emit timeout(
}
}
"""
ie, a singleshot timer stops itself on timeout...
Lukáš Tinkl (lukas-kde) wrote : | # |
> On 10/10/2016 10:33, Lukáš Tinkl wrote:
> > Yeah, the core of this problem seems to be the fact that even a single shot
> timer, although it fires only once, is never stopped.
> >
> > The fake timer was doing a manual stop() in that case; if you remove this
> discrepancy, then the regression test passes with this branch, and fails in
> the real environment - resulting in the bug, as described in lp:1607427.
> >
> > In other words, the functionality works exactly once - and then stops
> working. The key press handler has this:
> >
> > ...
> > && !m_activationTi
> >
> > meaning that if the timer is never stopped, it will never register any
> subsequent Super key presses.
>
>
> That's all very strange. qtimer.cpp has this:
>
> """
>
> void QTimer:
> {
> if (e->timerId() == id) {
> if (single)
> stop();
> emit timeout(
> }
> }
>
> """
>
>
> ie, a singleshot timer stops itself on timeout...
Yeah, but our (your :p) Utils/Timer.cpp doesn't and that's the problem really
Albert Astals Cid (aacid) wrote : | # |
I think this is a better fix, actually fixing Timer::isRunning not to lie
http://
What do you think?
Albert Astals Cid (aacid) wrote : | # |
Forgot to initialize m_isRunning http://
Daniel d'Andrada (dandrader) wrote : | # |
> Forgot to initialize m_isRunning http://
Now that makes sense. Proper fix.
Lukáš Tinkl (lukas-kde) wrote : | # |
Pushed Albert's change
Daniel d'Andrada (dandrader) wrote : | # |
Looks good to me.
* Did you perform an exploratory manual test run of the code change and any related functionality?
No, but fix is simple, and so is the code being fixed. That, plus the regression test, makes me confident enough to approve it already.
* Did CI run pass? If not, please explain why.
No results yet. May reassess once it comes.
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2659
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2661
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Albert Astals Cid (aacid) wrote : | # |
Abstaining since code is partially mine
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2661
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 2662. By Lukáš Tinkl
-
don't return garbage when the timer isn't running, or never been started
Lukáš Tinkl (lukas-kde) wrote : | # |
Submitted a fix for what I think is the culprit why it can occasionally break
(quite visible when testing the appDrawer branch):
QElapsedTimer:
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:2662
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 2663. By Lukáš Tinkl
-
make the FakeElapsedTimer more realistic; adapt the test
Preview Diff
1 | === modified file 'plugins/Utils/ElapsedTimer.h' |
2 | --- plugins/Utils/ElapsedTimer.h 2015-04-22 10:40:54 +0000 |
3 | +++ plugins/Utils/ElapsedTimer.h 2016-11-29 15:38:24 +0000 |
4 | @@ -41,7 +41,7 @@ |
5 | public: |
6 | void start() override { m_timer.start(); } |
7 | qint64 msecsSinceReference() const override { return m_timer.msecsSinceReference(); } |
8 | - qint64 elapsed() const override { return m_timer.elapsed(); } |
9 | + qint64 elapsed() const override { return m_timer.isValid() ? m_timer.elapsed() : 0; } |
10 | private: |
11 | QElapsedTimer m_timer; |
12 | }; |
13 | |
14 | === modified file 'plugins/Utils/Timer.cpp' |
15 | --- plugins/Utils/Timer.cpp 2015-04-22 10:40:54 +0000 |
16 | +++ plugins/Utils/Timer.cpp 2016-11-29 15:38:24 +0000 |
17 | @@ -37,13 +37,16 @@ |
18 | void Timer::start() |
19 | { |
20 | m_timer.start(); |
21 | - AbstractTimer::start(); |
22 | } |
23 | |
24 | void Timer::stop() |
25 | { |
26 | m_timer.stop(); |
27 | - AbstractTimer::stop(); |
28 | +} |
29 | + |
30 | +bool Timer::isRunning() const |
31 | +{ |
32 | + return m_timer.isActive(); |
33 | } |
34 | |
35 | bool Timer::isSingleShot() const |
36 | |
37 | === modified file 'plugins/Utils/Timer.h' |
38 | --- plugins/Utils/Timer.h 2015-04-22 10:40:54 +0000 |
39 | +++ plugins/Utils/Timer.h 2016-11-29 15:38:24 +0000 |
40 | @@ -30,18 +30,16 @@ |
41 | { |
42 | Q_OBJECT |
43 | public: |
44 | - AbstractTimer(QObject *parent) : QObject(parent), m_isRunning(false) {} |
45 | + AbstractTimer(QObject *parent) : QObject(parent) {} |
46 | virtual int interval() const = 0; |
47 | virtual void setInterval(int msecs) = 0; |
48 | - virtual void start() { m_isRunning = true; } |
49 | - virtual void stop() { m_isRunning = false; } |
50 | - bool isRunning() const { return m_isRunning; } |
51 | + virtual void start() = 0; |
52 | + virtual void stop() = 0; |
53 | + virtual bool isRunning() const = 0; |
54 | virtual bool isSingleShot() const = 0; |
55 | virtual void setSingleShot(bool value) = 0; |
56 | Q_SIGNALS: |
57 | void timeout(); |
58 | -private: |
59 | - bool m_isRunning; |
60 | }; |
61 | |
62 | /** A QTimer wrapper */ |
63 | @@ -55,6 +53,7 @@ |
64 | void setInterval(int msecs) override; |
65 | void start() override; |
66 | void stop() override; |
67 | + bool isRunning() const override; |
68 | bool isSingleShot() const override; |
69 | void setSingleShot(bool value) override; |
70 | private: |
71 | |
72 | === modified file 'tests/plugins/Utils/WindowInputMonitorTest.cpp' |
73 | --- tests/plugins/Utils/WindowInputMonitorTest.cpp 2016-03-21 19:35:46 +0000 |
74 | +++ tests/plugins/Utils/WindowInputMonitorTest.cpp 2016-11-29 15:38:24 +0000 |
75 | @@ -25,14 +25,15 @@ |
76 | public: |
77 | static qint64 msecsSinceEpoch; |
78 | |
79 | - FakeElapsedTimer() { start(); } |
80 | + FakeElapsedTimer() {} |
81 | |
82 | - void start() override { m_msecsSinceReference = msecsSinceEpoch; } |
83 | + void start() override { m_msecsSinceReference = msecsSinceEpoch; m_valid = true; } |
84 | qint64 msecsSinceReference() const override { return m_msecsSinceReference; } |
85 | - qint64 elapsed() const override { return msecsSinceEpoch - m_msecsSinceReference; } |
86 | + qint64 elapsed() const override { return m_valid ? msecsSinceEpoch - m_msecsSinceReference : qrand(); } |
87 | |
88 | private: |
89 | qint64 m_msecsSinceReference; |
90 | + bool m_valid{false}; |
91 | }; |
92 | qint64 FakeElapsedTimer::msecsSinceEpoch = 0; |
93 | |
94 | @@ -48,11 +49,14 @@ |
95 | int interval() const override; |
96 | void setInterval(int msecs) override; |
97 | void start() override; |
98 | + void stop() override; |
99 | + bool isRunning() const override; |
100 | bool isSingleShot() const override; |
101 | void setSingleShot(bool value) override; |
102 | private: |
103 | int m_interval; |
104 | bool m_singleShot; |
105 | + bool m_isRunning; |
106 | qint64 m_nextTimeoutTime; |
107 | }; |
108 | |
109 | @@ -85,6 +89,8 @@ |
110 | void tapWhileTouching(); |
111 | void multipleHomeKeys(); |
112 | |
113 | + void repeatedSuperPress(); |
114 | + |
115 | private: |
116 | void passTime(qint64 timeSpanMs); |
117 | |
118 | @@ -98,11 +104,10 @@ |
119 | |
120 | void WindowInputMonitorTest::cleanup() |
121 | { |
122 | - delete m_fakeTimerFactory; |
123 | + delete m_fakeTimerFactory; |
124 | m_fakeTimerFactory = nullptr; |
125 | } |
126 | |
127 | - |
128 | void WindowInputMonitorTest::passTime(qint64 timeSpanMs) |
129 | { |
130 | qint64 finalTime = FakeElapsedTimer::msecsSinceEpoch + timeSpanMs; |
131 | @@ -133,7 +138,7 @@ |
132 | QFETCH(int, silenceAfterTap); |
133 | QFETCH(int, expectedActivatedCount); |
134 | QFETCH(Qt::Key, key); |
135 | - WindowInputMonitor homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer); |
136 | + WindowInputMonitor homeKeyWatcher(m_fakeTimerFactory->create(this), new FakeElapsedTimer); |
137 | QSignalSpy activatedSpy(&homeKeyWatcher, &WindowInputMonitor::homeKeyActivated); |
138 | QVERIFY(activatedSpy.isValid()); |
139 | |
140 | @@ -194,7 +199,7 @@ |
141 | |
142 | void WindowInputMonitorTest::tapWhileTouching() |
143 | { |
144 | - WindowInputMonitor homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer); |
145 | + WindowInputMonitor homeKeyWatcher(m_fakeTimerFactory->create(this), new FakeElapsedTimer); |
146 | QSignalSpy activatedSpy(&homeKeyWatcher, &WindowInputMonitor::homeKeyActivated); |
147 | QVERIFY(activatedSpy.isValid()); |
148 | |
149 | @@ -229,7 +234,7 @@ |
150 | */ |
151 | void WindowInputMonitorTest::multipleHomeKeys() |
152 | { |
153 | - WindowInputMonitor homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer); |
154 | + WindowInputMonitor homeKeyWatcher(m_fakeTimerFactory->create(this), new FakeElapsedTimer); |
155 | QSignalSpy activatedSpy(&homeKeyWatcher, &WindowInputMonitor::homeKeyActivated); |
156 | QVERIFY(activatedSpy.isValid()); |
157 | |
158 | @@ -258,12 +263,64 @@ |
159 | QCOMPARE(activatedSpy.count(), 1); |
160 | } |
161 | |
162 | +// regression test for lp:1607427 |
163 | +void WindowInputMonitorTest::repeatedSuperPress() |
164 | +{ |
165 | + WindowInputMonitor homeKeyWatcher(m_fakeTimerFactory->create(this), new FakeElapsedTimer); |
166 | + QSignalSpy activatedSpy(&homeKeyWatcher, &WindowInputMonitor::homeKeyActivated); |
167 | + QVERIFY(activatedSpy.isValid()); |
168 | + |
169 | + // 1st try |
170 | + passTime(1000); |
171 | + { |
172 | + QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Super_L, Qt::NoModifier); |
173 | + homeKeyWatcher.update(&keyEvent); |
174 | + } |
175 | + passTime(50); |
176 | + { |
177 | + QKeyEvent keyEvent(QEvent::KeyRelease, Qt::Key_Super_L, Qt::NoModifier); |
178 | + homeKeyWatcher.update(&keyEvent); |
179 | + } |
180 | + passTime(1000); |
181 | + QCOMPARE(activatedSpy.count(), 1); |
182 | + |
183 | + // a touch event in between |
184 | + { |
185 | + QTouchEvent touchEvent(QEvent::TouchBegin); |
186 | + homeKeyWatcher.update(&touchEvent); |
187 | + } |
188 | + { |
189 | + QTouchEvent touchEvent(QEvent::TouchUpdate); |
190 | + homeKeyWatcher.update(&touchEvent); |
191 | + } |
192 | + { |
193 | + QTouchEvent touchEvent(QEvent::TouchEnd); |
194 | + homeKeyWatcher.update(&touchEvent); |
195 | + } |
196 | + |
197 | + passTime(1000); |
198 | + // 2nd try |
199 | + activatedSpy.clear(); |
200 | + { |
201 | + QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Super_L, Qt::NoModifier); |
202 | + homeKeyWatcher.update(&keyEvent); |
203 | + } |
204 | + passTime(50); |
205 | + { |
206 | + QKeyEvent keyEvent(QEvent::KeyRelease, Qt::Key_Super_L, Qt::NoModifier); |
207 | + homeKeyWatcher.update(&keyEvent); |
208 | + } |
209 | + passTime(1000); |
210 | + QCOMPARE(activatedSpy.count(), 1); |
211 | +} |
212 | + |
213 | /////////////////////////////////// FakeTimer ////////////////////////////////// |
214 | |
215 | FakeTimer::FakeTimer(QObject *parent) |
216 | : UnityUtil::AbstractTimer(parent) |
217 | , m_interval(0) |
218 | , m_singleShot(true) |
219 | + , m_isRunning(false) |
220 | { |
221 | } |
222 | |
223 | @@ -285,10 +342,20 @@ |
224 | |
225 | void FakeTimer::start() |
226 | { |
227 | - AbstractTimer::start(); |
228 | + m_isRunning = true; |
229 | m_nextTimeoutTime = FakeElapsedTimer::msecsSinceEpoch + (qint64)interval(); |
230 | } |
231 | |
232 | +void FakeTimer::stop() |
233 | +{ |
234 | + m_isRunning = false; |
235 | +} |
236 | + |
237 | +bool FakeTimer::isRunning() const |
238 | +{ |
239 | + return m_isRunning; |
240 | +} |
241 | + |
242 | int FakeTimer::interval() const |
243 | { |
244 | return m_interval; |
FAILED: Continuous integration, rev:2657 /unity8- jenkins. ubuntu. com/job/ lp-unity8- ci/2343/ /unity8- jenkins. ubuntu. com/job/ build/3084 /unity8- jenkins. ubuntu. com/job/ test-0- autopkgtest/ label=amd64, release= vivid+overlay, testname= qmluitests. sh/1731 /unity8- jenkins. ubuntu. com/job/ test-0- autopkgtest/ label=amd64, release= xenial+ overlay, testname= qmluitests. sh/1731 /unity8- jenkins. ubuntu. com/job/ test-0- autopkgtest/ label=amd64, release= yakkety, testname= qmluitests. sh/1731 /unity8- jenkins. ubuntu. com/job/ build-0- fetch/3112 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 2969 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 2969/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 2969 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 2969/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 2969 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 2969/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 2969 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 2969/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 2969 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 2969/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 2969 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 2969/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 2969 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 2969/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 2969 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 2969/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= yakkety/ 2969 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= yakkety/ 2969/artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /unity8- jenkins. ubuntu. com/job/ lp-unity8- ci/2343/ rebuild
https:/