diff --git a/src/app/KeyInput.cpp b/src/app/KeyInput.cpp index c4e127a..184ef3b 100644 --- a/src/app/KeyInput.cpp +++ b/src/app/KeyInput.cpp @@ -8,8 +8,7 @@ namespace { struct JsCodeToVk { const char* code; uint16_t vk; }; // KeyboardEvent.code values are physical positions, so a binding made on one -// keyboard layout means the same physical key on another. Escape is absent on -// purpose — the remap window uses it to cancel listening. +// keyboard layout means the same physical key on another. const JsCodeToVk kCodeMap[] = { // Letters {"KeyA",'A'},{"KeyB",'B'},{"KeyC",'C'},{"KeyD",'D'},{"KeyE",'E'},{"KeyF",'F'}, @@ -29,6 +28,7 @@ const JsCodeToVk kCodeMap[] = { {"Backspace", VK_BACK}, {"Delete", VK_DELETE}, {"Insert", VK_INSERT}, + {"Escape", VK_ESCAPE}, // Navigation {"ArrowUp", VK_UP}, diff --git a/src/app/RemapWindow.cpp b/src/app/RemapWindow.cpp index 2f6542a..4f14146 100644 --- a/src/app/RemapWindow.cpp +++ b/src/app/RemapWindow.cpp @@ -1336,18 +1336,20 @@ document.addEventListener('auxclick',function(e){ }); document.addEventListener('keydown',function(e){ - // Escape stays the cancel affordance, so it is deliberately not bindable. - // Innermost dismissable thing first: the modal is the only one that can sit - // on top of the others. + // Escape closes whichever overlay sits on top of the page — innermost + // first, and the modal is the only one that can sit on top of the other. + // Neither overlay is up while a row is listening, so in that case Escape + // falls through to the capture logic below and binds like any other key + // (issue #105) — the row's own Cancel button is how listening is aborted. if(e.key==='Escape'){ if(pendingAction!==null||document.getElementById('modal-backdrop').style.display==='flex'){ resolveModal('cancel'); - } else if(comboOpen){ + return; + } + if(comboOpen){ closeCombo(); - } else { - cancelListening(); + return; } - return; } // The search box is a real text field — typing in it must not be swallowed // by the binding-capture handler below.