49 gtk_list_store_append(test->
store, &iter);
50 gtk_list_store_set(test->
store, &iter, 0, text, -1);
55 while(gtk_events_pending()) gtk_main_iteration();
60 g_main_loop_quit(loop);
61 return G_SOURCE_REMOVE;
66 GMainLoop *loop = g_main_loop_new(NULL,
FALSE);
68 g_main_loop_run(loop);
69 g_main_loop_unref(loop);
74 gboolean mapped =
FALSE;
75 GList *toplevels = gtk_window_list_toplevels();
76 for(GList *toplevel = toplevels; toplevel; toplevel = g_list_next(toplevel))
78 GtkWidget *widget = GTK_WIDGET(toplevel->data);
79 if(widget != entry_window && gtk_widget_get_mapped(widget)) mapped =
TRUE;
81 g_list_free(toplevels);
87 GdkEventKey
event = { 0 };
88 event.type = GDK_KEY_PRESS;
89 event.window = g_object_ref(gtk_widget_get_window(widget));
90 event.send_event =
TRUE;
91 event.time = GDK_CURRENT_TIME;
92 event.keyval = keyval;
93 gboolean handled =
FALSE;
94 g_signal_emit_by_name(widget,
"key-press-event", &event, &handled);
95 g_object_unref(event.window);
104 GdkDisplay *display = gtk_widget_get_display(widget);
105 GdkEvent *
event = gdk_event_new(GDK_KEY_PRESS);
106 event->key.window = g_object_ref(gtk_widget_get_window(gtk_widget_get_toplevel(widget)));
107 event->key.send_event =
TRUE;
108 event->key.time = GDK_CURRENT_TIME;
109 event->key.keyval = keyval;
110 gdk_event_set_device(event, gdk_seat_get_keyboard(gdk_display_get_default_seat(display)));
111 gtk_main_do_event(event);
112 gdk_event_free(event);
116 GtkTreeIter *iter, gpointer user_data)
118 gchar *candidate = NULL;
119 gtk_tree_model_get(gtk_entry_completion_get_model(completion), iter, 0, &candidate, -1);
120 const gchar *token = g_strrstr(
key,
",");
121 token = token ? token + 1 :
key;
122 while(*token ==
' ') token++;
123 const gboolean matches = g_str_has_prefix(candidate, token);
131 test->
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
132 test->
entry = GTK_ENTRY(gtk_entry_new());
135 g_object_set(test->
entry,
"im-module",
"gtk-im-context-simple", NULL);
136 test->
store = gtk_list_store_new(1, G_TYPE_STRING);
139 test->
completion = gtk_entry_completion_new();
140 gtk_entry_completion_set_model(test->
completion, GTK_TREE_MODEL(test->
store));
141 gtk_entry_completion_set_text_column(test->
completion, 0);
142 gtk_entry_completion_set_inline_completion(test->
completion,
TRUE);
143 gtk_entry_completion_set_popup_completion(test->
completion,
TRUE);
144 gtk_entry_completion_set_minimum_key_length(test->
completion, 1);
146 g_signal_connect(test->
completion,
"match-selected",
149 gtk_container_add(GTK_CONTAINER(test->
window), GTK_WIDGET(test->
entry));
150 gtk_widget_show_all(test->
window);
151 gtk_window_set_focus(GTK_WINDOW(test->
window), GTK_WIDGET(test->
entry));
152 gtk_window_present(GTK_WINDOW(test->
window));
153 gdk_window_focus(gtk_widget_get_window(test->
window), GDK_CURRENT_TIME);
155 GdkEvent *focus_event = gdk_event_new(GDK_FOCUS_CHANGE);
156 focus_event->focus_change.window = g_object_ref(gtk_widget_get_window(GTK_WIDGET(test->
entry)));
157 focus_event->focus_change.in =
TRUE;
158 gtk_widget_send_focus_change(GTK_WIDGET(test->
entry), focus_event);
159 gdk_event_free(focus_event);
160 assert_true(gtk_widget_has_focus(GTK_WIDGET(test->
entry)));
168 gtk_entry_set_completion(test->
entry, NULL);
169 gtk_widget_destroy(test->
window);
172 g_object_unref(test->
store);
179 if(event->keyval != GDK_KEY_Return)
return FALSE;
180 state->entry_calls++;
182 state->text = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
190 gtk_entry_set_text(test->
entry,
"subjects");
192 gtk_list_store_clear(test->
store);
197 assert_string_equal(gtk_entry_get_text(test->
entry),
"");
198 assert_ptr_equal(gtk_entry_get_completion(test->
entry), test->
completion);
206 gtk_entry_set_text(test->
entry,
"subjects");
209 assert_string_equal(gtk_entry_get_text(test->
entry),
"");
212 gtk_entry_set_text(test->
entry,
"subjects|animals, places");
215 assert_string_equal(gtk_entry_get_text(test->
entry),
"");
219 gtk_editable_insert_text(GTK_EDITABLE(test->
entry),
"places", -1, &
position);
221 gtk_entry_completion_insert_prefix(test->
completion);
224 assert_ptr_equal(gtk_entry_get_completion(test->
entry), test->
completion);
225 assert_string_equal(gtk_entry_get_text(test->
entry),
"places|france|paris");
230 GtkEntry *entry = GTK_ENTRY(gtk_entry_new());
231 gtk_entry_set_text(entry,
"places|france");
235 assert_string_equal(gtk_entry_get_text(entry),
"");
236 assert_null(gtk_entry_get_completion(entry));
237 gtk_widget_destroy(GTK_WIDGET(entry));
244 gtk_entry_set_text(test->
entry,
"subjects|animals, pla");
245 gtk_editable_set_position(GTK_EDITABLE(test->
entry), -1);
246 gtk_entry_completion_set_inline_completion(test->
completion,
TRUE);
248 assert_true(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(test->
store), &iter));
249 assert_true(gtk_tree_model_iter_next(GTK_TREE_MODEL(test->
store), &iter));
251 gboolean handled =
FALSE;
252 g_signal_emit_by_name(test->
completion,
"match-selected",
253 GTK_TREE_MODEL(test->
store), &iter, &handled);
256 assert_true(handled);
257 assert_string_equal(gtk_entry_get_text(test->
entry),
258 "subjects|animals,places|france|paris");
259 assert_true(gtk_entry_completion_get_inline_completion(test->
completion));
260 assert_ptr_equal(gtk_entry_get_completion(test->
entry), test->
completion);
273 gtk_editable_insert_text(GTK_EDITABLE(test->
entry),
"subjects|animals, pl", -1, &
position);
274 gtk_editable_set_position(GTK_EDITABLE(test->
entry), -1);
277 assert_string_equal(gtk_entry_get_text(test->
entry),
"subjects|animals, pla");
283 assert_string_equal(gtk_entry_get_text(test->
entry),
284 "subjects|animals,places|france|paris");
287 assert_true(gtk_entry_completion_get_inline_completion(test->
completion));
291 assert_string_equal(handler_state.
text,
"subjects|animals,places|france|paris");
294 g_free(handler_state.
text);
299 if(!gtk_init_check(&argc, &argv))
return 77;
300 const struct CMUnitTest tests[] = {
311 return cmocka_run_group_tests(tests, NULL, NULL);
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
const float uint32_t state[4]
GtkEntryCompletion * completion
gboolean dt_tagging_completion_match_selected(GtkEntryCompletion *completion, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
void dt_tagging_entry_clear(GtkEntry *entry, GCallback key_handler, gpointer user_data)
static void test_selected_completion_replaces_only_the_active_token(void **state)
static int _teardown_completion(void **state)
static void test_completion_survives_repeated_single_and_hierarchical_clears(void **state)
static void test_clear_cancels_completion_before_model_refresh(void **state)
static gboolean _send_key(GtkWidget *widget, const guint keyval)
static gboolean _quit_main_loop(GMainLoop *loop)
static void _type_key(GtkWidget *widget, const guint keyval)
static void _append_completion(dt_tagging_completion_test_t *test, const char *text)
static void _drain_gtk_events()
static gboolean _match_last_hierarchical_token(GtkEntryCompletion *completion, const gchar *key, GtkTreeIter *iter, gpointer user_data)
static gboolean _record_plain_return(GtkWidget *entry, GdkEventKey *event, dt_return_handler_state_t *state)
static void test_clear_supports_entry_without_completion(void **state)
static void test_completion_keeps_return_priority_after_reattach(void **state)
static void _wait_for_completion_sources()
static int _setup_completion(void **state)
static gboolean _completion_popup_is_mapped(GtkWidget *entry_window)