entry completion: Use a popover

This lets us remove a use of GTK_WINDOW_POPUP,
which should eventually be going away.

We need to disable treeview search, since it
creates a toplevel that will disrupt our grabbing
popup, causing it to be dismissed.

We don't need to grab ourselves, since the popover
code does it for us. We don't need to reposition our
window, since the popover takes care of that too.
This commit is contained in:
Matthias Clasen 2019-04-20 04:32:29 +00:00
parent 0d25233e39
commit c3c33ac168

View File

@ -79,8 +79,7 @@
#include "gtkscrolledwindow.h" #include "gtkscrolledwindow.h"
#include "gtksizerequest.h" #include "gtksizerequest.h"
#include "gtkbox.h" #include "gtkbox.h"
#include "gtkwindow.h" #include "gtkpopover.h"
#include "gtkwindowgroup.h"
#include "gtkentry.h" #include "gtkentry.h"
#include "gtkmain.h" #include "gtkmain.h"
#include "gtkmarshalers.h" #include "gtkmarshalers.h"
@ -526,6 +525,7 @@ gtk_entry_completion_constructed (GObject *object)
G_CALLBACK (gtk_entry_completion_list_activated), G_CALLBACK (gtk_entry_completion_list_activated),
completion); completion);
gtk_tree_view_set_enable_search (GTK_TREE_VIEW (priv->tree_view), FALSE);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree_view), FALSE); gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree_view), FALSE);
gtk_tree_view_set_hover_selection (GTK_TREE_VIEW (priv->tree_view), TRUE); gtk_tree_view_set_hover_selection (GTK_TREE_VIEW (priv->tree_view), TRUE);
gtk_tree_view_set_activate_on_single_click (GTK_TREE_VIEW (priv->tree_view), TRUE); gtk_tree_view_set_activate_on_single_click (GTK_TREE_VIEW (priv->tree_view), TRUE);
@ -561,6 +561,7 @@ gtk_entry_completion_constructed (GObject *object)
g_signal_connect (priv->action_view, "row-activated", g_signal_connect (priv->action_view, "row-activated",
G_CALLBACK (gtk_entry_completion_action_activated), G_CALLBACK (gtk_entry_completion_action_activated),
completion); completion);
gtk_tree_view_set_enable_search (GTK_TREE_VIEW (priv->action_view), FALSE);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->action_view), FALSE); gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->action_view), FALSE);
gtk_tree_view_set_hover_selection (GTK_TREE_VIEW (priv->action_view), TRUE); gtk_tree_view_set_hover_selection (GTK_TREE_VIEW (priv->action_view), TRUE);
gtk_tree_view_set_activate_on_single_click (GTK_TREE_VIEW (priv->action_view), TRUE); gtk_tree_view_set_activate_on_single_click (GTK_TREE_VIEW (priv->action_view), TRUE);
@ -578,9 +579,8 @@ gtk_entry_completion_constructed (GObject *object)
NULL); NULL);
/* pack it all */ /* pack it all */
priv->popup_window = gtk_window_new (GTK_WINDOW_POPUP); priv->popup_window = gtk_popover_new (NULL);
gtk_window_set_resizable (GTK_WINDOW (priv->popup_window), FALSE); gtk_popover_set_position (GTK_POPOVER (priv->popup_window), GTK_POS_BOTTOM);
gtk_window_set_type_hint (GTK_WINDOW(priv->popup_window), GDK_SURFACE_TYPE_HINT_COMBO);
controller = gtk_event_controller_key_new (); controller = gtk_event_controller_key_new ();
g_signal_connect (controller, "key-pressed", g_signal_connect (controller, "key-pressed",
@ -762,38 +762,12 @@ gtk_entry_completion_dispose (GObject *object)
GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (object); GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (object);
GtkEntryCompletionPrivate *priv = completion->priv; GtkEntryCompletionPrivate *priv = completion->priv;
if (priv->tree_view)
{
gtk_widget_destroy (priv->tree_view);
priv->tree_view = NULL;
}
if (priv->entry) if (priv->entry)
gtk_entry_set_completion (GTK_ENTRY (priv->entry), NULL); gtk_entry_set_completion (GTK_ENTRY (priv->entry), NULL);
if (priv->actions) g_clear_object (&priv->actions);
{ g_clear_object (&priv->action_view);
g_object_unref (priv->actions); g_clear_object (&priv->cell_area);
priv->actions = NULL;
}
if (priv->action_view)
{
g_object_unref (priv->action_view);
priv->action_view = NULL;
}
if (priv->popup_window)
{
gtk_widget_destroy (priv->popup_window);
priv->popup_window = NULL;
}
if (priv->cell_area)
{
g_object_unref (priv->cell_area);
priv->cell_area = NULL;
}
G_OBJECT_CLASS (gtk_entry_completion_parent_class)->dispose (object); G_OBJECT_CLASS (gtk_entry_completion_parent_class)->dispose (object);
} }
@ -1461,39 +1435,11 @@ _gtk_entry_completion_resize_popup (GtkEntryCompletion *completion)
NULL, FALSE, 0.0, 0.0); NULL, FALSE, 0.0, 0.0);
gtk_tree_path_free (path); gtk_tree_path_free (path);
} }
if (gtk_window_get_transient_for (GTK_WINDOW (completion->priv->popup_window)))
{
gdk_surface_move_to_rect (_gtk_widget_get_surface (completion->priv->popup_window),
&allocation,
GDK_GRAVITY_SOUTH,
GDK_GRAVITY_NORTH,
GDK_ANCHOR_FLIP_Y | GDK_ANCHOR_SLIDE_X,
0, 0);
gtk_widget_show (completion->priv->popup_window);
}
}
static void
prepare_popup_func (GdkSeat *seat,
GdkSurface *surface,
gpointer user_data)
{
GtkEntryCompletion *completion = user_data;
/* prevent the first row being focused */
gtk_widget_grab_focus (completion->priv->tree_view);
gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->tree_view)));
gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->action_view)));
gtk_widget_show (completion->priv->popup_window);
} }
static void static void
gtk_entry_completion_popup (GtkEntryCompletion *completion) gtk_entry_completion_popup (GtkEntryCompletion *completion)
{ {
GtkWidget *toplevel;
GtkText *text = gtk_entry_get_text_widget (GTK_ENTRY (completion->priv->entry)); GtkText *text = gtk_entry_get_text_widget (GTK_ENTRY (completion->priv->entry));
if (gtk_widget_get_mapped (completion->priv->popup_window)) if (gtk_widget_get_mapped (completion->priv->popup_window))
@ -1505,40 +1451,14 @@ gtk_entry_completion_popup (GtkEntryCompletion *completion)
if (!gtk_widget_has_focus (GTK_WIDGET (text))) if (!gtk_widget_has_focus (GTK_WIDGET (text)))
return; return;
if (completion->priv->has_grab)
return;
gtk_widget_show (completion->priv->vbox);
/* default on no match */ /* default on no match */
completion->priv->current_selected = -1; completion->priv->current_selected = -1;
toplevel = gtk_widget_get_toplevel (completion->priv->entry);
if (GTK_IS_WINDOW (toplevel))
{
gtk_window_set_transient_for (GTK_WINDOW (completion->priv->popup_window),
GTK_WINDOW (toplevel));
gtk_window_group_add_window (gtk_window_get_group (GTK_WINDOW (toplevel)),
GTK_WINDOW (completion->priv->popup_window));
}
gtk_window_set_display (GTK_WINDOW (completion->priv->popup_window),
gtk_widget_get_display (completion->priv->entry));
gtk_widget_realize (completion->priv->popup_window); gtk_widget_realize (completion->priv->popup_window);
_gtk_entry_completion_resize_popup (completion); _gtk_entry_completion_resize_popup (completion);
if (completion->priv->device) gtk_popover_popup (GTK_POPOVER (completion->priv->popup_window));
{
gtk_grab_add (completion->priv->popup_window);
gdk_seat_grab (gdk_device_get_seat (completion->priv->device),
gtk_widget_get_surface (completion->priv->popup_window),
GDK_SEAT_CAPABILITY_POINTER | GDK_SEAT_CAPABILITY_TOUCH,
TRUE, NULL, NULL,
prepare_popup_func, completion);
completion->priv->has_grab = TRUE;
}
} }
void void
@ -1547,14 +1467,7 @@ _gtk_entry_completion_popdown (GtkEntryCompletion *completion)
if (!gtk_widget_get_mapped (completion->priv->popup_window)) if (!gtk_widget_get_mapped (completion->priv->popup_window))
return; return;
if (completion->priv->has_grab) gtk_popover_popdown (GTK_POPOVER (completion->priv->popup_window));
{
gdk_seat_ungrab (gdk_device_get_seat (completion->priv->device));
gtk_grab_remove (completion->priv->popup_window);
completion->priv->has_grab = FALSE;
}
gtk_widget_hide (completion->priv->popup_window);
} }
static gboolean static gboolean
@ -2036,8 +1949,7 @@ gtk_entry_completion_timeout (gpointer data)
} }
else if (gtk_widget_get_visible (completion->priv->popup_window)) else if (gtk_widget_get_visible (completion->priv->popup_window))
_gtk_entry_completion_popdown (completion); _gtk_entry_completion_popdown (completion);
return G_SOURCE_REMOVE;
return FALSE;
} }
static inline gboolean static inline gboolean
@ -2428,6 +2340,15 @@ accept_completion_callback (GtkEntryCompletion *completion)
return FALSE; return FALSE;
} }
static gboolean
text_focus_out (GtkEntryCompletion *completion)
{
if (gtk_widget_get_mapped (completion->priv->popup_window))
return FALSE;
return accept_completion_callback (completion);
}
static void static void
completion_insert_text_callback (GtkText *entry, completion_insert_text_callback (GtkText *entry,
const gchar *text, const gchar *text,
@ -2461,7 +2382,7 @@ connect_completion_signals (GtkEntryCompletion *completion)
controller = priv->entry_key_controller = gtk_event_controller_key_new (); controller = priv->entry_key_controller = gtk_event_controller_key_new ();
g_signal_connect (controller, "key-pressed", g_signal_connect (controller, "key-pressed",
G_CALLBACK (gtk_entry_completion_key_pressed), completion); G_CALLBACK (gtk_entry_completion_key_pressed), completion);
g_signal_connect_swapped (controller, "focus-out", G_CALLBACK (accept_completion_callback), completion); g_signal_connect_swapped (controller, "focus-out", G_CALLBACK (text_focus_out), completion);
gtk_widget_add_controller (GTK_WIDGET (text), controller); gtk_widget_add_controller (GTK_WIDGET (text), controller);
completion->priv->changed_id = completion->priv->changed_id =
@ -2548,10 +2469,8 @@ _gtk_entry_completion_disconnect (GtkEntryCompletion *completion)
unset_accessible_relation (completion->priv->popup_window, unset_accessible_relation (completion->priv->popup_window,
completion->priv->entry); completion->priv->entry);
gtk_window_set_attached_to (GTK_WINDOW (completion->priv->popup_window), gtk_popover_set_relative_to (GTK_POPOVER (completion->priv->popup_window),
NULL); NULL);
gtk_window_set_transient_for (GTK_WINDOW (completion->priv->popup_window), NULL);
completion->priv->entry = NULL; completion->priv->entry = NULL;
} }
@ -2564,7 +2483,7 @@ _gtk_entry_completion_connect (GtkEntryCompletion *completion,
set_accessible_relation (completion->priv->popup_window, set_accessible_relation (completion->priv->popup_window,
completion->priv->entry); completion->priv->entry);
gtk_window_set_attached_to (GTK_WINDOW (completion->priv->popup_window), gtk_popover_set_relative_to (GTK_POPOVER (completion->priv->popup_window),
completion->priv->entry); completion->priv->entry);
connect_completion_signals (completion); connect_completion_signals (completion);