diff --git a/js/misc/inputMethod.js b/js/misc/inputMethod.js index d169ea8cbe1f91fc9107f3e7e951193463bac550..53af39d8582230a1e33a4798ce7334b6b38c57d6 100644 --- a/js/misc/inputMethod.js +++ b/js/misc/inputMethod.js @@ -227,6 +227,7 @@ export const InputMethod = GObject.registerClass({ this._surroundingText = null; this._surroundingTextCursor = null; + this._surroundingTextAnchor = null; this._preeditStr = null; this._setTerminalMode(false); } @@ -247,6 +248,7 @@ export const InputMethod = GObject.registerClass({ vfunc_set_surrounding(text, cursor, anchor) { this._surroundingText = text; this._surroundingTextCursor = cursor; + this._surroundingTextAnchor = anchor; this.emit('surrounding-text-set'); if (!this._context || (!text && text !== '')) @@ -348,7 +350,11 @@ export const InputMethod = GObject.registerClass({ } getSurroundingText() { - return [this._surroundingText, this._surroundingTextCursor]; + return [ + this._surroundingText, + this._surroundingTextCursor, + this._surroundingTextAnchor, + ]; } hasPreedit() { diff --git a/js/ui/keyboard.js b/js/ui/keyboard.js index 1aa47ae47b52f250ac09f2335d81f2fbaf3f9244..38f1b8ee3a3dcdfc412cc50fdc13a5b6625d7640 100644 --- a/js/ui/keyboard.js +++ b/js/ui/keyboard.js @@ -1619,18 +1619,10 @@ export const Keyboard = GObject.registerClass({ } _previousWordPosition(text, cursor) { - /* Skip word prior to cursor */ - let pos = Math.max(0, text.slice(0, cursor).search(/\s+\S+\s*$/)); - if (pos < 0) - return 0; - - /* Skip contiguous spaces */ - for (; pos >= 0; pos--) { - if (text.charAt(pos) !== ' ') - return GLib.utf8_strlen(text.slice(0, pos + 1), -1); - } - - return 0; + const upToCursor = [...text].slice(0, cursor).join(''); + const jsStringPos = Math.max(0, upToCursor.search(/\s+\S+\s*$/)); + const charPos = GLib.utf8_strlen(text.slice(0, jsStringPos), -1); + return charPos; } _toggleDelete(enabled) { @@ -1658,31 +1650,35 @@ export const Keyboard = GObject.registerClass({ } if (enabled) { - let func = (text, cursor) => { - if (cursor === 0) + let func = (text, cursor, anchor) => { + if (cursor === 0 && anchor === 0) return; - let encoder = new TextEncoder(); - let decoder = new TextDecoder(); - - /* Find cursor/anchor position in characters */ - const cursorIdx = GLib.utf8_strlen(decoder.decode(encoder.encode( - text).slice(0, cursor)), -1); - const anchorIdx = this._timesDeleted < BACKSPACE_WORD_DELETE_THRESHOLD - ? cursorIdx - 1 - : this._previousWordPosition(text, cursor); - /* Now get offset from cursor */ - const offset = anchorIdx - cursorIdx; + let offset, len; + if (cursor > anchor) { + offset = anchor - cursor; + len = -offset; + } else if (cursor < anchor) { + offset = 0; + len = anchor - cursor; + } else if (this._timesDeleted < BACKSPACE_WORD_DELETE_THRESHOLD) { + offset = -1; + len = 1; + } else { + const wordLength = cursor - this._previousWordPosition(text, cursor); + offset = -wordLength; + len = wordLength; + } this._timesDeleted++; - Main.inputMethod.delete_surrounding(offset, Math.abs(offset)); + Main.inputMethod.delete_surrounding(offset, len); }; this._surroundingUpdateId = Main.inputMethod.connect( 'surrounding-text-set', () => { - let [text, cursor] = Main.inputMethod.getSurroundingText(); + let [text, cursor, anchor] = Main.inputMethod.getSurroundingText(); if (this._timesDeleted === 0) { - func(text, cursor); + func(text, cursor, anchor); } else { if (this._surroundingUpdateTimeoutId > 0) { GLib.source_remove(this._surroundingUpdateTimeoutId); @@ -1690,16 +1686,16 @@ export const Keyboard = GObject.registerClass({ } this._surroundingUpdateTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, KEY_RELEASE_TIMEOUT, () => { - func(text, cursor); + func(text, cursor, cursor); this._surroundingUpdateTimeoutId = 0; return GLib.SOURCE_REMOVE; }); } }); - let [text, cursor] = Main.inputMethod.getSurroundingText(); + let [text, cursor, anchor] = Main.inputMethod.getSurroundingText(); if (text) - func(text, cursor); + func(text, cursor, anchor); else Main.inputMethod.request_surrounding(); } else {