on xenial help sign in
Avoid showing the shutdown dialog when turning on the screen if your device is under heavy load.
30e803cMichael Terry
plugins/Utils/windowkeysfilter.cpp+15−1
@@ -21,7 +21,8 @@
21#include <QQuickWindow>
21#include <QQuickWindow>
22
22
23WindowKeysFilter::WindowKeysFilter(QQuickItem *parent)
23WindowKeysFilter::WindowKeysFilter(QQuickItem *parent)
24− : QQuickItem(parent)
24+ : QQuickItem(parent),
25+ m_currentEventTimestamp(0)
25{
26{
26 connect(this, &QQuickItem::windowChanged,
27 connect(this, &QQuickItem::windowChanged,
27 this, &WindowKeysFilter::setupFilterOnWindow);
28 this, &WindowKeysFilter::setupFilterOnWindow);
@@ -36,7 +37,15 @@ bool WindowKeysFilter::eventFilter(QObject *watched, QEvent *event)
36 if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
37 if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
37 // Let QML see this event and decide if it does not want it
38 // Let QML see this event and decide if it does not want it
38 event->accept();
39 event->accept();
40+
41+ m_currentEventTimestamp = static_cast<QInputEvent*>(event)->timestamp();
42+ Q_EMIT currentEventTimestampChanged();
43+
39 QCoreApplication::sendEvent(this, event);
44 QCoreApplication::sendEvent(this, event);
45+
46+ m_currentEventTimestamp = 0;
47+ Q_EMIT currentEventTimestampChanged();
48+
40 return event->isAccepted();
49 return event->isAccepted();
41 } else {
50 } else {
42 // Not interested
51 // Not interested
@@ -56,3 +65,8 @@ void WindowKeysFilter::setupFilterOnWindow(QQuickWindow *window)
56 m_filteredWindow = window;
65 m_filteredWindow = window;
57 }
66 }
58}
67}
68+
69+ulong WindowKeysFilter::currentEventTimestamp() const
70+{
71+ return m_currentEventTimestamp;
72+}
plugins/Utils/windowkeysfilter.h+7
@@ -36,16 +36,23 @@
36class WindowKeysFilter : public QQuickItem
36class WindowKeysFilter : public QQuickItem
37{
37{
38 Q_OBJECT
38 Q_OBJECT
39+ Q_PROPERTY(ulong currentEventTimestamp READ currentEventTimestamp NOTIFY currentEventTimestampChanged)
39public:
40public:
40 WindowKeysFilter(QQuickItem *parent = 0);
41 WindowKeysFilter(QQuickItem *parent = 0);
41
42
42 bool eventFilter(QObject *watched, QEvent *event) override;
43 bool eventFilter(QObject *watched, QEvent *event) override;
43
44
45+ ulong currentEventTimestamp() const;
46+
47+Q_SIGNALS:
48+ void currentEventTimestampChanged();
49+
44private Q_SLOTS:
50private Q_SLOTS:
45 void setupFilterOnWindow(QQuickWindow *window);
51 void setupFilterOnWindow(QQuickWindow *window);
46
52
47private:
53private:
48 QPointer<QQuickWindow> m_filteredWindow;
54 QPointer<QQuickWindow> m_filteredWindow;
55+ ulong m_currentEventTimestamp;
49};
56};
50
57
51#endif // UNITY_WINDOWKEYSFILTER_H
58#endif // UNITY_WINDOWKEYSFILTER_H
qml/Components/PhysicalKeysMapper.qml+13−20
@@ -57,27 +57,20 @@ Item {
57
57
58 property bool altPressed: false
58 property bool altPressed: false
59 property bool altTabPressed: false
59 property bool altTabPressed: false
60− }
61
60
62− Timer {
61+ property var powerButtonPressStart: 0
63− id: powerKeyLongPressTimer
64− interval: root.powerKeyLongPressTime
65− onTriggered: root.powerKeyLongPressed();
66 }
62 }
67
63
68− function onKeyPressed(event) {
64+ function onKeyPressed(event, currentEventTimestamp) {
69− if ((event.key == Qt.Key_PowerDown || event.key == Qt.Key_PowerOff)
65+ if (event.key == Qt.Key_PowerDown || event.key == Qt.Key_PowerOff) {
70− && (!event.isAutoRepeat || !powerKeyLongPressTimer.running)) {
66+ if (event.isAutoRepeat) {
71−
67+ if (d.powerButtonPressStart > 0
72− // FIXME: We only consider power key presses if the screen is
68+ && currentEventTimestamp - d.powerButtonPressStart >= powerKeyLongPressTime) {
73− // on because of bugs 1410830/1409003. The theory is that when
69+ d.powerButtonPressStart = 0;
74− // those bugs are encountered, there is a >2s delay between the
70+ root.powerKeyLongPressed();
75− // power press event and the power release event, which causes
71+ }
76− // the shutdown dialog to appear on resume. So to avoid that
72+ } else {
77− // symptom while we investigate the root cause, we simply won't
73+ d.powerButtonPressStart = currentEventTimestamp;
78− // initiate any dialogs when the screen is off.
79− if (Powerd.status === Powerd.On) {
80− powerKeyLongPressTimer.restart();
81 }
74 }
82 } else if ((event.key == Qt.Key_MediaTogglePlayPause || event.key == Qt.Key_MediaPlay) && !event.isAutoRepeat) {
75 } else if ((event.key == Qt.Key_MediaTogglePlayPause || event.key == Qt.Key_MediaPlay) && !event.isAutoRepeat) {
83 event.accepted = callManager.handleMediaKey(false);
76 event.accepted = callManager.handleMediaKey(false);
@@ -113,9 +106,9 @@ Item {
113 }
106 }
114 }
107 }
115
108
116− function onKeyReleased(event) {
109+ function onKeyReleased(event, currentEventTimestamp) {
117 if (event.key == Qt.Key_PowerDown || event.key == Qt.Key_PowerOff) {
110 if (event.key == Qt.Key_PowerDown || event.key == Qt.Key_PowerOff) {
118− powerKeyLongPressTimer.stop();
111+ d.powerButtonPressStart = 0;
119 event.accepted = true;
112 event.accepted = true;
120 } else if (event.key == Qt.Key_VolumeDown) {
113 } else if (event.key == Qt.Key_VolumeDown) {
121 if (!d.ignoreVolumeEvents) root.volumeDownTriggered();
114 if (!d.ignoreVolumeEvents) root.volumeDownTriggered();
qml/Shell.qml+2−2
@@ -172,8 +172,8 @@ Item {
172 }
172 }
173
173
174 WindowKeysFilter {
174 WindowKeysFilter {
175− Keys.onPressed: physicalKeysMapper.onKeyPressed(event);
175+ Keys.onPressed: physicalKeysMapper.onKeyPressed(event, currentEventTimestamp);
176− Keys.onReleased: physicalKeysMapper.onKeyReleased(event);
176+ Keys.onReleased: physicalKeysMapper.onKeyReleased(event, currentEventTimestamp);
177 }
177 }
178
178
179 HomeKeyWatcher {
179 HomeKeyWatcher {
tests/qmltests/Components/tst_PhysicalKeysMapper.qml+10−9
@@ -67,26 +67,27 @@ TestCase {
67 Powerd.setStatus(data.status, Powerd.Unknown);
67 Powerd.setStatus(data.status, Powerd.Unknown);
68 physicalKeysMapper.powerKeyLongPressTime = 500;
68 physicalKeysMapper.powerKeyLongPressTime = 500;
69
69
70− physicalKeysMapper.onKeyPressed({ key: Qt.Key_PowerDown, isAutoRepeat: false });
70+ physicalKeysMapper.onKeyPressed({ key: Qt.Key_PowerDown, isAutoRepeat: false }, 100);
71
71
72 // After the first key press the screen is always on
72 // After the first key press the screen is always on
73 // and the rest of keypresses are auto repeat
73 // and the rest of keypresses are auto repeat
74 Powerd.setStatus(Powerd.On, Powerd.Unknown);
74 Powerd.setStatus(Powerd.On, Powerd.Unknown);
75
75
76− for (var i = 0; i < 3; ++i) {
76+ physicalKeysMapper.onKeyPressed({ key: Qt.Key_PowerDown, isAutoRepeat: true}, 300);
77− wait(10);
77+ physicalKeysMapper.onKeyPressed({ key: Qt.Key_PowerDown, isAutoRepeat: true}, 400);
78− physicalKeysMapper.onKeyPressed({ key: Qt.Key_PowerDown, isAutoRepeat: true});
78+ physicalKeysMapper.onKeyPressed({ key: Qt.Key_PowerDown, isAutoRepeat: true}, 500);
79− }
79+ physicalKeysMapper.onKeyPressed({ key: Qt.Key_PowerDown, isAutoRepeat: true}, 599);
80
80
81 // powerKeyLongPressed should not have been emitted yet.
81 // powerKeyLongPressed should not have been emitted yet.
82 compare(powerSpy.count, 0);
82 compare(powerSpy.count, 0);
83
83
84− for (var i = 0; i < 10; ++i) {
85− wait(50);
86− physicalKeysMapper.onKeyPressed({ key: Qt.Key_PowerDown, isAutoRepeat: true});
84+ physicalKeysMapper.onKeyPressed({ key: Qt.Key_PowerDown, isAutoRepeat: true}, 600);
87− }
88
85
89 compare(powerSpy.count, 1);
86 compare(powerSpy.count, 1);
87+
88+ // Confirm we only emit once
89+ physicalKeysMapper.onKeyPressed({ key: Qt.Key_PowerDown, isAutoRepeat: true}, 601);
90+ compare(powerSpy.count, 1);
90 }
91 }
91
92
92 function test_screenshotButtons_data() {
93 function test_screenshotButtons_data() {