diff options
author | Alexander Mikhaylenko <alexm@gnome.org> | 2022-03-23 15:14:48 +0400 |
---|---|---|
committer | Alexander Mikhaylenko <alexm@gnome.org> | 2022-03-23 15:31:29 +0400 |
commit | 56f0e359e90b7a625a78a72393defff8c2197fef (patch) | |
tree | 65b064f452dc957944ce05f774875d6cc4c0d954 /lib | |
parent | 1e4c397c3e2fe003bf1afbc229408ff21a4a3373 (diff) | |
download | epiphany-56f0e359e90b7a625a78a72393defff8c2197fef.tar.gz |
location-entry: Reorder functions
Match the GTK4 order to reduce the diff.
Part-of: <https://gitlab.gnome.org/GNOME/epiphany/-/merge_requests/1099>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/widgets/ephy-location-entry.c | 1218 |
1 files changed, 608 insertions, 610 deletions
diff --git a/lib/widgets/ephy-location-entry.c b/lib/widgets/ephy-location-entry.c index e6b7b1689..a177c2462 100644 --- a/lib/widgets/ephy-location-entry.c +++ b/lib/widgets/ephy-location-entry.c @@ -107,304 +107,119 @@ enum signalsEnum { static gint signals[LAST_SIGNAL] = { 0 }; static void ephy_location_entry_title_widget_interface_init (EphyTitleWidgetInterface *iface); -static void schedule_dns_prefetch (EphyLocationEntry *entry, - const gchar *url); G_DEFINE_TYPE_WITH_CODE (EphyLocationEntry, ephy_location_entry, GTK_TYPE_BIN, G_IMPLEMENT_INTERFACE (EPHY_TYPE_TITLE_WIDGET, ephy_location_entry_title_widget_interface_init)) -static gboolean -entry_button_release (GtkWidget *widget, - GdkEvent *event, - gpointer user_data) -{ - EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (user_data); - if (((GdkEventButton *)event)->button != GDK_BUTTON_PRIMARY) - return GDK_EVENT_PROPAGATE; - - gtk_editable_select_region (GTK_EDITABLE (entry->url_entry), 0, -1); - - g_signal_handlers_block_by_func (widget, G_CALLBACK (entry_button_release), entry); - entry->button_release_is_blocked = TRUE; - - return GDK_EVENT_STOP; -} +typedef struct { + GUri *uri; + EphyLocationEntry *entry; +} PrefetchHelper; static void -update_entry_style (EphyLocationEntry *self) -{ - PangoAttrList *attrs; - PangoAttribute *color_normal; - PangoAttribute *color_dimmed; - PangoAttribute *scaled; - g_autoptr (GUri) uri = NULL; - const char *text = gtk_entry_get_text (GTK_ENTRY (self->url_entry)); - const char *host; - const char *base_domain; - char *sub_string; - - attrs = pango_attr_list_new (); - - if (self->adaptive_mode == EPHY_ADAPTIVE_MODE_NARROW) { - scaled = pango_attr_scale_new (PANGO_SCALE_SMALL); - pango_attr_list_insert (attrs, scaled); - } - - if (gtk_widget_has_focus (self->url_entry)) - goto out; - - uri = g_uri_parse (text, G_URI_FLAGS_NONE, NULL); - if (!uri) - goto out; - - host = g_uri_get_host (uri); - if (!host || strlen (host) == 0) - goto out; - - base_domain = soup_tld_get_base_domain (host, NULL); - if (!base_domain) - goto out; - - sub_string = strstr (text, base_domain); - if (!sub_string) - goto out; - - /* Complete text is dimmed */ - color_dimmed = pango_attr_foreground_alpha_new (32768); - pango_attr_list_insert (attrs, color_dimmed); - - /* Base domain with normal style */ - color_normal = pango_attr_foreground_alpha_new (65535); - color_normal->start_index = sub_string - text; - color_normal->end_index = color_normal->start_index + strlen (base_domain); - pango_attr_list_insert (attrs, color_normal); - -out: - gtk_entry_set_attributes (GTK_ENTRY (self->url_entry), attrs); - pango_attr_list_unref (attrs); -} - -static gboolean -entry_focus_in_event (GtkWidget *widget, - GdkEvent *event, - gpointer user_data) +free_prefetch_helper (PrefetchHelper *helper) { - EphyLocationEntry *self = EPHY_LOCATION_ENTRY (user_data); - - update_entry_style (self); - return GDK_EVENT_PROPAGATE; + g_uri_unref (helper->uri); + g_object_unref (helper->entry); + g_free (helper); } static gboolean -entry_focus_out_event (GtkWidget *widget, - GdkEvent *event, - gpointer user_data) -{ - EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (user_data); - - update_entry_style (entry); - - if (((GdkEventButton *)event)->button != GDK_BUTTON_PRIMARY) - return GDK_EVENT_PROPAGATE; - - /* Unselect. */ - gtk_editable_select_region (GTK_EDITABLE (entry->url_entry), 0, 0); - - if (entry->button_release_is_blocked) { - g_signal_handlers_unblock_by_func (widget, G_CALLBACK (entry_button_release), entry); - entry->button_release_is_blocked = FALSE; - } - - return GDK_EVENT_PROPAGATE; -} - -static void -editable_changed_cb (GtkEditable *editable, - EphyLocationEntry *entry); - -static void -ephy_location_entry_activate (EphyLocationEntry *entry) +do_dns_prefetch (PrefetchHelper *helper) { - g_signal_emit_by_name (entry->url_entry, "activate"); -} + EphyEmbedShell *shell = ephy_embed_shell_get_default (); -static const char * -ephy_location_entry_title_widget_get_address (EphyTitleWidget *widget) -{ - EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (widget); + if (helper->uri) + webkit_web_context_prefetch_dns (ephy_embed_shell_get_web_context (shell), g_uri_get_host (helper->uri)); - g_assert (entry); + helper->entry->dns_prefetch_handle_id = 0; - return gtk_entry_get_text (GTK_ENTRY (entry->url_entry)); + return G_SOURCE_REMOVE; } +/* + * Note: As we do not have access to WebKitNetworkProxyMode, and because + * Epiphany does not ever change it, we are just checking system default proxy. + */ static void -ephy_location_entry_title_widget_set_address (EphyTitleWidget *widget, - const char *address) +proxy_resolver_ready_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) { - EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (widget); - GtkClipboard *clipboard; - const char *text; - g_autofree char *effective_text = NULL; - g_autofree char *selection = NULL; - int start, end; - const char *final_text; - - g_assert (widget); - - /* Setting a new text will clear the clipboard. This makes it impossible - * to copy&paste from the location entry of one tab into another tab, see - * bug #155824. So we save the selection iff the clipboard was owned by - * the location entry. - */ - if (gtk_widget_get_realized (GTK_WIDGET (entry))) { - clipboard = gtk_widget_get_clipboard (GTK_WIDGET (entry->url_entry), - GDK_SELECTION_PRIMARY); - g_assert (clipboard != NULL); - - if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (entry->url_entry) && - gtk_editable_get_selection_bounds (GTK_EDITABLE (entry->url_entry), - &start, &end)) { - selection = gtk_editable_get_chars (GTK_EDITABLE (entry->url_entry), - start, end); - } - } + PrefetchHelper *helper = user_data; + GProxyResolver *resolver = G_PROXY_RESOLVER (object); + g_autoptr (GError) error = NULL; + g_auto (GStrv) proxies = NULL; - if (address != NULL) { - if (g_str_has_prefix (address, EPHY_ABOUT_SCHEME)) - effective_text = g_strdup_printf ("about:%s", - address + strlen (EPHY_ABOUT_SCHEME) + 1); - text = address; - } else { - text = ""; + proxies = g_proxy_resolver_lookup_finish (resolver, result, &error); + if (error != NULL) { + free_prefetch_helper (helper); + return; } - final_text = effective_text ? effective_text : text; - - entry->block_update = TRUE; - g_signal_handlers_block_by_func (entry->url_entry, G_CALLBACK (editable_changed_cb), entry); - gtk_entry_set_text (GTK_ENTRY (entry->url_entry), final_text); - update_entry_style (entry); - g_signal_handlers_unblock_by_func (entry->url_entry, G_CALLBACK (editable_changed_cb), entry); - - dzl_suggestion_entry_hide_suggestions (DZL_SUGGESTION_ENTRY (entry->url_entry)); - entry->block_update = FALSE; - - /* Now restore the selection. - * Note that it's not owned by the entry anymore! - */ - if (selection != NULL) { - gtk_clipboard_set_text (gtk_clipboard_get (GDK_SELECTION_PRIMARY), - selection, strlen (selection)); + if (proxies != NULL && (g_strv_length (proxies) > 1 || g_strcmp0 (proxies[0], "direct://") != 0)) { + free_prefetch_helper (helper); + return; } -} -static EphySecurityLevel -ephy_location_entry_title_widget_get_security_level (EphyTitleWidget *widget) -{ - EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (widget); - - g_assert (entry); - - return entry->security_level; + g_clear_handle_id (&helper->entry->dns_prefetch_handle_id, g_source_remove); + helper->entry->dns_prefetch_handle_id = + g_timeout_add_full (G_PRIORITY_DEFAULT, + 250, + (GSourceFunc)do_dns_prefetch, + helper, + (GDestroyNotify)free_prefetch_helper); + g_source_set_name_by_id (helper->entry->dns_prefetch_handle_id, "[epiphany] do_dns_prefetch"); } static void -ephy_location_entry_title_widget_set_security_level (EphyTitleWidget *widget, - EphySecurityLevel security_level) - +schedule_dns_prefetch (EphyLocationEntry *entry, + const gchar *url) { - EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (widget); - const char *icon_name; - - g_assert (entry); - - if (!entry->reader_mode_active) { - icon_name = ephy_security_level_to_icon_name (security_level); - gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry->url_entry), - GTK_ENTRY_ICON_PRIMARY, - icon_name); - } else { - gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry->url_entry), - GTK_ENTRY_ICON_PRIMARY, - NULL); - } - - entry->security_level = security_level; -} + GProxyResolver *resolver = g_proxy_resolver_get_default (); + PrefetchHelper *helper; + g_autoptr (GUri) uri = NULL; -static void -ephy_location_entry_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (object); + if (resolver == NULL) + return; - switch (prop_id) { - case PROP_ADDRESS: - ephy_title_widget_set_address (EPHY_TITLE_WIDGET (entry), - g_value_get_string (value)); - break; - case PROP_SECURITY_LEVEL: - ephy_title_widget_set_security_level (EPHY_TITLE_WIDGET (entry), - g_value_get_enum (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} + uri = g_uri_parse (url, G_URI_FLAGS_NONE, NULL); + if (!uri || !g_uri_get_host (uri)) + return; -static void -ephy_location_entry_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (object); + helper = g_new0 (PrefetchHelper, 1); + helper->entry = g_object_ref (entry); + helper->uri = g_steal_pointer (&uri); - switch (prop_id) { - case PROP_ADDRESS: - g_value_set_string (value, ephy_title_widget_get_address (EPHY_TITLE_WIDGET (entry))); - break; - case PROP_SECURITY_LEVEL: - g_value_set_enum (value, ephy_title_widget_get_security_level (EPHY_TITLE_WIDGET (entry))); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } + g_proxy_resolver_lookup_async (resolver, url, NULL, proxy_resolver_ready_cb, helper); } static void -ephy_location_entry_constructed (GObject *object) -{ - EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (object); - - G_OBJECT_CLASS (ephy_location_entry_parent_class)->constructed (object); - - gtk_entry_set_input_hints (GTK_ENTRY (entry->url_entry), GTK_INPUT_HINT_NO_EMOJI); -} +editable_changed_cb (GtkEditable *editable, + EphyLocationEntry *entry); static void -ephy_location_entry_finalize (GObject *object) +suggestion_selected (DzlSuggestionEntry *entry, + DzlSuggestion *suggestion, + gpointer user_data) { - EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (object); - - g_free (entry->saved_text); - g_clear_pointer (&entry->jump_tab, g_free); + EphyLocationEntry *lentry = EPHY_LOCATION_ENTRY (user_data); + const gchar *uri = dzl_suggestion_get_id (suggestion); - G_OBJECT_CLASS (ephy_location_entry_parent_class)->finalize (object); -} + g_signal_handlers_block_by_func (entry, G_CALLBACK (editable_changed_cb), user_data); + g_clear_pointer (&lentry->jump_tab, g_free); -static void -ephy_location_entry_get_preferred_height (GtkWidget *widget, - gint *minimum_height, - gint *natural_height) -{ - EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (widget); + if (g_str_has_prefix (uri, "ephy-tab://")) { + lentry->jump_tab = g_strdup (uri); + gtk_entry_set_text (GTK_ENTRY (entry), dzl_suggestion_get_subtitle (suggestion)); + } else { + gtk_entry_set_text (GTK_ENTRY (entry), uri); + } + gtk_editable_set_position (GTK_EDITABLE (entry), -1); + g_signal_handlers_unblock_by_func (entry, G_CALLBACK (editable_changed_cb), user_data); - gtk_widget_get_preferred_height (entry->url_entry, minimum_height, natural_height); + schedule_dns_prefetch (lentry, uri); } static void @@ -453,139 +268,41 @@ ephy_location_entry_cut_clipboard (GtkEntry *entry) } static void -ephy_location_entry_title_widget_interface_init (EphyTitleWidgetInterface *iface) +entry_redo_activate_cb (GtkMenuItem *item, + EphyLocationEntry *entry) { - iface->get_address = ephy_location_entry_title_widget_get_address; - iface->set_address = ephy_location_entry_title_widget_set_address; - iface->get_security_level = ephy_location_entry_title_widget_get_security_level; - iface->set_security_level = ephy_location_entry_title_widget_set_security_level; + ephy_location_entry_undo_reset (entry); } static void -ephy_location_entry_dispose (GObject *object) +entry_undo_activate_cb (GtkMenuItem *item, + EphyLocationEntry *entry) { - EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (object); - - g_clear_handle_id (&entry->progress_timeout, g_source_remove); - - g_clear_object (&entry->css_provider); - - G_OBJECT_CLASS (ephy_location_entry_parent_class)->dispose (object); + ephy_location_entry_reset (entry); } - -static void -ephy_location_entry_class_init (EphyLocationEntryClass *klass) +static gboolean +entry_button_release (GtkWidget *widget, + GdkEvent *event, + gpointer user_data) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - - object_class->get_property = ephy_location_entry_get_property; - object_class->set_property = ephy_location_entry_set_property; - object_class->constructed = ephy_location_entry_constructed; - object_class->finalize = ephy_location_entry_finalize; - object_class->dispose = ephy_location_entry_dispose; - - widget_class->get_preferred_height = ephy_location_entry_get_preferred_height; - - g_object_class_override_property (object_class, PROP_ADDRESS, "address"); - g_object_class_override_property (object_class, PROP_SECURITY_LEVEL, "security-level"); - - /** - * EphyLocationEntry::activate: - * @flags: the #GdkModifierType from the activation event - * - * Emitted when the entry is activated. - * - */ - signals[ACTIVATE] = g_signal_new ("activate", G_OBJECT_CLASS_TYPE (klass), - G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, - 1, - GDK_TYPE_MODIFIER_TYPE); + EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (user_data); - /** - * EphyLocationEntry::user-changed: - * @entry: the object on which the signal is emitted - * - * Emitted when the user changes the contents of the internal #GtkEntry - * - */ - signals[USER_CHANGED] = g_signal_new ("user_changed", G_OBJECT_CLASS_TYPE (klass), - G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, - 0, - G_TYPE_NONE); + if (((GdkEventButton *)event)->button != GDK_BUTTON_PRIMARY) + return GDK_EVENT_PROPAGATE; - /** - * EphyLocationEntry::reader-mode-changed: - * @entry: the object on which the signal is emitted - * @active: whether reader mode is active - * - * Emitted when the user clicks the reader mode icon inside the - * #EphyLocationEntry. - * - */ - signals[READER_MODE_CHANGED] = g_signal_new ("reader-mode-changed", G_OBJECT_CLASS_TYPE (klass), - G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, - 1, - G_TYPE_BOOLEAN); + gtk_editable_select_region (GTK_EDITABLE (entry->url_entry), 0, -1); - /** - * EphyLocationEntry::get-location: - * @entry: the object on which the signal is emitted - * Returns: the current page address as a string - * - * For drag and drop purposes, the location bar will request you the - * real address of where it is pointing to. The signal handler for this - * function should return the address of the currently loaded site. - * - */ - signals[GET_LOCATION] = g_signal_new ("get-location", G_OBJECT_CLASS_TYPE (klass), - G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST, - 0, ephy_signal_accumulator_string, - NULL, NULL, - G_TYPE_STRING, - 0, - G_TYPE_NONE); + g_signal_handlers_block_by_func (widget, G_CALLBACK (entry_button_release), entry); + entry->button_release_is_blocked = TRUE; - /** - * EphyLocationEntry::get-title: - * @entry: the object on which the signal is emitted - * Returns: the current page title as a string - * - * For drag and drop purposes, the location bar will request you the - * title of where it is pointing to. The signal handler for this - * function should return the title of the currently loaded site. - * - */ - signals[GET_TITLE] = g_signal_new ("get-title", G_OBJECT_CLASS_TYPE (klass), - G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST, - 0, ephy_signal_accumulator_string, - NULL, NULL, - G_TYPE_STRING, - 0, - G_TYPE_NONE); + return GDK_EVENT_STOP; } static void -editable_changed_cb (GtkEditable *editable, - EphyLocationEntry *entry) +ephy_location_entry_activate (EphyLocationEntry *entry) { - if (entry->block_update == TRUE) - return; - else { - entry->user_changed = TRUE; - entry->can_redo = FALSE; - } - - g_clear_pointer (&entry->jump_tab, g_free); - - g_signal_emit (entry, signals[USER_CHANGED], 0); + g_signal_emit_by_name (entry->url_entry, "activate"); } static gboolean @@ -656,140 +373,121 @@ entry_key_press_cb (GtkEntry *entry, } static void -entry_clear_activate_cb (GtkMenuItem *item, - EphyLocationEntry *entry) +handle_forward_tab_key (GtkWidget *widget, + gpointer user_data) { - entry->block_update = TRUE; - g_signal_handlers_block_by_func (entry->url_entry, G_CALLBACK (editable_changed_cb), entry); - gtk_entry_set_text (GTK_ENTRY (entry->url_entry), ""); - g_signal_handlers_unblock_by_func (entry->url_entry, G_CALLBACK (editable_changed_cb), entry); - entry->block_update = FALSE; - entry->user_changed = TRUE; -} + EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (user_data); + GtkWidget *popover; -static void -paste_received (GtkClipboard *clipboard, - const gchar *text, - EphyLocationEntry *entry) -{ - if (text) { - g_signal_handlers_block_by_func (entry->url_entry, G_CALLBACK (editable_changed_cb), entry); - gtk_entry_set_text (GTK_ENTRY (entry->url_entry), text); - ephy_location_entry_activate (entry); - g_signal_handlers_unblock_by_func (entry->url_entry, G_CALLBACK (editable_changed_cb), entry); + popover = dzl_suggestion_entry_get_popover (DZL_SUGGESTION_ENTRY (entry->url_entry)); + if (gtk_widget_is_visible (popover)) { + g_signal_emit_by_name (entry->url_entry, "move-suggestion", 1, G_TYPE_INT, 1, G_TYPE_NONE); + } else { + gtk_widget_child_focus (gtk_widget_get_toplevel (GTK_WIDGET (entry)), GTK_DIR_TAB_FORWARD); } } static void -entry_paste_and_go_activate_cb (GtkMenuItem *item, - EphyLocationEntry *entry) +handle_backward_tab_key (GtkWidget *widget, + gpointer user_data) { - GtkClipboard *clipboard; + EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (user_data); + GtkWidget *popover; - clipboard = gtk_clipboard_get_default (gdk_display_get_default ()); - gtk_clipboard_request_text (clipboard, - (GtkClipboardTextReceivedFunc)paste_received, - entry); + popover = dzl_suggestion_entry_get_popover (DZL_SUGGESTION_ENTRY (entry->url_entry)); + if (gtk_widget_is_visible (popover)) { + g_signal_emit_by_name (entry->url_entry, "move-suggestion", -1, G_TYPE_INT, 1, G_TYPE_NONE); + } else { + gtk_widget_child_focus (gtk_widget_get_toplevel (GTK_WIDGET (entry)), GTK_DIR_TAB_BACKWARD); + } } static void -entry_redo_activate_cb (GtkMenuItem *item, - EphyLocationEntry *entry) +update_entry_style (EphyLocationEntry *self) { - ephy_location_entry_undo_reset (entry); -} + PangoAttrList *attrs; + PangoAttribute *color_normal; + PangoAttribute *color_dimmed; + PangoAttribute *scaled; + g_autoptr (GUri) uri = NULL; + const char *text = gtk_entry_get_text (GTK_ENTRY (self->url_entry)); + const char *host; + const char *base_domain; + char *sub_string; -static void -entry_undo_activate_cb (GtkMenuItem *item, - EphyLocationEntry *entry) -{ - ephy_location_entry_reset (entry); -} + attrs = pango_attr_list_new (); -/* The build should fail here each time when upgrading to a new major version - * of GTK+, so that we don't forget to update this domain. - */ -#if GTK_MAJOR_VERSION == 3 -#define GTK_GETTEXT_DOMAIN "gtk30" -#endif + if (self->adaptive_mode == EPHY_ADAPTIVE_MODE_NARROW) { + scaled = pango_attr_scale_new (PANGO_SCALE_SMALL); + pango_attr_list_insert (attrs, scaled); + } -static void -entry_populate_popup_cb (GtkEntry *entry, - GtkMenu *menu, - EphyLocationEntry *lentry) -{ - GtkWidget *clear_menuitem; - GtkWidget *undo_menuitem; - GtkWidget *redo_menuitem; - GtkWidget *paste_and_go_menuitem; - GtkWidget *separator; - GtkWidget *paste_menuitem = NULL; - GList *children, *item; - int pos = 0, sep = 0; - gboolean is_editable; + if (gtk_widget_has_focus (self->url_entry)) + goto out; - /* Translators: the mnemonic shouldn't conflict with any of the - * standard items in the GtkEntry context menu (Cut, Copy, Paste, Delete, - * Select All, Input Methods and Insert Unicode control character.) - */ - clear_menuitem = gtk_menu_item_new_with_mnemonic (_("Cl_ear")); - g_signal_connect (clear_menuitem, "activate", - G_CALLBACK (entry_clear_activate_cb), lentry); - is_editable = gtk_editable_get_editable (GTK_EDITABLE (entry)); - gtk_widget_set_sensitive (clear_menuitem, is_editable); - gtk_widget_show (clear_menuitem); + uri = g_uri_parse (text, G_URI_FLAGS_NONE, NULL); + if (!uri) + goto out; - /* search for the 2nd separator (the one after Select All) in the context - * menu, and insert this menu item before it. - * It's a bit of a hack, but there seems to be no better way to do it :/ - */ - children = gtk_container_get_children (GTK_CONTAINER (menu)); - for (item = children; item != NULL && sep < 2; item = item->next, pos++) { - if (GTK_IS_SEPARATOR_MENU_ITEM (item->data)) - sep++; - } - g_list_free (children); + host = g_uri_get_host (uri); + if (!host || strlen (host) == 0) + goto out; - gtk_menu_shell_insert (GTK_MENU_SHELL (menu), clear_menuitem, pos - 1); + base_domain = soup_tld_get_base_domain (host, NULL); + if (!base_domain) + goto out; - paste_and_go_menuitem = gtk_menu_item_new_with_mnemonic (_("Paste and _Go")); + sub_string = strstr (text, base_domain); + if (!sub_string) + goto out; - /* Search for the Paste menu item and insert right after it. */ - children = gtk_container_get_children (GTK_CONTAINER (menu)); - for (item = children, pos = 0; item != NULL; item = item->next, pos++) { - if (g_strcmp0 (gtk_menu_item_get_label (item->data), g_dgettext (GTK_GETTEXT_DOMAIN, "_Paste")) == 0) { - paste_menuitem = item->data; - break; - } - } - g_assert (paste_menuitem != NULL); - g_list_free (children); + /* Complete text is dimmed */ + color_dimmed = pango_attr_foreground_alpha_new (32768); + pango_attr_list_insert (attrs, color_dimmed); - g_signal_connect (paste_and_go_menuitem, "activate", - G_CALLBACK (entry_paste_and_go_activate_cb), lentry); - lentry->paste_binding = g_object_bind_property (paste_menuitem, "sensitive", - paste_and_go_menuitem, "sensitive", - G_BINDING_SYNC_CREATE); - gtk_widget_show (paste_and_go_menuitem); - gtk_menu_shell_insert (GTK_MENU_SHELL (menu), paste_and_go_menuitem, pos + 1); + /* Base domain with normal style */ + color_normal = pango_attr_foreground_alpha_new (65535); + color_normal->start_index = sub_string - text; + color_normal->end_index = color_normal->start_index + strlen (base_domain); + pango_attr_list_insert (attrs, color_normal); - undo_menuitem = gtk_menu_item_new_with_mnemonic (_("_Undo")); - gtk_widget_set_sensitive (undo_menuitem, lentry->user_changed); - g_signal_connect (undo_menuitem, "activate", - G_CALLBACK (entry_undo_activate_cb), lentry); - gtk_widget_show (undo_menuitem); - gtk_menu_shell_insert (GTK_MENU_SHELL (menu), undo_menuitem, 0); +out: + gtk_entry_set_attributes (GTK_ENTRY (self->url_entry), attrs); + pango_attr_list_unref (attrs); +} - redo_menuitem = gtk_menu_item_new_with_mnemonic (_("_Redo")); - gtk_widget_set_sensitive (redo_menuitem, lentry->can_redo); - g_signal_connect (redo_menuitem, "activate", - G_CALLBACK (entry_redo_activate_cb), lentry); - gtk_widget_show (redo_menuitem); - gtk_menu_shell_insert (GTK_MENU_SHELL (menu), redo_menuitem, 1); +static gboolean +entry_focus_in_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data) +{ + EphyLocationEntry *self = EPHY_LOCATION_ENTRY (user_data); - separator = gtk_separator_menu_item_new (); - gtk_widget_show (separator); - gtk_menu_shell_insert (GTK_MENU_SHELL (menu), separator, 2); + update_entry_style (self); + return GDK_EVENT_PROPAGATE; +} + +static gboolean +entry_focus_out_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data) +{ + EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (user_data); + + update_entry_style (entry); + + if (((GdkEventButton *)event)->button != GDK_BUTTON_PRIMARY) + return GDK_EVENT_PROPAGATE; + + /* Unselect. */ + gtk_editable_select_region (GTK_EDITABLE (entry->url_entry), 0, 0); + + if (entry->button_release_is_blocked) { + g_signal_handlers_unblock_by_func (widget, G_CALLBACK (entry_button_release), entry); + entry->button_release_is_blocked = FALSE; + } + + return GDK_EVENT_PROPAGATE; } static gboolean @@ -896,6 +594,47 @@ event_button_press_event_cb (GtkWidget *widget, } static void +enter_notify_cb (GtkWidget *widget, + GdkEvent *event, + gpointer user_data) +{ + gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_PRELIGHT, FALSE); +} + +static void +leave_notify_cb (GtkWidget *widget, + GdkEvent *event, + gpointer user_data) +{ + gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_PRELIGHT); +} + +static void +editable_changed_cb (GtkEditable *editable, + EphyLocationEntry *entry) +{ + if (entry->block_update == TRUE) + return; + else { + entry->user_changed = TRUE; + entry->can_redo = FALSE; + } + + g_clear_pointer (&entry->jump_tab, g_free); + + g_signal_emit (entry, signals[USER_CHANGED], 0); +} + +static void +reader_mode_clicked_cb (EphyLocationEntry *self) +{ + self->reader_mode_active = !self->reader_mode_active; + + g_signal_emit (G_OBJECT (self), signals[READER_MODE_CHANGED], 0, + self->reader_mode_active); +} + +static void ephy_location_entry_suggestion_activated (DzlSuggestionEntry *entry, DzlSuggestion *arg1, gpointer user_data) @@ -918,72 +657,153 @@ ephy_location_entry_suggestion_activated (DzlSuggestionEntry *entry, } static void -suggestion_selected (DzlSuggestionEntry *entry, - DzlSuggestion *suggestion, - gpointer user_data) +activate_cb (EphyLocationEntry *self) { - EphyLocationEntry *lentry = EPHY_LOCATION_ENTRY (user_data); - const gchar *uri = dzl_suggestion_get_id (suggestion); - - g_signal_handlers_block_by_func (entry, G_CALLBACK (editable_changed_cb), user_data); - g_clear_pointer (&lentry->jump_tab, g_free); + GdkModifierType modifiers; - if (g_str_has_prefix (uri, "ephy-tab://")) { - lentry->jump_tab = g_strdup (uri); - gtk_entry_set_text (GTK_ENTRY (entry), dzl_suggestion_get_subtitle (suggestion)); - } else { - gtk_entry_set_text (GTK_ENTRY (entry), uri); - } - gtk_editable_set_position (GTK_EDITABLE (entry), -1); - g_signal_handlers_unblock_by_func (entry, G_CALLBACK (editable_changed_cb), user_data); + ephy_gui_get_current_event (NULL, &modifiers, NULL, NULL); - schedule_dns_prefetch (lentry, uri); + g_signal_emit (G_OBJECT (self), signals[ACTIVATE], 0, modifiers); } static void -enter_notify_cb (GtkWidget *widget, - GdkEvent *event, - gpointer user_data) +update_reader_icon (EphyLocationEntry *entry) { - gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_PRELIGHT, FALSE); + GtkIconTheme *theme; + const gchar *name; + + theme = gtk_icon_theme_get_default (); + + if (gtk_icon_theme_has_icon (theme, "view-reader-symbolic")) + name = "view-reader-symbolic"; + else + name = "ephy-reader-mode-symbolic"; + + gtk_image_set_from_icon_name (GTK_IMAGE (entry->reader_mode_icon), + name, GTK_ICON_SIZE_MENU); } static void -leave_notify_cb (GtkWidget *widget, - GdkEvent *event, - gpointer user_data) +paste_received (GtkClipboard *clipboard, + const gchar *text, + EphyLocationEntry *entry) { - gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_PRELIGHT); + if (text) { + g_signal_handlers_block_by_func (entry->url_entry, G_CALLBACK (editable_changed_cb), entry); + gtk_entry_set_text (GTK_ENTRY (entry->url_entry), text); + ephy_location_entry_activate (entry); + g_signal_handlers_unblock_by_func (entry->url_entry, G_CALLBACK (editable_changed_cb), entry); + } } static void -handle_forward_tab_key (GtkWidget *widget, - gpointer user_data) +entry_paste_and_go_activate_cb (GtkMenuItem *item, + EphyLocationEntry *entry) { - EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (user_data); - GtkWidget *popover; + GtkClipboard *clipboard; - popover = dzl_suggestion_entry_get_popover (DZL_SUGGESTION_ENTRY (entry->url_entry)); - if (gtk_widget_is_visible (popover)) { - g_signal_emit_by_name (entry->url_entry, "move-suggestion", 1, G_TYPE_INT, 1, G_TYPE_NONE); - } else { - gtk_widget_child_focus (gtk_widget_get_toplevel (GTK_WIDGET (entry)), GTK_DIR_TAB_FORWARD); - } + clipboard = gtk_clipboard_get_default (gdk_display_get_default ()); + gtk_clipboard_request_text (clipboard, + (GtkClipboardTextReceivedFunc)paste_received, + entry); } static void -handle_backward_tab_key (GtkWidget *widget, - gpointer user_data) +entry_clear_activate_cb (GtkMenuItem *item, + EphyLocationEntry *entry) { - EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (user_data); - GtkWidget *popover; + entry->block_update = TRUE; + g_signal_handlers_block_by_func (entry->url_entry, G_CALLBACK (editable_changed_cb), entry); + gtk_entry_set_text (GTK_ENTRY (entry->url_entry), ""); + g_signal_handlers_unblock_by_func (entry->url_entry, G_CALLBACK (editable_changed_cb), entry); + entry->block_update = FALSE; + entry->user_changed = TRUE; +} - popover = dzl_suggestion_entry_get_popover (DZL_SUGGESTION_ENTRY (entry->url_entry)); - if (gtk_widget_is_visible (popover)) { - g_signal_emit_by_name (entry->url_entry, "move-suggestion", -1, G_TYPE_INT, 1, G_TYPE_NONE); - } else { - gtk_widget_child_focus (gtk_widget_get_toplevel (GTK_WIDGET (entry)), GTK_DIR_TAB_BACKWARD); +/* The build should fail here each time when upgrading to a new major version + * of GTK+, so that we don't forget to update this domain. + */ +#if GTK_MAJOR_VERSION == 3 +#define GTK_GETTEXT_DOMAIN "gtk30" +#endif + +static void +entry_populate_popup_cb (GtkEntry *entry, + GtkMenu *menu, + EphyLocationEntry *lentry) +{ + GtkWidget *clear_menuitem; + GtkWidget *undo_menuitem; + GtkWidget *redo_menuitem; + GtkWidget *paste_and_go_menuitem; + GtkWidget *separator; + GtkWidget *paste_menuitem = NULL; + GList *children, *item; + int pos = 0, sep = 0; + gboolean is_editable; + + /* Translators: the mnemonic shouldn't conflict with any of the + * standard items in the GtkEntry context menu (Cut, Copy, Paste, Delete, + * Select All, Input Methods and Insert Unicode control character.) + */ + clear_menuitem = gtk_menu_item_new_with_mnemonic (_("Cl_ear")); + g_signal_connect (clear_menuitem, "activate", + G_CALLBACK (entry_clear_activate_cb), lentry); + is_editable = gtk_editable_get_editable (GTK_EDITABLE (entry)); + gtk_widget_set_sensitive (clear_menuitem, is_editable); + gtk_widget_show (clear_menuitem); + + /* search for the 2nd separator (the one after Select All) in the context + * menu, and insert this menu item before it. + * It's a bit of a hack, but there seems to be no better way to do it :/ + */ + children = gtk_container_get_children (GTK_CONTAINER (menu)); + for (item = children; item != NULL && sep < 2; item = item->next, pos++) { + if (GTK_IS_SEPARATOR_MENU_ITEM (item->data)) + sep++; + } + g_list_free (children); + + gtk_menu_shell_insert (GTK_MENU_SHELL (menu), clear_menuitem, pos - 1); + + paste_and_go_menuitem = gtk_menu_item_new_with_mnemonic (_("Paste and _Go")); + + /* Search for the Paste menu item and insert right after it. */ + children = gtk_container_get_children (GTK_CONTAINER (menu)); + for (item = children, pos = 0; item != NULL; item = item->next, pos++) { + if (g_strcmp0 (gtk_menu_item_get_label (item->data), g_dgettext (GTK_GETTEXT_DOMAIN, "_Paste")) == 0) { + paste_menuitem = item->data; + break; + } } + g_assert (paste_menuitem != NULL); + g_list_free (children); + + g_signal_connect (paste_and_go_menuitem, "activate", + G_CALLBACK (entry_paste_and_go_activate_cb), lentry); + lentry->paste_binding = g_object_bind_property (paste_menuitem, "sensitive", + paste_and_go_menuitem, "sensitive", + G_BINDING_SYNC_CREATE); + gtk_widget_show (paste_and_go_menuitem); + gtk_menu_shell_insert (GTK_MENU_SHELL (menu), paste_and_go_menuitem, pos + 1); + + undo_menuitem = gtk_menu_item_new_with_mnemonic (_("_Undo")); + gtk_widget_set_sensitive (undo_menuitem, lentry->user_changed); + g_signal_connect (undo_menuitem, "activate", + G_CALLBACK (entry_undo_activate_cb), lentry); + gtk_widget_show (undo_menuitem); + gtk_menu_shell_insert (GTK_MENU_SHELL (menu), undo_menuitem, 0); + + redo_menuitem = gtk_menu_item_new_with_mnemonic (_("_Redo")); + gtk_widget_set_sensitive (redo_menuitem, lentry->can_redo); + g_signal_connect (redo_menuitem, "activate", + G_CALLBACK (entry_redo_activate_cb), lentry); + gtk_widget_show (redo_menuitem); + gtk_menu_shell_insert (GTK_MENU_SHELL (menu), redo_menuitem, 1); + + separator = gtk_separator_menu_item_new (); + gtk_widget_show (separator); + gtk_menu_shell_insert (GTK_MENU_SHELL (menu), separator, 2); } static void @@ -1020,39 +840,186 @@ position_func (DzlSuggestionEntry *self, } static void -update_reader_icon (EphyLocationEntry *entry) +ephy_location_entry_get_preferred_height (GtkWidget *widget, + gint *minimum_height, + gint *natural_height) { - GtkIconTheme *theme; - const gchar *name; + EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (widget); - theme = gtk_icon_theme_get_default (); + gtk_widget_get_preferred_height (entry->url_entry, minimum_height, natural_height); +} - if (gtk_icon_theme_has_icon (theme, "view-reader-symbolic")) - name = "view-reader-symbolic"; - else - name = "ephy-reader-mode-symbolic"; +static void +ephy_location_entry_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (object); - gtk_image_set_from_icon_name (GTK_IMAGE (entry->reader_mode_icon), - name, GTK_ICON_SIZE_MENU); + switch (prop_id) { + case PROP_ADDRESS: + ephy_title_widget_set_address (EPHY_TITLE_WIDGET (entry), + g_value_get_string (value)); + break; + case PROP_SECURITY_LEVEL: + ephy_title_widget_set_security_level (EPHY_TITLE_WIDGET (entry), + g_value_get_enum (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } } static void -reader_mode_clicked_cb (EphyLocationEntry *self) +ephy_location_entry_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) { - self->reader_mode_active = !self->reader_mode_active; + EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (object); - g_signal_emit (G_OBJECT (self), signals[READER_MODE_CHANGED], 0, - self->reader_mode_active); + switch (prop_id) { + case PROP_ADDRESS: + g_value_set_string (value, ephy_title_widget_get_address (EPHY_TITLE_WIDGET (entry))); + break; + case PROP_SECURITY_LEVEL: + g_value_set_enum (value, ephy_title_widget_get_security_level (EPHY_TITLE_WIDGET (entry))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } } static void -activate_cb (EphyLocationEntry *self) +ephy_location_entry_constructed (GObject *object) { - GdkModifierType modifiers; + EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (object); - ephy_gui_get_current_event (NULL, &modifiers, NULL, NULL); + G_OBJECT_CLASS (ephy_location_entry_parent_class)->constructed (object); - g_signal_emit (G_OBJECT (self), signals[ACTIVATE], 0, modifiers); + gtk_entry_set_input_hints (GTK_ENTRY (entry->url_entry), GTK_INPUT_HINT_NO_EMOJI); +} + +static void +ephy_location_entry_dispose (GObject *object) +{ + EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (object); + + g_clear_handle_id (&entry->progress_timeout, g_source_remove); + + g_clear_object (&entry->css_provider); + + G_OBJECT_CLASS (ephy_location_entry_parent_class)->dispose (object); +} + +static void +ephy_location_entry_finalize (GObject *object) +{ + EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (object); + + g_free (entry->saved_text); + g_clear_pointer (&entry->jump_tab, g_free); + + G_OBJECT_CLASS (ephy_location_entry_parent_class)->finalize (object); +} + +static void +ephy_location_entry_class_init (EphyLocationEntryClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->get_property = ephy_location_entry_get_property; + object_class->set_property = ephy_location_entry_set_property; + object_class->constructed = ephy_location_entry_constructed; + object_class->finalize = ephy_location_entry_finalize; + object_class->dispose = ephy_location_entry_dispose; + + widget_class->get_preferred_height = ephy_location_entry_get_preferred_height; + + g_object_class_override_property (object_class, PROP_ADDRESS, "address"); + g_object_class_override_property (object_class, PROP_SECURITY_LEVEL, "security-level"); + + /** + * EphyLocationEntry::activate: + * @flags: the #GdkModifierType from the activation event + * + * Emitted when the entry is activated. + * + */ + signals[ACTIVATE] = g_signal_new ("activate", G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, + 1, + GDK_TYPE_MODIFIER_TYPE); + + /** + * EphyLocationEntry::user-changed: + * @entry: the object on which the signal is emitted + * + * Emitted when the user changes the contents of the internal #GtkEntry + * + */ + signals[USER_CHANGED] = g_signal_new ("user_changed", G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, + 0, + G_TYPE_NONE); + + /** + * EphyLocationEntry::reader-mode-changed: + * @entry: the object on which the signal is emitted + * @active: whether reader mode is active + * + * Emitted when the user clicks the reader mode icon inside the + * #EphyLocationEntry. + * + */ + signals[READER_MODE_CHANGED] = g_signal_new ("reader-mode-changed", G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, + 1, + G_TYPE_BOOLEAN); + + /** + * EphyLocationEntry::get-location: + * @entry: the object on which the signal is emitted + * Returns: the current page address as a string + * + * For drag and drop purposes, the location bar will request you the + * real address of where it is pointing to. The signal handler for this + * function should return the address of the currently loaded site. + * + */ + signals[GET_LOCATION] = g_signal_new ("get-location", G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST, + 0, ephy_signal_accumulator_string, + NULL, NULL, + G_TYPE_STRING, + 0, + G_TYPE_NONE); + + /** + * EphyLocationEntry::get-title: + * @entry: the object on which the signal is emitted + * Returns: the current page title as a string + * + * For drag and drop purposes, the location bar will request you the + * title of where it is pointing to. The signal handler for this + * function should return the title of the currently loaded site. + * + */ + signals[GET_TITLE] = g_signal_new ("get-title", G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST, + 0, ephy_signal_accumulator_string, + NULL, NULL, + G_TYPE_STRING, + 0, + G_TYPE_NONE); } static void @@ -1198,93 +1165,124 @@ ephy_location_entry_init (EphyLocationEntry *le) ephy_location_entry_construct_contents (le); } -GtkWidget * -ephy_location_entry_new (void) +static const char * +ephy_location_entry_title_widget_get_address (EphyTitleWidget *widget) { - return GTK_WIDGET (g_object_new (EPHY_TYPE_LOCATION_ENTRY, NULL)); -} + EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (widget); -typedef struct { - GUri *uri; - EphyLocationEntry *entry; -} PrefetchHelper; + g_assert (entry); + + return gtk_entry_get_text (GTK_ENTRY (entry->url_entry)); +} static void -free_prefetch_helper (PrefetchHelper *helper) +ephy_location_entry_title_widget_set_address (EphyTitleWidget *widget, + const char *address) { - g_uri_unref (helper->uri); - g_object_unref (helper->entry); - g_free (helper); + EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (widget); + GtkClipboard *clipboard; + const char *text; + g_autofree char *effective_text = NULL; + g_autofree char *selection = NULL; + int start, end; + const char *final_text; + + g_assert (widget); + + /* Setting a new text will clear the clipboard. This makes it impossible + * to copy&paste from the location entry of one tab into another tab, see + * bug #155824. So we save the selection iff the clipboard was owned by + * the location entry. + */ + if (gtk_widget_get_realized (GTK_WIDGET (entry))) { + clipboard = gtk_widget_get_clipboard (GTK_WIDGET (entry->url_entry), + GDK_SELECTION_PRIMARY); + g_assert (clipboard != NULL); + + if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (entry->url_entry) && + gtk_editable_get_selection_bounds (GTK_EDITABLE (entry->url_entry), + &start, &end)) { + selection = gtk_editable_get_chars (GTK_EDITABLE (entry->url_entry), + start, end); + } + } + + if (address != NULL) { + if (g_str_has_prefix (address, EPHY_ABOUT_SCHEME)) + effective_text = g_strdup_printf ("about:%s", + address + strlen (EPHY_ABOUT_SCHEME) + 1); + text = address; + } else { + text = ""; + } + + final_text = effective_text ? effective_text : text; + + entry->block_update = TRUE; + g_signal_handlers_block_by_func (entry->url_entry, G_CALLBACK (editable_changed_cb), entry); + gtk_entry_set_text (GTK_ENTRY (entry->url_entry), final_text); + update_entry_style (entry); + g_signal_handlers_unblock_by_func (entry->url_entry, G_CALLBACK (editable_changed_cb), entry); + + dzl_suggestion_entry_hide_suggestions (DZL_SUGGESTION_ENTRY (entry->url_entry)); + entry->block_update = FALSE; + + /* Now restore the selection. + * Note that it's not owned by the entry anymore! + */ + if (selection != NULL) { + gtk_clipboard_set_text (gtk_clipboard_get (GDK_SELECTION_PRIMARY), + selection, strlen (selection)); + } } -static gboolean -do_dns_prefetch (PrefetchHelper *helper) +static EphySecurityLevel +ephy_location_entry_title_widget_get_security_level (EphyTitleWidget *widget) { - EphyEmbedShell *shell = ephy_embed_shell_get_default (); - - if (helper->uri) - webkit_web_context_prefetch_dns (ephy_embed_shell_get_web_context (shell), g_uri_get_host (helper->uri)); + EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (widget); - helper->entry->dns_prefetch_handle_id = 0; + g_assert (entry); - return G_SOURCE_REMOVE; + return entry->security_level; } -/* - * Note: As we do not have access to WebKitNetworkProxyMode, and because - * Epiphany does not ever change it, we are just checking system default proxy. - */ static void -proxy_resolver_ready_cb (GObject *object, - GAsyncResult *result, - gpointer user_data) +ephy_location_entry_title_widget_set_security_level (EphyTitleWidget *widget, + EphySecurityLevel security_level) + { - PrefetchHelper *helper = user_data; - GProxyResolver *resolver = G_PROXY_RESOLVER (object); - g_autoptr (GError) error = NULL; - g_auto (GStrv) proxies = NULL; + EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (widget); + const char *icon_name; - proxies = g_proxy_resolver_lookup_finish (resolver, result, &error); - if (error != NULL) { - free_prefetch_helper (helper); - return; - } + g_assert (entry); - if (proxies != NULL && (g_strv_length (proxies) > 1 || g_strcmp0 (proxies[0], "direct://") != 0)) { - free_prefetch_helper (helper); - return; + if (!entry->reader_mode_active) { + icon_name = ephy_security_level_to_icon_name (security_level); + gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry->url_entry), + GTK_ENTRY_ICON_PRIMARY, + icon_name); + } else { + gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry->url_entry), + GTK_ENTRY_ICON_PRIMARY, + NULL); } - g_clear_handle_id (&helper->entry->dns_prefetch_handle_id, g_source_remove); - helper->entry->dns_prefetch_handle_id = - g_timeout_add_full (G_PRIORITY_DEFAULT, - 250, - (GSourceFunc)do_dns_prefetch, - helper, - (GDestroyNotify)free_prefetch_helper); - g_source_set_name_by_id (helper->entry->dns_prefetch_handle_id, "[epiphany] do_dns_prefetch"); + entry->security_level = security_level; } static void -schedule_dns_prefetch (EphyLocationEntry *entry, - const gchar *url) +ephy_location_entry_title_widget_interface_init (EphyTitleWidgetInterface *iface) { - GProxyResolver *resolver = g_proxy_resolver_get_default (); - PrefetchHelper *helper; - g_autoptr (GUri) uri = NULL; - - if (resolver == NULL) - return; - - uri = g_uri_parse (url, G_URI_FLAGS_NONE, NULL); - if (!uri || !g_uri_get_host (uri)) - return; - - helper = g_new0 (PrefetchHelper, 1); - helper->entry = g_object_ref (entry); - helper->uri = g_steal_pointer (&uri); + iface->get_address = ephy_location_entry_title_widget_get_address; + iface->set_address = ephy_location_entry_title_widget_set_address; + iface->get_security_level = ephy_location_entry_title_widget_get_security_level; + iface->set_security_level = ephy_location_entry_title_widget_set_security_level; +} - g_proxy_resolver_lookup_async (resolver, url, NULL, proxy_resolver_ready_cb, helper); +GtkWidget * +ephy_location_entry_new (void) +{ + return GTK_WIDGET (g_object_new (EPHY_TYPE_LOCATION_ENTRY, NULL)); } /** |