From d5b965da70307eb789a6f5e6d494eaad3df990ed Mon Sep 17 00:00:00 2001 From: Boris Astardzhiev Date: Sat, 15 Feb 2020 08:57:48 -0500 Subject: [PATCH] Added type-ahead find for Desktop icons (Bug #11149) Co-authored-by: Alexander Schwinn --- src/xfdesktop-icon-view.c | 65 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/src/xfdesktop-icon-view.c b/src/xfdesktop-icon-view.c index b665cc10..cf1fab1f 100644 --- a/src/xfdesktop-icon-view.c +++ b/src/xfdesktop-icon-view.c @@ -1071,18 +1071,81 @@ xfdesktop_icon_view_button_release(GtkWidget *widget, return TRUE; } +static gboolean +xfdesktop_icon_view_select_icon_from_list_by_key(XfdesktopIconView *icon_view, + GdkEventKey *evt, + GList *icon_list) +{ + XfdesktopIcon *icon = NULL; + const gchar *label; + gunichar lchar, kchar; + GList *l; + + /* Do it case-insensitive */ + kchar = g_unichar_tolower(gdk_keyval_to_unicode(evt->keyval)); + for(l = icon_list; l; l = l->next) { + icon = (XfdesktopIcon *)l->data; + label = xfdesktop_icon_peek_label(icon); + if(label && g_utf8_validate(label, g_utf8_strlen(label, -1), NULL) == TRUE) { + lchar = g_unichar_tolower(g_utf8_get_char(label)); + if(lchar == kchar) { + icon_view->priv->cursor = icon; + xfdesktop_icon_view_select_item(icon_view, icon); + return TRUE; + } + } + } + + return FALSE; +} + +static void +xfdesktop_icon_view_type_ahead_find_icon(XfdesktopIconView *icon_view, + GdkEventKey *evt) +{ + GList *icon_list_p_current_cursor; + gboolean icon_selected = FALSE; + + xfdesktop_icon_view_unselect_all(icon_view); + + /* If we have a cursor, we try to select the next matching item after the cursor */ + if(icon_view->priv->cursor != NULL) { + icon_list_p_current_cursor = g_list_find(icon_view->priv->icons, icon_view->priv->cursor); + icon_selected = xfdesktop_icon_view_select_icon_from_list_by_key(icon_view, evt, + g_list_next(icon_list_p_current_cursor)); + } + + /* still nothing is selected, select first icon from the beginning of the list */ + if(icon_selected == FALSE) { + xfdesktop_icon_view_select_icon_from_list_by_key(icon_view, + evt, + icon_view->priv->icons); + } +} + static gboolean xfdesktop_icon_view_key_press(GtkWidget *widget, GdkEventKey *evt, gpointer user_data) { XfdesktopIconView *icon_view = XFDESKTOP_ICON_VIEW(user_data); + gboolean ret = FALSE; DBG("entering"); /* since we're NO_WINDOW, events don't get delivered to us normally, * so we have to activate the bindings manually */ - return gtk_bindings_activate_event(G_OBJECT(icon_view), evt); + ret = gtk_bindings_activate_event(G_OBJECT(icon_view), evt); + if(ret == FALSE) { + /* Binding not found, now inspect the pressed character. + * Let's try to find an icon starting with this character and make + * the icon selected. */ + guint32 unicode = gdk_keyval_to_unicode(evt->keyval); + if(unicode && g_unichar_isgraph(unicode) == TRUE) + xfdesktop_icon_view_type_ahead_find_icon(icon_view, evt); + } + + return ret; } static gboolean -- 2.25.0