From 7a409bfffc87230d11d27d7e876e75f32632285b Mon Sep 17 00:00:00 2001 From: Sebastian Keller Date: Sat, 22 Apr 2023 00:05:22 +0200 Subject: [PATCH] keyboard: Delete selected text on backspace Previously backspace would only ever remove a single character left of the cursor, regardless of selection. This requires the application to correctly set the anchor position in text_input::set_surrounding_text(), which currently only gtk4 seems to do. When there is no selection or on other applications that always set cursor = anchor, like gtk3 does, the behavior is not changed and still only deletes one character. Part-of: --- js/misc/inputMethod.js | 8 +++++++- js/ui/keyboard.js | 35 +++++++++++++++++++++++------------ 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/js/misc/inputMethod.js b/js/misc/inputMethod.js index d169ea8cb..53af39d85 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 180bc6b29..38f1b8ee3 100644 --- a/js/ui/keyboard.js +++ b/js/ui/keyboard.js @@ -1650,24 +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; - const anchor = this._timesDeleted < BACKSPACE_WORD_DELETE_THRESHOLD - ? cursor - 1 - : this._previousWordPosition(text, cursor); - const offset = anchor - cursor; + 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); @@ -1675,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 {