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: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2746>
This commit is contained in:
Sebastian Keller 2023-04-22 00:05:22 +02:00 committed by Carlos Garnacho
parent 484a237002
commit 7a409bfffc
2 changed files with 30 additions and 13 deletions

View File

@ -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() {

View File

@ -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 {