vcl/unx/gtk3/gtkinst.cxx | 58 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+)
New commits: commit 43d8805c5f2525739319de886b78806b0bc14970 Author: Caolán McNamara <[email protected]> AuthorDate: Mon Dec 8 11:20:51 2025 +0000 Commit: Adolfo Jayme Barrientos <[email protected]> CommitDate: Tue Dec 9 05:33:41 2025 +0100 tdf#169105 defeat klipper triggering losing selection during autocomplete klipper, for some reason, causes the GtkComboBox to lose the clipboard selection during autocomplete, and by default the visible selection is dropped by GtkEntry when it loses the clipboard. So, defeat klipper by, when autocompleting, replacing the default clipboard handing with a custom one that retains the GtkEntry selection on losing the clipboard but not losing focusa. Change-Id: I51c34c386c06b63a15755eb00f0b8b5a399a568d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195224 Reviewed-by: Caolán McNamara <[email protected]> Tested-by: Jenkins (cherry picked from commit 722f5e3aef579784c28b5e38cb8a9f457409be3b) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195261 Reviewed-by: Adolfo Jayme Barrientos <[email protected]> diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx index 56336207ae84..e44d8ef516f2 100644 --- a/vcl/unx/gtk3/gtkinst.cxx +++ b/vcl/unx/gtk3/gtkinst.cxx @@ -21044,6 +21044,9 @@ private: set_active_including_mru(nPos, true); } select_entry_region(aText.getLength(), aStartText.getLength()); + // take over clipboard handling for the autocomplete selection + // in order to defeat klipper + autocomplete_update_primary_selection(GTK_ENTRY(m_pEntry)); } enable_notify_events(); } @@ -22018,6 +22021,61 @@ private: return pos; } + static void autocomplete_clip_get(GtkClipboard*, GtkSelectionData* pSelectionData, guint, gpointer user_data) + { + GtkEntry *pEntry = GTK_ENTRY(user_data); + + gint nStart, nEnd; + if (gtk_editable_get_selection_bounds(GTK_EDITABLE(pEntry), &nStart, &nEnd)) + { + gchar* pStr = gtk_editable_get_chars(GTK_EDITABLE(pEntry), nStart, nEnd); + gtk_selection_data_set_text(pSelectionData, pStr, -1); + g_free(pStr); + } + } + + static void autocomplete_clip_clear(GtkClipboard*, gpointer user_data) + { + GtkEntry* pEntry = GTK_ENTRY(user_data); + + // We lose the clipboard, but we still have focus, keep the text selected anyway + // so autocomplete doesn't get broken. + if (gtk_widget_has_focus(GTK_WIDGET(pEntry))) + return; + + gint nCurrentPos = gtk_editable_get_position(GTK_EDITABLE(pEntry)); + gtk_editable_select_region(GTK_EDITABLE(pEntry), nCurrentPos, nCurrentPos); + } + + + // This is intended to be basically the same as + // gtk_entry_update_primary_selection except that the clipboard cleared + // callback will only unselect the text selection if the widget no longer + // has focus. This attempts to defeat klipper breaking autocomplete when it + // appears to steal the clipboard during autocomplete. + static void autocomplete_update_primary_selection(GtkEntry* pEntry) + { + if (!gtk_widget_get_realized(GTK_WIDGET(pEntry))) + return; + + gint nStart, nEnd; + if (!gtk_editable_get_selection_bounds(GTK_EDITABLE(pEntry), &nStart, &nEnd)) + return; + + GtkTargetList* pTargetList = gtk_target_list_new(nullptr, 0); + gtk_target_list_add_text_targets(pTargetList, 0); + + gint nTargets; + GtkTargetEntry* pTargets = gtk_target_table_new_from_list(pTargetList, &nTargets); + + GtkClipboard* pClipboard = gtk_widget_get_clipboard(GTK_WIDGET(pEntry), GDK_SELECTION_PRIMARY); + + gtk_clipboard_set_with_owner(pClipboard, pTargets, nTargets, autocomplete_clip_get, autocomplete_clip_clear, G_OBJECT(pEntry)); + + gtk_target_table_free(pTargets, nTargets); + gtk_target_list_unref(pTargetList); + } + public: GtkInstanceComboBox(GtkBuilder* pComboBuilder, GtkComboBox* pComboBox, GtkInstanceBuilder* pBuilder, bool bTakeOwnership) : GtkInstanceContainer(GTK_CONTAINER(gtk_builder_get_object(pComboBuilder, "box")), pBuilder, bTakeOwnership)
