From a4020ad79c4c9f275c960882bfec8bb473d98d9f Mon Sep 17 00:00:00 2001 From: Florrie Date: Wed, 12 Sep 2018 13:39:14 -0300 Subject: (breaking, very) Fix how text inputs bubble events This is extremely super duper very breaking in that it reverses the order that keyboard events are bubbled. This fixes an issue in the following situation: You have a focus element which captures keyboard input. When the X key is pressed, a text input, which is a child (directly or indirectly) of it, is selected and has its value emptied. As the user types into that text input, if they press the X key, the handler on the focus element will detect this, and clear and select the text input - interrupting the user's typing. The situation is fixed in this commit by making the text input avoid bubbling events when text is entered. I'm not sure this is 100% complete, because arrow key events and the like are still bubbled, but those aren't difficult to change later. The breaking fundamental change here is that keyboard events are now bubbled from the top element down. Before, a parent element could deny child elements from responding to the event; now the child can deny the parent. --- ui/Root.js | 2 +- ui/form/TextInput.js | 23 ++++++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) (limited to 'ui') diff --git a/ui/Root.js b/ui/Root.js index a6b3acf..7e031d3 100644 --- a/ui/Root.js +++ b/ui/Root.js @@ -27,7 +27,7 @@ module.exports = class Root extends DisplayElement { handleData(buffer) { if (this.selectedElement) { const els = [ - ...this.selectedElement.directAncestors, this.selectedElement] + ...this.selectedElement.directAncestors, this.selectedElement].reverse() for (const el of els) { if (el instanceof FocusElement) { const shouldBreak = (el.keyPressed(buffer) === false) diff --git a/ui/form/TextInput.js b/ui/form/TextInput.js index 11e4060..f07b562 100644 --- a/ui/form/TextInput.js +++ b/ui/form/TextInput.js @@ -70,13 +70,22 @@ module.exports = class TextInput extends FocusElement { // ESC is bad and we don't want that in the text input! return } else { - // console.log(keyBuf, keyBuf[0], keyBuf[1], keyBuf[2]) - this.value = ( - this.value.slice(0, this.cursorIndex) + keyBuf.toString() + - this.value.slice(this.cursorIndex) - ) - this.cursorIndex++ - this.root.cursorMoved() + const isTextInput = keyBuf.toString().split('').every(chr => { + const n = chr.charCodeAt(0) + return n > 31 && n < 127 + }) + + if (isTextInput) { + this.value = ( + this.value.slice(0, this.cursorIndex) + keyBuf.toString() + + this.value.slice(this.cursorIndex) + ) + this.cursorIndex += keyBuf.toString().length + this.root.cursorMoved() + this.keepCursorInRange() + + return false + } } this.keepCursorInRange() -- cgit 1.3.0-6-gf8a5