on xenial help sign in
Count the key events rather than wall time when considering showing the shutdown dialog
cde772bMichael Terry
qml/Components/PhysicalKeysMapper.qml+17−19
@@ -42,7 +42,7 @@ Item {
42
42
43 readonly property bool altTabPressed: d.altTabPressed
43 readonly property bool altTabPressed: d.altTabPressed
44
44
45− property int powerKeyLongPressTime: 2000
45+ property int powerKeyLongPressCount: 31 // about 2s
46
46
47 // For testing. If running windowed (e.g. tryShell), Alt+Tab is taken by the
47 // For testing. If running windowed (e.g. tryShell), Alt+Tab is taken by the
48 // running desktop, set this to true to use Ctrl+Tab instead.
48 // running desktop, set this to true to use Ctrl+Tab instead.
@@ -57,27 +57,26 @@ 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 int powerButtonCount
63− id: powerKeyLongPressTimer
64− interval: root.powerKeyLongPressTime
65− onTriggered: root.powerKeyLongPressed();
66 }
62 }
67
63
68 function onKeyPressed(event) {
64 function onKeyPressed(event) {
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+ d.powerButtonCount++;
72− // FIXME: We only consider power key presses if the screen is
68+
73− // on because of bugs 1410830/1409003. The theory is that when
69+ // We count repeats rather than watch the time because if the
74− // those bugs are encountered, there is a >2s delay between the
70+ // system is loaded, we may misinterpret a long wall-clock
75− // power press event and the power release event, which causes
71+ // delay as a long press, when in fact we just didn't get
76− // the shutdown dialog to appear on resume. So to avoid that
72+ // around to noticing the key-release event in time. But if we
77− // symptom while we investigate the root cause, we simply won't
73+ // count events instead, we will be in sync with the event
78− // initiate any dialogs when the screen is off.
74+ // queue.
79− if (Powerd.status === Powerd.On) {
75+ if (d.powerButtonCount === powerKeyLongPressCount) {
80− powerKeyLongPressTimer.restart();
76+ root.powerKeyLongPressed();
77+ }
78+ } else {
79+ d.powerButtonCount = 0;
81 }
80 }
82 } else if ((event.key == Qt.Key_MediaTogglePlayPause || event.key == Qt.Key_MediaPlay) && !event.isAutoRepeat) {
81 } else if ((event.key == Qt.Key_MediaTogglePlayPause || event.key == Qt.Key_MediaPlay) && !event.isAutoRepeat) {
83 event.accepted = callManager.handleMediaKey(false);
82 event.accepted = callManager.handleMediaKey(false);
@@ -115,7 +114,6 @@ Item {
115
114
116 function onKeyReleased(event) {
115 function onKeyReleased(event) {
117 if (event.key == Qt.Key_PowerDown || event.key == Qt.Key_PowerOff) {
116 if (event.key == Qt.Key_PowerDown || event.key == Qt.Key_PowerOff) {
118− powerKeyLongPressTimer.stop();
119 event.accepted = true;
117 event.accepted = true;
120 } else if (event.key == Qt.Key_VolumeDown) {
118 } else if (event.key == Qt.Key_VolumeDown) {
121 if (!d.ignoreVolumeEvents) root.volumeDownTriggered();
119 if (!d.ignoreVolumeEvents) root.volumeDownTriggered();
tests/qmltests/Components/tst_PhysicalKeysMapper.qml+7−7
@@ -65,7 +65,7 @@ TestCase {
65
65
66 function test_powerKeyLongPressed(data) {
66 function test_powerKeyLongPressed(data) {
67 Powerd.setStatus(data.status, Powerd.Unknown);
67 Powerd.setStatus(data.status, Powerd.Unknown);
68− physicalKeysMapper.powerKeyLongPressTime = 500;
68+ physicalKeysMapper.powerKeyLongPressCount = 5;
69
69
70 physicalKeysMapper.onKeyPressed({ key: Qt.Key_PowerDown, isAutoRepeat: false });
70 physicalKeysMapper.onKeyPressed({ key: Qt.Key_PowerDown, isAutoRepeat: false });
71
71
@@ -73,19 +73,19 @@ TestCase {
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+ for (var i = 0; i < 4; ++i) {
77− wait(10);
78 physicalKeysMapper.onKeyPressed({ key: Qt.Key_PowerDown, isAutoRepeat: true});
77 physicalKeysMapper.onKeyPressed({ key: Qt.Key_PowerDown, isAutoRepeat: true});
79 }
78 }
80
79
81 // powerKeyLongPressed should not have been emitted yet.
80 // powerKeyLongPressed should not have been emitted yet.
82 compare(powerSpy.count, 0);
81 compare(powerSpy.count, 0);
83
82
84− for (var i = 0; i < 10; ++i) {
83+ // Fifth repeat event will trigger emission
85− wait(50);
86− physicalKeysMapper.onKeyPressed({ key: Qt.Key_PowerDown, isAutoRepeat: true});
84+ physicalKeysMapper.onKeyPressed({ key: Qt.Key_PowerDown, isAutoRepeat: true});
87− }
85+ compare(powerSpy.count, 1);
88
86
87+ // Make sure we don't double-emit
88+ physicalKeysMapper.onKeyPressed({ key: Qt.Key_PowerDown, isAutoRepeat: true});
89 compare(powerSpy.count, 1);
89 compare(powerSpy.count, 1);
90 }
90 }
91
91