summaryrefslogtreecommitdiff
path: root/gtk
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2020-01-10 21:56:26 -0500
committerMatthias Clasen <mclasen@redhat.com>2020-01-11 00:50:22 -0500
commitec255f9bb11acdeea2ee44530f8987cddd44b610 (patch)
treeb05d32f18c1838955daf7544071a176a8d6e5036 /gtk
parent9dc6be4fb0782881b5ff43f38a4f785144f5b240 (diff)
downloadgtk+-ec255f9bb11acdeea2ee44530f8987cddd44b610.tar.gz
Update all callers
Diffstat (limited to 'gtk')
-rw-r--r--gtk/gtkcalendar.c27
-rw-r--r--gtk/gtkexpander.c10
-rw-r--r--gtk/gtkfilechooserwidget.c6
-rw-r--r--gtk/gtkiconview.c16
-rw-r--r--gtk/gtknotebook.c15
-rw-r--r--gtk/gtkplacessidebar.c13
-rw-r--r--gtk/gtksearchlistmodel.c544
-rw-r--r--gtk/gtksearchlistmodel.h50
-rw-r--r--gtk/gtkstackswitcher.c20
-rw-r--r--gtk/gtktext.c42
-rw-r--r--gtk/gtktextview.c2
-rw-r--r--gtk/gtktreeview.c13
12 files changed, 681 insertions, 77 deletions
diff --git a/gtk/gtkcalendar.c b/gtk/gtkcalendar.c
index 8d9d36fa88..377616d143 100644
--- a/gtk/gtkcalendar.c
+++ b/gtk/gtkcalendar.c
@@ -331,10 +331,8 @@ static gboolean gtk_calendar_query_tooltip (GtkWidget *widget,
gboolean keyboard_mode,
GtkTooltip *tooltip);
-static gboolean gtk_calendar_drag_motion (GtkDropTarget *dest,
+static gboolean gtk_calendar_drag_accept (GtkDropTarget *dest,
GdkDrop *drop,
- int x,
- int y,
GtkCalendar *calendar);
static void gtk_calendar_drag_leave (GtkDropTarget *dest,
GdkDrop *drop,
@@ -792,7 +790,7 @@ gtk_calendar_init (GtkCalendar *calendar)
dest = gtk_drop_target_new (formats, GDK_ACTION_COPY);
gdk_content_formats_unref (formats);
- g_signal_connect (dest, "accept", G_CALLBACK (gtk_calendar_drag_motion), calendar);
+ g_signal_connect (dest, "accept", G_CALLBACK (gtk_calendar_drag_accept), calendar);
g_signal_connect (dest, "drag-leave", G_CALLBACK (gtk_calendar_drag_leave), calendar);
g_signal_connect (dest, "drag-drop", G_CALLBACK (gtk_calendar_drag_drop), calendar);
@@ -2984,7 +2982,8 @@ got_text (GObject *source,
GAsyncResult *result,
gpointer data)
{
- GtkCalendar *calendar = GTK_CALENDAR (data);
+ GtkDropTarget *dest = GTK_DROP_TARGET (data);
+ GtkCalendar *calendar = GTK_CALENDAR (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest)));
GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (calendar);
GdkDrop *drop = GDK_DROP (source);
guint day, month, year;
@@ -3010,8 +3009,9 @@ got_text (GObject *source,
}
else
suggested_action = 0;
-
gdk_drop_status (drop, suggested_action);
+ if (suggested_action == 0)
+ gtk_drop_target_deny_drop (dest, drop);
return;
}
@@ -3027,6 +3027,7 @@ got_text (GObject *source,
g_warning ("Received invalid date data");
g_date_free (date);
gdk_drop_finish (drop, 0);
+ gtk_drop_target_deny_drop (dest, drop);
return;
}
@@ -3046,23 +3047,23 @@ got_text (GObject *source,
}
static gboolean
-gtk_calendar_drag_motion (GtkDropTarget *dest,
+gtk_calendar_drag_accept (GtkDropTarget *dest,
GdkDrop *drop,
- int x,
- int y,
GtkCalendar *calendar)
{
GdkAtom target;
target = gtk_drop_target_find_mimetype (dest);
if (!target || gdk_drop_get_actions (drop) == 0)
- gdk_drop_status (drop, 0);
+ {
+ gdk_drop_status (drop, 0);
+ return FALSE;
+ }
else if (get_status_pending (drop) == 0)
{
set_status_pending (drop, gdk_drop_get_actions (drop));
- gdk_drop_read_text_async (drop, NULL, got_text, calendar);
+ gdk_drop_read_text_async (drop, NULL, got_text, dest);
}
-
return TRUE;
}
@@ -3079,7 +3080,7 @@ gtk_calendar_drag_drop (GtkDropTarget *dest,
if (target != NULL)
{
set_status_pending (drop, 0);
- gdk_drop_read_text_async (drop, NULL, got_text, calendar);
+ gdk_drop_read_text_async (drop, NULL, got_text, dest);
return TRUE;
}
diff --git a/gtk/gtkexpander.c b/gtk/gtkexpander.c
index 68d0a19652..f1a38acc48 100644
--- a/gtk/gtkexpander.c
+++ b/gtk/gtkexpander.c
@@ -192,10 +192,8 @@ static void gtk_expander_size_allocate (GtkWidget *widget,
int baseline);
static gboolean gtk_expander_focus (GtkWidget *widget,
GtkDirectionType direction);
-static gboolean gtk_expander_drag_motion (GtkDropTarget *dest,
+static gboolean gtk_expander_drag_accept (GtkDropTarget *dest,
GdkDrop *drop,
- int x,
- int y,
GtkExpander *expander);
static void gtk_expander_drag_leave (GtkDropTarget *dest,
GdkDrop *drop,
@@ -379,7 +377,7 @@ gtk_expander_init (GtkExpander *expander)
formats = gdk_content_formats_new (NULL, 0);
dest = gtk_drop_target_new (formats, 0);
gdk_content_formats_unref (formats);
- g_signal_connect (dest, "accept", G_CALLBACK (gtk_expander_drag_motion), expander);
+ g_signal_connect (dest, "accept", G_CALLBACK (gtk_expander_drag_accept), expander);
g_signal_connect (dest, "drag-leave", G_CALLBACK (gtk_expander_drag_leave), expander);
gtk_widget_add_controller (GTK_WIDGET (expander), GTK_EVENT_CONTROLLER (dest));
@@ -549,10 +547,8 @@ expand_timeout (gpointer data)
}
static gboolean
-gtk_expander_drag_motion (GtkDropTarget *dest,
+gtk_expander_drag_accept (GtkDropTarget *dest,
GdkDrop *drop,
- int x,
- int y,
GtkExpander *expander)
{
GtkExpanderPrivate *priv = gtk_expander_get_instance_private (expander);
diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c
index 38fc967dfb..4aecc911c7 100644
--- a/gtk/gtkfilechooserwidget.c
+++ b/gtk/gtkfilechooserwidget.c
@@ -2046,10 +2046,8 @@ file_list_drag_drop_cb (GtkDropTarget *dest,
/* Disable the normal tree drag motion handler, it makes it look like you're
dropping the dragged item onto a tree item */
static gboolean
-file_list_drag_motion_cb (GtkDropTarget *dest,
+file_list_drag_accept_cb (GtkDropTarget *dest,
GdkDrop *drop,
- int x,
- int y,
GtkFileChooserWidget *impl)
{
g_signal_stop_emission_by_name (dest, "accept");
@@ -8497,7 +8495,7 @@ post_process_ui (GtkFileChooserWidget *impl)
GDK_ACTION_COPY | GDK_ACTION_MOVE);
dest = gtk_drop_target_new (formats, GDK_ACTION_COPY | GDK_ACTION_MOVE);
- g_signal_connect (dest, "accept", G_CALLBACK (file_list_drag_motion_cb), impl);
+ g_signal_connect (dest, "accept", G_CALLBACK (file_list_drag_accept_cb), impl);
g_signal_connect (dest, "drag-drop", G_CALLBACK (file_list_drag_drop_cb), impl);
gtk_widget_add_controller (priv->browse_files_tree_view, GTK_EVENT_CONTROLLER (dest));
gdk_content_formats_unref (formats);
diff --git a/gtk/gtkiconview.c b/gtk/gtkiconview.c
index 94e30bee6e..c662156488 100644
--- a/gtk/gtkiconview.c
+++ b/gtk/gtkiconview.c
@@ -292,7 +292,7 @@ static GBytes * gtk_icon_view_drag_data_get (const char *mime_type,
static void gtk_icon_view_drag_leave (GtkDropTarget *dest,
GdkDrop *drop,
GtkIconView *icon_view);
-static gboolean gtk_icon_view_drag_motion (GtkDropTarget *dest,
+static void gtk_icon_view_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y,
@@ -6179,7 +6179,7 @@ gtk_icon_view_drag_leave (GtkDropTarget *dest,
remove_scroll_timeout (icon_view);
}
-static gboolean
+static void
gtk_icon_view_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
@@ -6193,10 +6193,10 @@ gtk_icon_view_drag_motion (GtkDropTarget *dest,
gboolean empty;
if (!set_destination (icon_view, dest, x, y, &suggested_action, &target))
- return FALSE;
-
- icon_view->priv->event_last_x = x;
- icon_view->priv->event_last_y = y;
+ {
+ gdk_drop_status (drop, 0);
+ return;
+ }
gtk_icon_view_get_drag_dest_item (icon_view, &path, &pos);
@@ -6233,8 +6233,6 @@ gtk_icon_view_drag_motion (GtkDropTarget *dest,
if (path)
gtk_tree_path_free (path);
-
- return TRUE;
}
static gboolean
@@ -6457,7 +6455,7 @@ gtk_icon_view_enable_model_drag_dest (GtkIconView *icon_view,
icon_view->priv->dest = gtk_drop_target_new (formats, actions);
g_signal_connect (icon_view->priv->dest, "drag-leave", G_CALLBACK (gtk_icon_view_drag_leave), icon_view);
- g_signal_connect (icon_view->priv->dest, "accept", G_CALLBACK (gtk_icon_view_drag_motion), icon_view);
+ g_signal_connect (icon_view->priv->dest, "drag-motion", G_CALLBACK (gtk_icon_view_drag_motion), icon_view);
g_signal_connect (icon_view->priv->dest, "drag-drop", G_CALLBACK (gtk_icon_view_drag_drop), icon_view);
gtk_widget_add_controller (GTK_WIDGET (icon_view), GTK_EVENT_CONTROLLER (icon_view->priv->dest));
diff --git a/gtk/gtknotebook.c b/gtk/gtknotebook.c
index a160ccb4eb..c8fa3c94fd 100644
--- a/gtk/gtknotebook.c
+++ b/gtk/gtknotebook.c
@@ -703,7 +703,7 @@ static void gtk_notebook_dnd_finished_cb (GdkDrag *drag,
static void gtk_notebook_drag_cancel_cb (GdkDrag *drag,
GdkDragCancelReason reason,
GtkWidget *widget);
-static gboolean gtk_notebook_drag_motion (GtkDropTarget *dest,
+static void gtk_notebook_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y);
@@ -1349,7 +1349,7 @@ gtk_notebook_init (GtkNotebook *notebook)
targets = gdk_content_formats_new (dst_notebook_targets, G_N_ELEMENTS (dst_notebook_targets));
dest = gtk_drop_target_new (targets, GDK_ACTION_MOVE);
- g_signal_connect (dest, "accept", G_CALLBACK (gtk_notebook_drag_motion), NULL);
+ g_signal_connect (dest, "drag-motion", G_CALLBACK (gtk_notebook_drag_motion), NULL);
g_signal_connect (dest, "drag-leave", G_CALLBACK (gtk_notebook_drag_leave), NULL);
g_signal_connect (dest, "drag-drop", G_CALLBACK (gtk_notebook_drag_drop), NULL);
gtk_widget_add_controller (GTK_WIDGET (priv->tabs_widget), GTK_EVENT_CONTROLLER (dest));
@@ -3188,7 +3188,7 @@ gtk_notebook_switch_tab_timeout (gpointer data)
return FALSE;
}
-static gboolean
+static void
gtk_notebook_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
@@ -3202,7 +3202,6 @@ gtk_notebook_drag_motion (GtkDropTarget *dest,
GtkNotebookArrow arrow;
GdkAtom target, tab_target;
GList *tab;
- gboolean retval = FALSE;
arrow = gtk_notebook_get_arrow (notebook, x, y);
if (arrow != ARROW_NONE)
@@ -3211,7 +3210,6 @@ gtk_notebook_drag_motion (GtkDropTarget *dest,
gtk_notebook_set_scroll_timer (notebook);
gdk_drop_status (drop, 0);
- retval = TRUE;
goto out;
}
@@ -3225,8 +3223,6 @@ gtk_notebook_drag_motion (GtkDropTarget *dest,
GtkWidget *source_child;
GdkDrag *drag = gdk_drop_get_drag (drop);
- retval = TRUE;
-
if (!drag)
{
gdk_drop_status (drop, 0);
@@ -3264,8 +3260,6 @@ gtk_notebook_drag_motion (GtkDropTarget *dest,
priv->mouse_x = x;
priv->mouse_y = y;
- retval = TRUE;
-
if (tab != priv->switch_tab)
remove_switch_tab_timer (notebook);
@@ -3282,8 +3276,7 @@ gtk_notebook_drag_motion (GtkDropTarget *dest,
remove_switch_tab_timer (notebook);
}
- out:
- return retval;
+ out:;
}
static void
diff --git a/gtk/gtkplacessidebar.c b/gtk/gtkplacessidebar.c
index aad2385b60..82c6ddad83 100644
--- a/gtk/gtkplacessidebar.c
+++ b/gtk/gtkplacessidebar.c
@@ -1723,12 +1723,12 @@ create_placeholder_row (GtkPlacesSidebar *sidebar)
return g_object_new (GTK_TYPE_SIDEBAR_ROW, "placeholder", TRUE, NULL);
}
-static gboolean
+static void
drag_motion_callback (GtkDropTarget *dest,
GdkDrop *drop,
- gint x,
- gint y,
- gpointer user_data)
+ gint x,
+ gint y,
+ gpointer user_data)
{
GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (user_data);
gint action;
@@ -1850,10 +1850,7 @@ drag_motion_callback (GtkDropTarget *dest,
out:
start_drop_feedback (sidebar, GTK_SIDEBAR_ROW (row), drag);
-
gdk_drop_status (drop, action);
-
- return TRUE;
}
/* Takes an array of URIs and turns it into a list of GFile */
@@ -4088,7 +4085,7 @@ gtk_places_sidebar_init (GtkPlacesSidebar *sidebar)
formats = gdk_content_formats_builder_free_to_formats (builder);
dest = gtk_drop_target_new (formats, GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK);
gdk_content_formats_unref (formats);
- g_signal_connect (dest, "accept", G_CALLBACK (drag_motion_callback), sidebar);
+ g_signal_connect (dest, "drag-motion", G_CALLBACK (drag_motion_callback), sidebar);
g_signal_connect (dest, "drag-drop", G_CALLBACK (drag_drop_callback), sidebar);
g_signal_connect (dest, "drag-leave", G_CALLBACK (drag_leave_callback), sidebar);
gtk_widget_add_controller (sidebar->list_box, GTK_EVENT_CONTROLLER (dest));
diff --git a/gtk/gtksearchlistmodel.c b/gtk/gtksearchlistmodel.c
new file mode 100644
index 0000000000..7a50c28833
--- /dev/null
+++ b/gtk/gtksearchlistmodel.c
@@ -0,0 +1,544 @@
+/*
+ * Copyright © 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#include "config.h"
+
+#include "gtksearchlistmodel.h"
+
+#include "gtkintl.h"
+#include "gtkselectionmodel.h"
+
+/**
+ * SECTION:gtksearchlistmodel
+ * @Short_description: A selection model that allows incremental searching
+ * @Title: GtkSearchListModel
+ * @see_also: #GtkSelectionModel
+ *
+ * GtkSearchListModel is an implementation of the #GtkSelectionModel interface
+ * that allows selecting a single element. The selected element can be determined
+ * interactively via a filter.
+ */
+struct _GtkSearchListModel
+{
+ GObject parent_instance;
+
+ GListModel *model;
+ guint selected;
+ gpointer selected_item;
+
+ GtkFilter *filter;
+};
+
+struct _GtkSearchListModelClass
+{
+ GObjectClass parent_class;
+};
+
+enum {
+ PROP_0,
+ PROP_MODEL,
+ PROP_FILTER,
+ PROP_SELECTED,
+ PROP_SELECTED_ITEM,
+
+ N_PROPS
+};
+
+static GParamSpec *properties[N_PROPS] = { NULL, };
+
+static GType
+gtk_search_list_model_get_item_type (GListModel *list)
+{
+ GtkSearchListModel *self = GTK_SEARCH_LIST_MODEL (list);
+
+ return g_list_model_get_item_type (self->model);
+}
+
+static guint
+gtk_search_list_model_get_n_items (GListModel *list)
+{
+ GtkSearchListModel *self = GTK_SEARCH_LIST_MODEL (list);
+
+ return g_list_model_get_n_items (self->model);
+}
+
+static gpointer
+gtk_search_list_model_get_item (GListModel *list,
+ guint position)
+{
+ GtkSearchListModel *self = GTK_SEARCH_LIST_MODEL (list);
+
+ return g_list_model_get_item (self->model, position);
+}
+
+static void
+gtk_search_list_model_list_model_init (GListModelInterface *iface)
+{
+ iface->get_item_type = gtk_search_list_model_get_item_type;
+ iface->get_n_items = gtk_search_list_model_get_n_items;
+ iface->get_item = gtk_search_list_model_get_item;
+}
+
+static gboolean
+gtk_search_list_model_is_selected (GtkSelectionModel *model,
+ guint position)
+{
+ GtkSearchListModel *self = GTK_SEARCH_LIST_MODEL (model);
+
+ return self->selected == position;
+}
+
+static void
+gtk_search_list_model_query_range (GtkSelectionModel *model,
+ guint position,
+ guint *start_range,
+ guint *n_range,
+ gboolean *selected)
+{
+ GtkSearchListModel *self = GTK_SEARCH_LIST_MODEL (model);
+ guint n_items;
+
+ n_items = g_list_model_get_n_items (self->model);
+
+ if (position >= n_items)
+ {
+ *start_range = position;
+ *n_range = 0;
+ *selected = FALSE;
+ }
+ else if (self->selected == GTK_INVALID_LIST_POSITION)
+ {
+ *start_range = 0;
+ *n_range = n_items;
+ *selected = FALSE;
+ }
+ else if (position < self->selected)
+ {
+ *start_range = 0;
+ *n_range = self->selected;
+ *selected = FALSE;
+ }
+ else if (position > self->selected)
+ {
+ *start_range = self->selected + 1;
+ *n_range = n_items - *start_range;
+ *selected = FALSE;
+ }
+ else
+ {
+ *start_range = self->selected;
+ *n_range = 1;
+ *selected = TRUE;
+ }
+}
+
+static void
+gtk_search_list_model_selection_model_init (GtkSelectionModelInterface *iface)
+{
+ iface->is_selected = gtk_search_list_model_is_selected;
+ iface->query_range = gtk_search_list_model_query_range;
+}
+
+G_DEFINE_TYPE_EXTENDED (GtkSearchListModel, gtk_search_list_model, G_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL,
+ gtk_search_list_model_list_model_init)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_SELECTION_MODEL,
+ gtk_search_list_model_selection_model_init))
+
+static void
+gtk_search_list_model_items_changed_cb (GListModel *model,
+ guint position,
+ guint removed,
+ guint added,
+ GtkSearchListModel *self)
+{
+ g_object_freeze_notify (G_OBJECT (self));
+
+ if (self->selected_item == NULL)
+ {
+ /* nothing to do */
+ }
+ else if (self->selected < position)
+ {
+ /* unchanged */
+ }
+ else if (self->selected >= position + removed)
+ {
+ self->selected += added - removed;
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED]);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED_ITEM]);
+ }
+ else
+ {
+ guint i;
+
+ for (i = 0; i < added; i++)
+ {
+ gpointer item = g_list_model_get_item (model, position + i);
+ if (item == self->selected_item)
+ {
+ /* the item moved */
+ //TODO refilter
+ if (self->selected != position + i)
+ {
+ self->selected = position + i;
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED]);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED_ITEM]);
+ }
+ break;
+ }
+ }
+ if (i == added)
+ {
+ /* the item really was deleted */
+ g_clear_object (&self->selected_item);
+ self->selected = GTK_INVALID_LIST_POSITION;
+ //TODO refilter
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED]);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED_ITEM]);
+ }
+ }
+
+ g_list_model_items_changed (G_LIST_MODEL (self), position, removed, added);
+
+ g_object_thaw_notify (G_OBJECT (self));
+}
+
+static void
+set_selected (GtkSearchListModel *self,
+ guint position)
+{
+ gpointer new_selected = NULL;
+ guint old_position;
+
+ if (self->selected == position)
+ return;
+
+ new_selected = g_list_model_get_item (self->model, position);
+
+ if (new_selected == NULL)
+ position = GTK_INVALID_LIST_POSITION;
+
+ if (self->selected == position)
+ return;
+
+ old_position = self->selected;
+ self->selected = position;
+ g_clear_object (&self->selected_item);
+ self->selected_item = new_selected;
+
+ if (old_position == GTK_INVALID_LIST_POSITION)
+ gtk_selection_model_selection_changed (GTK_SELECTION_MODEL (self), position, 1);
+ else if (position == GTK_INVALID_LIST_POSITION)
+ gtk_selection_model_selection_changed (GTK_SELECTION_MODEL (self), old_position, 1);
+ else if (position < old_position)
+ gtk_selection_model_selection_changed (GTK_SELECTION_MODEL (self), position, old_position - position + 1);
+ else
+ gtk_selection_model_selection_changed (GTK_SELECTION_MODEL (self), old_position, position - old_position + 1);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED]);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED_ITEM]);
+}
+
+static gboolean
+match_item (GtkSearchListModel *self,
+ guint position)
+{
+ gpointer item;
+ gboolean result;
+
+ item = g_list_model_get_item (self->model, position);
+ result = gtk_filter_match (self->filter, item);
+ g_object_unref (item);
+
+ return result;
+}
+
+static guint
+find_next_match (GtkSearchListModel *self,
+ guint position,
+ gboolean forward)
+{
+ guint i;
+
+ if (position == GTK_INVALID_LIST_POSITION)
+ position = 0;
+
+ g_print ("search %s from %u\n", forward ? "forward" : "backward", position);
+ if (forward)
+ for (i = position; i < g_list_model_get_n_items (self->model); i++)
+ {
+ if (match_item (self, i))
+ return i;
+ }
+ else
+ for (i = position; ; i--)
+ {
+ if (match_item (self, i))
+ return i;
+ if (i == 0)
+ break;
+ }
+
+ return GTK_INVALID_LIST_POSITION;
+}
+
+static void
+gtk_search_list_model_filter_changed_cb (GtkFilter *filter,
+ GtkFilterChange change,
+ GtkSearchListModel *self)
+{
+ guint position;
+
+g_print ("filter changed: change %d, strictness %d\n", change, gtk_filter_get_strictness (self->filter));
+
+ if (gtk_filter_get_strictness (self->filter) == GTK_FILTER_MATCH_NONE)
+ position = GTK_INVALID_LIST_POSITION;
+ else
+ switch (change)
+ {
+ case GTK_FILTER_CHANGE_DIFFERENT:
+ case GTK_FILTER_CHANGE_LESS_STRICT:
+ position = find_next_match (self, 0, TRUE);
+ break;
+ case GTK_FILTER_CHANGE_MORE_STRICT:
+ position = find_next_match (self, self->selected, TRUE);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ g_print ("select %u\n", position);
+ set_selected (self, position);
+}
+
+static void
+gtk_search_list_model_clear_model (GtkSearchListModel *self)
+{
+ if (self->model == NULL)
+ return;
+
+ g_signal_handlers_disconnect_by_func (self->model,
+ gtk_search_list_model_items_changed_cb,
+ self);
+ g_clear_object (&self->model);
+}
+
+static void
+gtk_search_list_model_clear_filter (GtkSearchListModel *self)
+{
+ if (self->filter == NULL)
+ return;
+
+ g_signal_handlers_disconnect_by_func (self->filter,
+ gtk_search_list_model_filter_changed_cb,
+ self);
+
+ g_clear_object (&self->filter);
+}
+
+static void
+gtk_search_list_model_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+
+{
+ GtkSearchListModel *self = GTK_SEARCH_LIST_MODEL (object);
+
+ switch (prop_id)
+ {
+ case PROP_MODEL:
+ self->model = g_value_dup_object (value);
+ g_signal_connect (self->model, "items-changed",
+ G_CALLBACK (gtk_search_list_model_items_changed_cb), self);
+ break;
+
+ case PROP_FILTER:
+ self->filter = g_value_dup_object (value);
+ g_signal_connect (self->filter, "changed",
+ G_CALLBACK (gtk_search_list_model_filter_changed_cb), self);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_search_list_model_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSearchListModel *self = GTK_SEARCH_LIST_MODEL (object);
+
+ switch (prop_id)
+ {
+ case PROP_MODEL:
+ g_value_set_object (value, self->model);
+ break;
+
+ case PROP_FILTER:
+ g_value_set_object (value, self->filter);
+ break;
+
+ case PROP_SELECTED:
+ g_value_set_uint (value, self->selected);
+ break;
+
+ case PROP_SELECTED_ITEM:
+ g_value_set_object (value, self->selected_item);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_search_list_model_dispose (GObject *object)
+{
+ GtkSearchListModel *self = GTK_SEARCH_LIST_MODEL (object);
+
+ gtk_search_list_model_clear_model (self);
+ gtk_search_list_model_clear_filter (self);
+
+ self->selected = GTK_INVALID_LIST_POSITION;
+ g_clear_object (&self->selected_item);
+
+ G_OBJECT_CLASS (gtk_search_list_model_parent_class)->dispose (object);
+}
+
+static void
+gtk_search_list_model_class_init (GtkSearchListModelClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->get_property = gtk_search_list_model_get_property;
+ gobject_class->set_property = gtk_search_list_model_set_property;
+ gobject_class->dispose = gtk_search_list_model_dispose;
+
+ /**
+ * GtkSearchListModel:selected:
+ *
+ * Position of the selected item
+ */
+ properties[PROP_SELECTED] =
+ g_param_spec_uint ("selected",
+ P_("Selected"),
+ P_("Position of the selected item"),
+ 0, G_MAXUINT, GTK_INVALID_LIST_POSITION,
+ G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * GtkSearchListModel:selected-item:
+ *
+ * The selected item
+ */
+ properties[PROP_SELECTED_ITEM] =
+ g_param_spec_object ("selected-item",
+ P_("Selected Item"),
+ P_("The selected item"),
+ G_TYPE_OBJECT,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * GtkSearchListModel:model:
+ *
+ * The model being managed
+ */
+ properties[PROP_MODEL] =
+ g_param_spec_object ("model",
+ P_("The model"),
+ P_("The model being managed"),
+ G_TYPE_LIST_MODEL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * GtkSearchListModel:filter:
+ *
+ * The filter determining the selected item
+ */
+ properties[PROP_FILTER] =
+ g_param_spec_object ("filter",
+ P_("The filter"),
+ P_("The filter being used"),
+ GTK_TYPE_FILTER,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (gobject_class, N_PROPS, properties);
+}
+
+static void
+gtk_search_list_model_init (GtkSearchListModel *self)
+{
+ self->selected = GTK_INVALID_LIST_POSITION;
+}
+
+/**
+ * gtk_search_list_model_new:
+ * @model: (transfer none): the #GListModel to manage
+ * @filter: (transfer none): the #GtkFilter to use
+ *
+ * Creates a new selection to handle @model.
+ *
+ * Returns: (transfer full) (type GtkSearchListModel): a new #GtkSearchListModel
+ **/
+GtkSearchListModel *
+gtk_search_list_model_new (GListModel *model,
+ GtkFilter *filter)
+{
+ g_return_val_if_fail (G_IS_LIST_MODEL (model), NULL);
+
+ return g_object_new (GTK_TYPE_SEARCH_LIST_MODEL,
+ "model", model,
+ "filter", filter,
+ NULL);
+}
+
+gboolean
+gtk_search_list_model_next_match (GtkSearchListModel *self)
+{
+ guint position;
+
+ position = find_next_match (self, self->selected, TRUE);
+ if (position == GTK_INVALID_LIST_POSITION)
+ return FALSE;
+
+ set_selected (self, position);
+
+ return TRUE;
+}
+
+gboolean
+gtk_search_list_model_previous_match (GtkSearchListModel *self)
+{
+ guint position;
+
+ position = find_next_match (self, self->selected, FALSE);
+ if (position == GTK_INVALID_LIST_POSITION)
+ return FALSE;
+
+ set_selected (self, position);
+
+ return TRUE;
+}
diff --git a/gtk/gtksearchlistmodel.h b/gtk/gtksearchlistmodel.h
new file mode 100644
index 0000000000..324449bbcd
--- /dev/null
+++ b/gtk/gtksearchlistmodel.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#ifndef __GTK_SEARCH_LIST_MODEL_H__
+#define __GTK_SEARCH_LIST_MODEL_H__
+
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#include <gio/gio.h>
+#include <gtk/gtkfilter.h>
+
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_SEARCH_LIST_MODEL (gtk_search_list_model_get_type ())
+
+GDK_AVAILABLE_IN_ALL
+G_DECLARE_FINAL_TYPE (GtkSearchListModel, gtk_search_list_model, GTK, SEARCH_LIST_MODEL, GObject)
+
+GDK_AVAILABLE_IN_ALL
+GtkSearchListModel * gtk_search_list_model_new (GListModel *model,
+ GtkFilter *filter);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_search_list_model_next_match (GtkSearchListModel *self);
+
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_search_list_model_previous_match (GtkSearchListModel *self);
+
+G_END_DECLS
+
+#endif /* __GTK_SEARCH_LIST_MODEL_H__ */
diff --git a/gtk/gtkstackswitcher.c b/gtk/gtkstackswitcher.c
index a5f3bbaeb1..c9d30fecf1 100644
--- a/gtk/gtkstackswitcher.c
+++ b/gtk/gtkstackswitcher.c
@@ -95,7 +95,10 @@ enum {
static void gtk_stack_switcher_drag_leave (GtkDropTarget *dest,
GdkDrop *drop,
GtkStackSwitcher *self);
-static gboolean gtk_stack_switcher_drag_motion (GtkDropTarget *dest,
+static gboolean gtk_stack_switcher_drag_accept (GtkDropTarget *dest,
+ GdkDrop *drop,
+ GtkStackSwitcher *self);
+static void gtk_stack_switcher_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y,
@@ -121,7 +124,8 @@ gtk_stack_switcher_init (GtkStackSwitcher *switcher)
dest = gtk_drop_target_new (formats, 0);
gdk_content_formats_unref (formats);
g_signal_connect (dest, "drag-leave", G_CALLBACK (gtk_stack_switcher_drag_leave), switcher);
- g_signal_connect (dest, "accept", G_CALLBACK (gtk_stack_switcher_drag_motion), switcher);
+ g_signal_connect (dest, "accept", G_CALLBACK (gtk_stack_switcher_drag_accept), switcher);
+ g_signal_connect (dest, "drag-motion", G_CALLBACK (gtk_stack_switcher_drag_motion), switcher);
gtk_widget_add_controller (GTK_WIDGET (switcher), GTK_EVENT_CONTROLLER (dest));
}
@@ -264,6 +268,14 @@ gtk_stack_switcher_switch_timeout (gpointer data)
}
static gboolean
+gtk_stack_switcher_drag_accept (GtkDropTarget *dest,
+ GdkDrop *drop,
+ GtkStackSwitcher *self)
+{
+ return TRUE;
+}
+
+static void
gtk_stack_switcher_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
@@ -274,7 +286,6 @@ gtk_stack_switcher_drag_motion (GtkDropTarget *dest,
GtkWidget *button;
GHashTableIter iter;
gpointer value;
- gboolean retval = FALSE;
button = NULL;
g_hash_table_iter_init (&iter, priv->buttons);
@@ -285,7 +296,6 @@ gtk_stack_switcher_drag_motion (GtkDropTarget *dest,
if (gtk_widget_contains (GTK_WIDGET (value), cx, cy))
{
button = GTK_WIDGET (value);
- retval = TRUE;
break;
}
}
@@ -302,8 +312,6 @@ gtk_stack_switcher_drag_motion (GtkDropTarget *dest,
self);
g_source_set_name_by_id (priv->switch_timer, "[gtk] gtk_stack_switcher_switch_timeout");
}
-
- return retval;
}
static void
diff --git a/gtk/gtktext.c b/gtk/gtktext.c
index 0c775301ec..45b9b3c82c 100644
--- a/gtk/gtktext.c
+++ b/gtk/gtktext.c
@@ -339,7 +339,10 @@ static gboolean gtk_text_drag_drop (GtkDropTarget *dest,
int x,
int y,
GtkText *text);
-static gboolean gtk_text_drag_motion (GtkDropTarget *dest,
+static gboolean gtk_text_drag_accept (GtkDropTarget *dest,
+ GdkDrop *drop,
+ GtkText *self);
+static void gtk_text_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y,
@@ -1732,7 +1735,8 @@ gtk_text_init (GtkText *self)
formats = gdk_content_formats_new_for_gtype (G_TYPE_STRING);
dest = gtk_drop_target_new (formats, GDK_ACTION_COPY | GDK_ACTION_MOVE);
- g_signal_connect (dest, "accept", G_CALLBACK (gtk_text_drag_motion), self);
+ g_signal_connect (dest, "accept", G_CALLBACK (gtk_text_drag_accept), self);
+ g_signal_connect (dest, "drag-motion", G_CALLBACK (gtk_text_drag_motion), self);
g_signal_connect (dest, "drag-leave", G_CALLBACK (gtk_text_drag_leave), self);
g_signal_connect (dest, "drag-drop", G_CALLBACK (gtk_text_drag_drop), self);
gdk_content_formats_unref (formats);
@@ -6230,6 +6234,29 @@ gtk_text_drag_drop (GtkDropTarget *dest,
}
static gboolean
+gtk_text_drag_accept (GtkDropTarget *dest,
+ GdkDrop *drop,
+ GtkText *self)
+{
+ GtkTextPrivate *priv = gtk_text_get_instance_private (self);
+ GdkDragAction suggested_action;
+
+ if (priv->editable &&
+ gtk_drop_target_find_mimetype (dest) != NULL)
+ {
+ suggested_action = GDK_ACTION_COPY | GDK_ACTION_MOVE;
+ }
+ else
+ {
+ /* Entry not editable, or no text */
+ suggested_action = 0;
+ }
+
+ gdk_drop_status (drop, suggested_action);
+ return suggested_action != 0;
+}
+
+static void
gtk_text_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
@@ -6237,8 +6264,6 @@ gtk_text_drag_motion (GtkDropTarget *dest,
GtkText *self)
{
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
- GtkWidget *widget = GTK_WIDGET (self);
- GdkDragAction suggested_action;
int new_position, old_position;
old_position = priv->dnd_position;
@@ -6247,8 +6272,6 @@ gtk_text_drag_motion (GtkDropTarget *dest,
if (priv->editable &&
gtk_drop_target_find_mimetype (dest) != NULL)
{
- suggested_action = GDK_ACTION_COPY | GDK_ACTION_MOVE;
-
if (priv->selection_bound == priv->current_pos ||
new_position < priv->selection_bound ||
new_position > priv->current_pos)
@@ -6263,16 +6286,11 @@ gtk_text_drag_motion (GtkDropTarget *dest,
else
{
/* Entry not editable, or no text */
- suggested_action = 0;
priv->dnd_position = -1;
}
- gdk_drop_status (drop, suggested_action);
-
if (priv->dnd_position != old_position)
- gtk_widget_queue_draw (widget);
-
- return TRUE;
+ gtk_widget_queue_draw (GTK_WIDGET (self));
}
/* We display the cursor when
diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c
index 21d0635a05..ed5f6ad90d 100644
--- a/gtk/gtktextview.c
+++ b/gtk/gtktextview.c
@@ -1638,7 +1638,7 @@ gtk_text_view_init (GtkTextView *text_view)
dest = gtk_drop_target_new (formats, GDK_ACTION_COPY | GDK_ACTION_MOVE);
gdk_content_formats_unref (formats);
g_signal_connect (dest, "drag-leave", G_CALLBACK (gtk_text_view_drag_leave), text_view);
- g_signal_connect (dest, "accept", G_CALLBACK (gtk_text_view_drag_motion), text_view);
+ g_signal_connect (dest, "drag-motion", G_CALLBACK (gtk_text_view_drag_motion), text_view);
g_signal_connect (dest, "drag-drop", G_CALLBACK (gtk_text_view_drag_drop), text_view);
gtk_widget_add_controller (GTK_WIDGET (text_view), GTK_EVENT_CONTROLLER (dest));
diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c
index 6dc7fa4004..003204cf1b 100644
--- a/gtk/gtktreeview.c
+++ b/gtk/gtktreeview.c
@@ -695,7 +695,7 @@ static GBytes *gtk_tree_view_drag_data_get (const char *mimetype,
static void gtk_tree_view_drag_leave (GtkDropTarget *dest,
GdkDrop *drop,
GtkTreeView *tree_view);
-static gboolean gtk_tree_view_drag_motion (GtkDropTarget *dest,
+static void gtk_tree_view_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y,
@@ -7244,7 +7244,7 @@ gtk_tree_view_drag_leave (GtkDropTarget *dest,
}
-static gboolean
+static void
gtk_tree_view_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
@@ -7258,7 +7258,10 @@ gtk_tree_view_drag_motion (GtkDropTarget *dest,
GdkAtom target;
if (!set_destination_row (tree_view, dest, x, y, &suggested_action, &target))
- return FALSE;
+ {
+ gdk_drop_status (drop, 0);
+ return;
+ }
tree_view->event_last_x = x;
tree_view->event_last_y = y;
@@ -7305,8 +7308,6 @@ gtk_tree_view_drag_motion (GtkDropTarget *dest,
if (path)
gtk_tree_path_free (path);
-
- return TRUE;
}
@@ -12924,7 +12925,7 @@ gtk_tree_view_enable_model_drag_dest (GtkTreeView *tree_view,
di->dest = gtk_drop_target_new (formats, actions);
g_signal_connect (di->dest, "drag-leave", G_CALLBACK (gtk_tree_view_drag_leave), tree_view);
- g_signal_connect (di->dest, "accept", G_CALLBACK (gtk_tree_view_drag_motion), tree_view);
+ g_signal_connect (di->dest, "drag-motion", G_CALLBACK (gtk_tree_view_drag_motion), tree_view);
g_signal_connect (di->dest, "drag-drop", G_CALLBACK (gtk_tree_view_drag_drop), tree_view);
gtk_widget_add_controller (GTK_WIDGET (tree_view), GTK_EVENT_CONTROLLER (di->dest));
g_object_ref (di->dest);