diff options
author | Michael Catanzaro <mcatanzaro@igalia.com> | 2017-11-22 17:51:31 -0600 |
---|---|---|
committer | Michael Catanzaro <mcatanzaro@igalia.com> | 2017-11-22 17:51:31 -0600 |
commit | 513727c50807df004c985be4cc03191655d53fb3 (patch) | |
tree | 8b7e810615e6050fd1897d80b3dc12d273337a61 /lib/widgets | |
parent | df1db5026cef1343d33e11a1bd370b41ea1eeb14 (diff) | |
download | epiphany-wip/libdazzle.tar.gz |
Revert "Stop using DzlSuggestionEntry for now"wip/libdazzle
This reverts commit df1db5026cef1343d33e11a1bd370b41ea1eeb14.
Diffstat (limited to 'lib/widgets')
-rw-r--r-- | lib/widgets/contrib/gd-two-lines-renderer.c | 621 | ||||
-rw-r--r-- | lib/widgets/contrib/gd-two-lines-renderer.h | 75 | ||||
-rw-r--r-- | lib/widgets/ephy-location-entry.c | 378 | ||||
-rw-r--r-- | lib/widgets/ephy-location-entry.h | 20 | ||||
-rw-r--r-- | lib/widgets/meson.build | 2 |
5 files changed, 41 insertions, 1055 deletions
diff --git a/lib/widgets/contrib/gd-two-lines-renderer.c b/lib/widgets/contrib/gd-two-lines-renderer.c deleted file mode 100644 index 5a029f7f2..000000000 --- a/lib/widgets/contrib/gd-two-lines-renderer.c +++ /dev/null @@ -1,621 +0,0 @@ -/* - * Copyright (c) 2011 Red Hat, Inc. - * - * This program 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 of the License, or (at your - * option) any later version. - * - * This program 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 program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Author: Cosimo Cecchi <cosimoc@redhat.com> - * - */ - -#include "gd-two-lines-renderer.h" -#include <string.h> - -#define SUBTITLE_DIM_PERCENTAGE 0.55 -#define SUBTITLE_SIZE_PERCENTAGE 0.82 - -G_DEFINE_TYPE (GdTwoLinesRenderer, gd_two_lines_renderer, GTK_TYPE_CELL_RENDERER_TEXT) - -struct _GdTwoLinesRendererPrivate { - gchar *line_two; - gint text_lines; -}; - -enum { - PROP_TEXT_LINES = 1, - PROP_LINE_TWO, - NUM_PROPERTIES -}; - -static GParamSpec *properties[NUM_PROPERTIES] = { NULL, }; - -static PangoLayout * -create_layout_with_attrs (GtkWidget *widget, - const GdkRectangle *cell_area, - GdTwoLinesRenderer *self, - PangoEllipsizeMode ellipsize) -{ - PangoLayout *layout; - gint wrap_width, xpad; - PangoWrapMode wrap_mode; - PangoAlignment alignment; - - g_object_get (self, - "wrap-width", &wrap_width, - "wrap-mode", &wrap_mode, - "alignment", &alignment, - "xpad", &xpad, - NULL); - - layout = pango_layout_new (gtk_widget_get_pango_context (widget)); - - pango_layout_set_ellipsize (layout, ellipsize); - pango_layout_set_alignment (layout, alignment); - - if (wrap_width != -1) - { - pango_layout_set_width (layout, wrap_width * PANGO_SCALE); - pango_layout_set_wrap (layout, wrap_mode); - } - else - { - if (cell_area != NULL) - pango_layout_set_width (layout, (cell_area->width - 2 * xpad) * PANGO_SCALE); - else - pango_layout_set_width (layout, -1); - - pango_layout_set_wrap (layout, PANGO_WRAP_CHAR); - } - - return layout; -} - -static void -apply_subtitle_style_to_layout (GtkStyleContext *context, - PangoLayout *layout, - GtkStateFlags flags) -{ - PangoFontDescription *desc; - PangoAttrList *layout_attr; - PangoAttribute *attr_alpha; - - gtk_style_context_save (context); - gtk_style_context_set_state (context, flags); - gtk_style_context_get (context, gtk_style_context_get_state (context), - "font", &desc, - NULL); - gtk_style_context_restore (context); - - /* Set the font size */ - pango_font_description_set_size (desc, pango_font_description_get_size (desc) * SUBTITLE_SIZE_PERCENTAGE); - pango_layout_set_font_description (layout, desc); - pango_font_description_free (desc); - - /* Set the font alpha */ - layout_attr = pango_attr_list_new (); - attr_alpha = pango_attr_foreground_alpha_new (SUBTITLE_DIM_PERCENTAGE * 65535); - pango_attr_list_insert (layout_attr, attr_alpha); - - pango_layout_set_attributes (layout, layout_attr); - pango_attr_list_unref (layout_attr); -} - -static void -gd_two_lines_renderer_prepare_layouts (GdTwoLinesRenderer *self, - const GdkRectangle *cell_area, - GtkWidget *widget, - PangoLayout **layout_one, - PangoLayout **layout_two) -{ - PangoLayout *line_one; - PangoLayout *line_two = NULL; - gchar *text = NULL; - - g_object_get (self, - "text", &text, - NULL); - - line_one = create_layout_with_attrs (widget, cell_area, - self, PANGO_ELLIPSIZE_MIDDLE); - - if (self->priv->line_two == NULL || - g_strcmp0 (self->priv->line_two, "") == 0) - { - pango_layout_set_height (line_one, - (self->priv->text_lines)); - - if (text != NULL) - pango_layout_set_text (line_one, text, -1); - } - else - { - GtkStyleContext *context; - - line_two = create_layout_with_attrs (widget, cell_area, - self, PANGO_ELLIPSIZE_END); - - context = gtk_widget_get_style_context (widget); - gtk_style_context_save (context); - apply_subtitle_style_to_layout (context, line_two, GTK_STATE_FLAG_NORMAL); - gtk_style_context_restore (context); - - pango_layout_set_height (line_one, - (self->priv->text_lines - 1)); - pango_layout_set_height (line_two, -1); - pango_layout_set_text (line_two, self->priv->line_two, -1); - - if (text != NULL) - pango_layout_set_text (line_one, text, -1); - } - - if (layout_one) - *layout_one = line_one; - if (layout_two) - *layout_two = line_two; - - g_free (text); -} - -static void -gd_two_lines_renderer_get_size (GtkCellRenderer *cell, - GtkWidget *widget, - PangoLayout *layout_1, - PangoLayout *layout_2, - gint *width, - gint *height, - const GdkRectangle *cell_area, - gint *x_offset_1, - gint *x_offset_2, - gint *y_offset) -{ - GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (cell); - gint xpad, ypad; - PangoLayout *layout_one, *layout_two; - GdkRectangle layout_one_rect, layout_two_rect, layout_union; - - if (layout_1 == NULL) - { - gd_two_lines_renderer_prepare_layouts (self, cell_area, widget, &layout_one, &layout_two); - } - else - { - layout_one = g_object_ref (layout_1); - - if (layout_2 != NULL) - layout_two = g_object_ref (layout_2); - else - layout_two = NULL; - } - - gtk_cell_renderer_get_padding (cell, &xpad, &ypad); - pango_layout_get_pixel_extents (layout_one, NULL, (PangoRectangle *) &layout_one_rect); - - if (layout_two != NULL) - { - pango_layout_get_pixel_extents (layout_two, NULL, (PangoRectangle *) &layout_two_rect); - - layout_union.width = MAX (layout_one_rect.width, layout_two_rect.width); - layout_union.height = layout_one_rect.height + layout_two_rect.height; - } - else - { - layout_union = layout_one_rect; - } - - if (cell_area) - { - gfloat xalign, yalign; - - gtk_cell_renderer_get_alignment (cell, &xalign, &yalign); - - layout_union.width = MIN (layout_union.width, cell_area->width - 2 * xpad); - layout_union.height = MIN (layout_union.height, cell_area->height - 2 * ypad); - - if (x_offset_1) - { - if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) - *x_offset_1 = (1.0 - xalign) * (cell_area->width - (layout_one_rect.width + (2 * xpad))); - else - *x_offset_1 = xalign * (cell_area->width - (layout_one_rect.width + (2 * xpad))); - - *x_offset_1 = MAX (*x_offset_1, 0); - } - if (x_offset_2) - { - if (layout_two != NULL) - { - if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) - *x_offset_2 = (1.0 - xalign) * (cell_area->width - (layout_two_rect.width + (2 * xpad))); - else - *x_offset_2 = xalign * (cell_area->width - (layout_two_rect.width + (2 * xpad))); - - *x_offset_2 = MAX (*x_offset_2, 0); - } - else - { - *x_offset_2 = 0; - } - } - - if (y_offset) - { - *y_offset = yalign * (cell_area->height - (layout_union.height + (2 * ypad))); - *y_offset = MAX (*y_offset, 0); - } - } - else - { - if (x_offset_1) *x_offset_1 = 0; - if (x_offset_2) *x_offset_2 = 0; - if (y_offset) *y_offset = 0; - } - - g_clear_object (&layout_one); - g_clear_object (&layout_two); - - if (height) - *height = ypad * 2 + layout_union.height; - - if (width) - *width = xpad * 2 + layout_union.width; -} - -static void -gd_two_lines_renderer_render (GtkCellRenderer *cell, - cairo_t *cr, - GtkWidget *widget, - const GdkRectangle *background_area, - const GdkRectangle *cell_area, - GtkCellRendererState flags) -{ - GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (cell); - GtkStyleContext *context; - gint line_one_height; - GtkStateFlags state; - GdkRectangle area, render_area = *cell_area; - gint xpad, ypad, x_offset_1, x_offset_2, y_offset; - PangoLayout *layout_one, *layout_two; - PangoRectangle layout_rect; - - /* fetch common information */ - context = gtk_widget_get_style_context (widget); - gd_two_lines_renderer_prepare_layouts (self, cell_area, widget, &layout_one, &layout_two); - gd_two_lines_renderer_get_size (cell, widget, - layout_one, layout_two, - NULL, NULL, - cell_area, - &x_offset_1, &x_offset_2, &y_offset); - gtk_cell_renderer_get_padding (cell, &xpad, &ypad); - - area = *cell_area; - area.x += xpad; - area.y += ypad; - - /* now render the first layout */ - pango_layout_get_pixel_extents (layout_one, NULL, &layout_rect); - - render_area = area; - render_area.x += x_offset_1 - layout_rect.x; - - gtk_render_layout (context, cr, - render_area.x, - render_area.y, - layout_one); - - /* render the second layout */ - if (layout_two != NULL) - { - pango_layout_get_pixel_size (layout_one, - NULL, &line_one_height); - - gtk_style_context_save (context); - - apply_subtitle_style_to_layout (context, layout_two, flags); - - state = gtk_cell_renderer_get_state (cell, widget, flags); - gtk_style_context_set_state (context, state); - - pango_layout_get_pixel_extents (layout_two, NULL, &layout_rect); - - render_area = area; - render_area.x += x_offset_2 - layout_rect.x; - render_area.y += line_one_height; - - gtk_render_layout (context, cr, - render_area.x, - render_area.y, - layout_two); - - gtk_style_context_restore (context); - } - - g_clear_object (&layout_one); - g_clear_object (&layout_two); -} - -static void -gd_two_lines_renderer_get_preferred_width (GtkCellRenderer *cell, - GtkWidget *widget, - gint *minimum_size, - gint *natural_size) -{ - PangoContext *context; - PangoFontMetrics *metrics; - PangoFontDescription *font_desc; - GtkStyleContext *style_context; - gint nat_width, min_width; - gint xpad, char_width, wrap_width, text_width; - gint width_chars, ellipsize_chars; - - g_object_get (cell, - "xpad", &xpad, - "width-chars", &width_chars, - "wrap-width", &wrap_width, - NULL); - style_context = gtk_widget_get_style_context (widget); - gtk_cell_renderer_get_padding (cell, &xpad, NULL); - - gd_two_lines_renderer_get_size (cell, widget, - NULL, NULL, - &text_width, NULL, - NULL, - NULL, NULL, NULL); - - /* Fetch the average size of a character */ - context = gtk_widget_get_pango_context (widget); - gtk_style_context_save (style_context); - gtk_style_context_set_state (style_context, 0); - gtk_style_context_get (style_context, gtk_style_context_get_state (style_context), - "font", &font_desc, NULL); - gtk_style_context_restore (style_context); - metrics = pango_context_get_metrics (context, font_desc, - pango_context_get_language (context)); - - char_width = pango_font_metrics_get_approximate_char_width (metrics); - - pango_font_metrics_unref (metrics); - pango_font_description_free (font_desc); - - /* enforce minimum width for ellipsized labels at ~3 chars */ - ellipsize_chars = 3; - - /* If no width-chars set, minimum for wrapping text will be the wrap-width */ - if (wrap_width > -1) - min_width = xpad * 2 + MIN (text_width, wrap_width); - else - min_width = xpad * 2 + - MIN (text_width, - (PANGO_PIXELS (char_width) * MAX (width_chars, ellipsize_chars))); - - if (width_chars > 0) - nat_width = xpad * 2 + - MAX ((PANGO_PIXELS (char_width) * width_chars), text_width); - else - nat_width = xpad * 2 + text_width; - - nat_width = MAX (nat_width, min_width); - - if (minimum_size) - *minimum_size = min_width; - - if (natural_size) - *natural_size = nat_width; -} - -static void -gd_two_lines_renderer_get_preferred_height_for_width (GtkCellRenderer *cell, - GtkWidget *widget, - gint width, - gint *minimum_size, - gint *natural_size) -{ - GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (cell); - PangoLayout *layout_one, *layout_two; - gint text_height, wrap_width; - gint xpad, ypad; - - gtk_cell_renderer_get_padding (cell, &xpad, &ypad); - g_object_get (cell, "wrap-width", &wrap_width, NULL); - gd_two_lines_renderer_prepare_layouts (self, NULL, widget, &layout_one, &layout_two); - - if (wrap_width != -1) - wrap_width = MIN (width - 2 * xpad, wrap_width); - else - wrap_width = width - 2 * xpad; - - pango_layout_set_width (layout_one, wrap_width); - if (layout_two != NULL) - pango_layout_set_width (layout_two, wrap_width); - - gd_two_lines_renderer_get_size (cell, widget, - layout_one, layout_two, - NULL, &text_height, - NULL, - NULL, NULL, NULL); - - text_height += 2 * ypad; - - if (minimum_size != NULL) - *minimum_size = text_height; - - if (natural_size != NULL) - *natural_size = text_height; - - g_clear_object (&layout_one); - g_clear_object (&layout_two); -} - -static void -gd_two_lines_renderer_get_preferred_height (GtkCellRenderer *cell, - GtkWidget *widget, - gint *minimum_size, - gint *natural_size) -{ - gint min_width; - - gtk_cell_renderer_get_preferred_width (cell, widget, &min_width, NULL); - gd_two_lines_renderer_get_preferred_height_for_width (cell, widget, min_width, - minimum_size, natural_size); -} - -static void -gd_two_lines_renderer_get_aligned_area (GtkCellRenderer *cell, - GtkWidget *widget, - GtkCellRendererState flags, - const GdkRectangle *cell_area, - GdkRectangle *aligned_area) -{ - GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (cell); - gint x_offset, x_offset_1, x_offset_2, y_offset; - PangoLayout *layout_one, *layout_two; - - /* fetch common information */ - gd_two_lines_renderer_prepare_layouts (self, cell_area, widget, &layout_one, &layout_two); - gd_two_lines_renderer_get_size (cell, widget, - layout_one, layout_two, - &aligned_area->width, &aligned_area->height, - cell_area, - &x_offset_1, &x_offset_2, &y_offset); - - x_offset = MIN (x_offset_1, x_offset_2); - - aligned_area->x = cell_area->x + x_offset; - aligned_area->y = cell_area->y; - - g_clear_object (&layout_one); - g_clear_object (&layout_two); -} - -static void -gd_two_lines_renderer_set_line_two (GdTwoLinesRenderer *self, - const gchar *line_two) -{ - if (g_strcmp0 (self->priv->line_two, line_two) == 0) - return; - - g_free (self->priv->line_two); - self->priv->line_two = g_strdup (line_two); - - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LINE_TWO]); -} - -static void -gd_two_lines_renderer_set_text_lines (GdTwoLinesRenderer *self, - gint text_lines) -{ - if (self->priv->text_lines == text_lines) - return; - - self->priv->text_lines = text_lines; - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TEXT_LINES]); -} - -static void -gd_two_lines_renderer_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (object); - - switch (property_id) - { - case PROP_TEXT_LINES: - gd_two_lines_renderer_set_text_lines (self, g_value_get_int (value)); - break; - case PROP_LINE_TWO: - gd_two_lines_renderer_set_line_two (self, g_value_get_string (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -gd_two_lines_renderer_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (object); - - switch (property_id) - { - case PROP_TEXT_LINES: - g_value_set_int (value, self->priv->text_lines); - break; - case PROP_LINE_TWO: - g_value_set_string (value, self->priv->line_two); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -gd_two_lines_renderer_finalize (GObject *object) -{ - GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (object); - - g_free (self->priv->line_two); - - G_OBJECT_CLASS (gd_two_lines_renderer_parent_class)->finalize (object); -} - -static void -gd_two_lines_renderer_class_init (GdTwoLinesRendererClass *klass) -{ - GtkCellRendererClass *cclass = GTK_CELL_RENDERER_CLASS (klass); - GObjectClass *oclass = G_OBJECT_CLASS (klass); - - cclass->render = gd_two_lines_renderer_render; - cclass->get_preferred_width = gd_two_lines_renderer_get_preferred_width; - cclass->get_preferred_height = gd_two_lines_renderer_get_preferred_height; - cclass->get_preferred_height_for_width = gd_two_lines_renderer_get_preferred_height_for_width; - cclass->get_aligned_area = gd_two_lines_renderer_get_aligned_area; - - oclass->set_property = gd_two_lines_renderer_set_property; - oclass->get_property = gd_two_lines_renderer_get_property; - oclass->finalize = gd_two_lines_renderer_finalize; - - properties[PROP_TEXT_LINES] = - g_param_spec_int ("text-lines", - "Lines of text", - "The total number of lines to be displayed", - 2, G_MAXINT, 2, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - properties[PROP_LINE_TWO] = - g_param_spec_string ("line-two", - "Second line", - "Second line", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_type_class_add_private (klass, sizeof (GdTwoLinesRendererPrivate)); - g_object_class_install_properties (oclass, NUM_PROPERTIES, properties); -} - -static void -gd_two_lines_renderer_init (GdTwoLinesRenderer *self) -{ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GD_TYPE_TWO_LINES_RENDERER, - GdTwoLinesRendererPrivate); -} - -GtkCellRenderer * -gd_two_lines_renderer_new (void) -{ - return g_object_new (GD_TYPE_TWO_LINES_RENDERER, NULL); -} diff --git a/lib/widgets/contrib/gd-two-lines-renderer.h b/lib/widgets/contrib/gd-two-lines-renderer.h deleted file mode 100644 index 23bf70f08..000000000 --- a/lib/widgets/contrib/gd-two-lines-renderer.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2011 Red Hat, Inc. - * - * This program 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 of the License, or (at your - * option) any later version. - * - * This program 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 program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Author: Cosimo Cecchi <cosimoc@redhat.com> - * - */ - -#ifndef _GD_TWO_LINES_RENDERER_H -#define _GD_TWO_LINES_RENDERER_H - -#include <glib-object.h> - -#include <gtk/gtk.h> - -G_BEGIN_DECLS - -#define GD_TYPE_TWO_LINES_RENDERER gd_two_lines_renderer_get_type() - -#define GD_TWO_LINES_RENDERER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - GD_TYPE_TWO_LINES_RENDERER, GdTwoLinesRenderer)) - -#define GD_TWO_LINES_RENDERER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - GD_TYPE_TWO_LINES_RENDERER, GdTwoLinesRendererClass)) - -#define GD_IS_TWO_LINES_RENDERER(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - GD_TYPE_TWO_LINES_RENDERER)) - -#define GD_IS_TWO_LINES_RENDERER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - GD_TYPE_TWO_LINES_RENDERER)) - -#define GD_TWO_LINES_RENDERER_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - GD_TYPE_TWO_LINES_RENDERER, GdTwoLinesRendererClass)) - -typedef struct _GdTwoLinesRenderer GdTwoLinesRenderer; -typedef struct _GdTwoLinesRendererClass GdTwoLinesRendererClass; -typedef struct _GdTwoLinesRendererPrivate GdTwoLinesRendererPrivate; - -struct _GdTwoLinesRenderer -{ - GtkCellRendererText parent; - - GdTwoLinesRendererPrivate *priv; -}; - -struct _GdTwoLinesRendererClass -{ - GtkCellRendererTextClass parent_class; -}; - -GType gd_two_lines_renderer_get_type (void) G_GNUC_CONST; - -GtkCellRenderer *gd_two_lines_renderer_new (void); - -G_END_DECLS - -#endif /* _GD_TWO_LINES_RENDERER_H */ diff --git a/lib/widgets/ephy-location-entry.c b/lib/widgets/ephy-location-entry.c index 74b590f9c..472d0ab66 100644 --- a/lib/widgets/ephy-location-entry.c +++ b/lib/widgets/ephy-location-entry.c @@ -31,10 +31,11 @@ #include "ephy-gui.h" #include "ephy-lib-type-builtins.h" #include "ephy-signal-accumulator.h" +#include "ephy-suggestion.h" #include "ephy-title-widget.h" #include "ephy-uri-helpers.h" -#include "gd-two-lines-renderer.h" +#include <dazzle.h> #include <gdk/gdkkeysyms.h> #include <glib/gi18n.h> #include <gtk/gtk.h> @@ -54,7 +55,7 @@ */ struct _EphyLocationEntry { - GtkEntry parent_instance; + DzlSuggestionEntry parent_instance; GtkTreeModel *model; @@ -91,12 +92,6 @@ struct _EphyLocationEntry { static gboolean ephy_location_entry_reset_internal (EphyLocationEntry *, gboolean); -static void extracell_data_func (GtkCellLayout *cell_layout, - GtkCellRenderer *cell, - GtkTreeModel *tree_model, - GtkTreeIter *iter, - gpointer data); - enum { PROP_0, PROP_ADDRESS, @@ -115,11 +110,17 @@ static gint signals[LAST_SIGNAL] = { 0 }; static void ephy_location_entry_title_widget_interface_init (EphyTitleWidgetInterface *iface); -G_DEFINE_TYPE_WITH_CODE (EphyLocationEntry, ephy_location_entry, GTK_TYPE_ENTRY, +G_DEFINE_TYPE_WITH_CODE (EphyLocationEntry, ephy_location_entry, DZL_TYPE_SUGGESTION_ENTRY, G_IMPLEMENT_INTERFACE (EPHY_TYPE_TITLE_WIDGET, ephy_location_entry_title_widget_interface_init)) static void +ephy_location_entry_activate (EphyLocationEntry *entry) +{ + g_signal_emit_by_name (entry, "activate"); +} + +static void update_address_state (EphyLocationEntry *entry) { const char *text; @@ -273,8 +274,12 @@ ephy_location_entry_get_property (GObject *object, static void ephy_location_entry_constructed (GObject *object) { + EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (object); + G_OBJECT_CLASS (ephy_location_entry_parent_class)->constructed (object); + dzl_suggestion_entry_set_position_func (DZL_SUGGESTION_ENTRY (entry), dzl_suggestion_entry_window_position_func, NULL, NULL); + #if GTK_CHECK_VERSION(3, 22, 20) gtk_entry_set_input_hints (GTK_ENTRY (object), GTK_INPUT_HINT_NO_EMOJI); #endif @@ -361,6 +366,16 @@ ephy_location_entry_cut_clipboard (GtkEntry *entry) } static void +ephy_location_entry_suggestion_activated (DzlSuggestionEntry *entry, + DzlSuggestion *suggestion) +{ + gtk_entry_set_text (GTK_ENTRY (entry), ephy_suggestion_get_uri (EPHY_SUGGESTION (suggestion))); + + /* Now trigger the load.... */ + ephy_location_entry_activate (EPHY_LOCATION_ENTRY (entry)); +} + +static void ephy_location_entry_title_widget_interface_init (EphyTitleWidgetInterface *iface) { iface->get_address = ephy_location_entry_title_widget_get_address; @@ -375,7 +390,9 @@ ephy_location_entry_class_init (EphyLocationEntryClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkEntryClass *entry_class = GTK_ENTRY_CLASS (klass); + DzlSuggestionEntryClass *dzl_entry_class = DZL_SUGGESTION_ENTRY_CLASS (klass); + object_class->constructed = ephy_location_entry_constructed; 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; @@ -387,6 +404,8 @@ ephy_location_entry_class_init (EphyLocationEntryClass *klass) entry_class->copy_clipboard = ephy_location_entry_copy_clipboard; entry_class->cut_clipboard = ephy_location_entry_cut_clipboard; + dzl_entry_class->suggestion_activated = ephy_location_entry_suggestion_activated; + g_object_class_override_property (object_class, PROP_ADDRESS, "address"); g_object_class_override_property (object_class, PROP_SECURITY_LEVEL, "security-level"); @@ -488,103 +507,18 @@ entry_key_press_cb (GtkEntry *entry, /* Make sure the location is activated on CTRL+l even when the * completion popup is shown and have an active keyboard grab. */ - ephy_location_entry_activate (location_entry); - } - - return FALSE; -} - -static gboolean -entry_key_press_after_cb (GtkEntry *entry, - GdkEventKey *event, - EphyLocationEntry *lentry) -{ - guint state = event->state & gtk_accelerator_get_default_mod_mask (); - - if ((event->keyval == GDK_KEY_Return || - event->keyval == GDK_KEY_KP_Enter || - event->keyval == GDK_KEY_ISO_Enter) && - (state == GDK_CONTROL_MASK || - state == (GDK_CONTROL_MASK | GDK_SHIFT_MASK))) { - /* gtk_im_context_reset (entry->im_context); */ - - lentry->needs_reset = TRUE; - g_signal_emit_by_name (entry, "activate"); - - return TRUE; + ephy_location_entry_focus (location_entry); } - if ((event->keyval == GDK_KEY_Down || event->keyval == GDK_KEY_KP_Down) - && state == 0) { - /* If we are focusing the entry, with the cursor at the end of it - * we emit the changed signal, so that the completion popup appears */ - const char *string; - - string = gtk_entry_get_text (entry); - if (gtk_editable_get_position (GTK_EDITABLE (entry)) == (int)strlen (string)) { - g_signal_emit_by_name (entry, "changed", 0); - return TRUE; - } - } + if (event->keyval == GDK_KEY_Return || + event->keyval == GDK_KEY_KP_Enter || + event->keyval == GDK_KEY_ISO_Enter) + ephy_location_entry_activate (location_entry); return FALSE; } static void -entry_activate_after_cb (GtkEntry *entry, - EphyLocationEntry *lentry) -{ - lentry->user_changed = FALSE; - - if (lentry->needs_reset) { - ephy_location_entry_reset_internal (lentry, TRUE); - lentry->needs_reset = FALSE; - } -} - -static gboolean -match_selected_cb (GtkEntryCompletion *completion, - GtkTreeModel *model, - GtkTreeIter *iter, - EphyLocationEntry *entry) -{ - char *item = NULL; - guint state; - - gtk_tree_model_get (model, iter, - entry->action_col, &item, -1); - if (item == NULL) return FALSE; - - ephy_gui_get_current_event (NULL, &state, NULL); - - entry->needs_reset = (state == GDK_CONTROL_MASK || - state == (GDK_CONTROL_MASK | GDK_SHIFT_MASK)); - - ephy_title_widget_set_address (EPHY_TITLE_WIDGET (entry), item); - /* gtk_im_context_reset (GTK_ENTRY (entry)->im_context); */ - g_signal_emit_by_name (entry, "activate"); - - g_free (item); - - return TRUE; -} - -static void -action_activated_after_cb (GtkEntryCompletion *completion, - gint index, - EphyLocationEntry *lentry) -{ - guint state, button; - - ephy_gui_get_current_event (NULL, &state, &button); - if ((state == GDK_CONTROL_MASK || - state == (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) || - button == 2) { - ephy_location_entry_reset_internal (lentry, TRUE); - } -} - -static void entry_clear_activate_cb (GtkMenuItem *item, EphyLocationEntry *entry) { @@ -601,7 +535,7 @@ paste_received (GtkClipboard *clipboard, { if (text) { gtk_entry_set_text (GTK_ENTRY (entry), text); - g_signal_emit_by_name (entry, "activate"); + ephy_location_entry_activate (entry); } } @@ -758,11 +692,6 @@ ephy_location_entry_construct_contents (EphyLocationEntry *lentry) "signal::key-press-event", G_CALLBACK (entry_key_press_cb), lentry, "signal::changed", G_CALLBACK (editable_changed_cb), lentry, NULL); - - g_signal_connect_after (entry, "key-press-event", - G_CALLBACK (entry_key_press_after_cb), lentry); - g_signal_connect_after (entry, "activate", - G_CALLBACK (entry_activate_after_cb), lentry); } static void @@ -839,238 +768,6 @@ schedule_dns_prefetch (EphyLocationEntry *entry, guint interval, const gchar *ur } #endif -static gboolean -cursor_on_match_cb (GtkEntryCompletion *completion, - GtkTreeModel *model, - GtkTreeIter *iter, - EphyLocationEntry *le) -{ - char *url = NULL; - GtkWidget *entry; - - gtk_tree_model_get (model, iter, - le->url_col, - &url, -1); - entry = gtk_entry_completion_get_entry (completion); - - /* Prevent the update so we keep the highlight from our input. - * See textcell_data_func(). - */ - le->block_update = TRUE; - gtk_entry_set_text (GTK_ENTRY (entry), url); - gtk_editable_set_position (GTK_EDITABLE (entry), -1); - le->block_update = FALSE; - -#if 0 -/* FIXME: Refactor the DNS prefetch, this is a layering violation */ - schedule_dns_prefetch (le, 250, (const gchar *)url); -#endif - - g_free (url); - - return TRUE; -} - -static void -extracell_data_func (GtkCellLayout *cell_layout, - GtkCellRenderer *cell, - GtkTreeModel *tree_model, - GtkTreeIter *iter, - gpointer data) -{ - EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (data); - gboolean is_bookmark = FALSE; - GValue visible = { 0, }; - - gtk_tree_model_get (tree_model, iter, - entry->extra_col, &is_bookmark, - -1); - - if (is_bookmark) - g_object_set (cell, - "icon-name", "user-bookmarks-symbolic", - NULL); - - g_value_init (&visible, G_TYPE_BOOLEAN); - g_value_set_boolean (&visible, is_bookmark); - g_object_set_property (G_OBJECT (cell), "visible", &visible); - g_value_unset (&visible); -} - -/** - * ephy_location_entry_set_match_func: - * @entry: an #EphyLocationEntry widget - * @match_func: a #GtkEntryCompletionMatchFunc - * @user_data: user_data to pass to the @match_func - * @notify: a #GDestroyNotify, like the one given to - * gtk_entry_completion_set_match_func - * - * Sets the match_func for the internal #GtkEntryCompletion to @match_func. - * - **/ -void -ephy_location_entry_set_match_func (EphyLocationEntry *entry, - GtkEntryCompletionMatchFunc match_func, - gpointer user_data, - GDestroyNotify notify) -{ - GtkEntryCompletion *completion; - - completion = gtk_entry_get_completion (GTK_ENTRY (entry)); - gtk_entry_completion_set_match_func (completion, match_func, user_data, notify); -} - -/** - * ephy_location_entry_set_completion: - * @entry: an #EphyLocationEntry widget - * @model: the #GtkModel for the completion - * @text_col: column id to access #GtkModel relevant data - * @action_col: column id to access #GtkModel relevant data - * @keywords_col: column id to access #GtkModel relevant data - * @relevance_col: column id to access #GtkModel relevant data - * @url_col: column id to access #GtkModel relevant data - * @extra_col: column id to access #GtkModel relevant data - * @favicon_col: column id to access #GtkModel relevant data - * - * Initializes @entry to have a #GtkEntryCompletion using @model as the - * internal #GtkModel. The *_col arguments are for internal data retrieval from - * @model, like when setting the text property of one of the #GtkCellRenderer - * of the completion. - * - **/ -void -ephy_location_entry_set_completion (EphyLocationEntry *entry, - GtkTreeModel *model, - guint text_col, - guint action_col, - guint keywords_col, - guint relevance_col, - guint url_col, - guint extra_col, - guint favicon_col) -{ - GtkEntryCompletion *completion; - GtkCellRenderer *cell; - - entry->text_col = text_col; - entry->action_col = action_col; - entry->keywords_col = keywords_col; - entry->relevance_col = relevance_col; - entry->url_col = url_col; - entry->extra_col = extra_col; - entry->favicon_col = favicon_col; - - completion = gtk_entry_completion_new (); - gtk_entry_completion_set_model (completion, model); - g_signal_connect (completion, "match-selected", - G_CALLBACK (match_selected_cb), entry); - g_signal_connect_after (completion, "action-activated", - G_CALLBACK (action_activated_after_cb), entry); - - cell = gtk_cell_renderer_pixbuf_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion), - cell, FALSE); - gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (completion), - cell, "pixbuf", favicon_col); - - /* Pixel-perfect aligment with the location entry favicon - * (16x16). Consider that this /might/ depend on the theme. - * - * The GtkEntryCompletion can not be themed so we work-around - * that with padding and fixed sizes. - * For the first cell, this is: - * - * ___+++++iiiiiiiiiiiiiiii++__ttt...bbb++++++__ - * - * _ = widget spacing, can not be handled (3 px) - * + = padding (5 px) (ICON_PADDING_LEFT) - * i = the icon (16 px) (ICON_CONTENT_WIDTH) - * + = padding (2 px) (ICON_PADDING_RIGHT) (cut by the fixed_size) - * _ = spacing between cells, can not be handled (2 px) - * t = the text (expands) - * b = bookmark icon (16 px) - * + = padding (6 px) (BKMK_PADDING_RIGHT) - * _ = widget spacing, can not be handled (2 px) - * - * Each character is a pixel. - * - * The text cell and the bookmark icon cell are much more - * flexible in its aligment, because they do not have to align - * with anything in the entry. - */ - -#define ROW_PADDING_VERT 4 - -#define ICON_PADDING_LEFT 5 -#define ICON_CONTENT_WIDTH 16 -#define ICON_PADDING_RIGHT 9 - -#define ICON_CONTENT_HEIGHT 16 - -#define TEXT_PADDING_LEFT 0 - -#define BKMK_PADDING_RIGHT 6 - - gtk_cell_renderer_set_padding - (cell, ICON_PADDING_LEFT, ROW_PADDING_VERT); - gtk_cell_renderer_set_fixed_size - (cell, - (ICON_PADDING_LEFT + ICON_CONTENT_WIDTH + ICON_PADDING_RIGHT), - ICON_CONTENT_HEIGHT); - gtk_cell_renderer_set_alignment (cell, 0.0, 0.5); - - cell = gd_two_lines_renderer_new (); - g_object_set (cell, - "ellipsize", PANGO_ELLIPSIZE_END, - "text-lines", 2, - NULL); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion), - cell, TRUE); - gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (completion), - cell, "text", text_col); - gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (completion), - cell, "line-two", url_col); - - /* Pixel-perfect aligment with the text in the location entry. - * See above. - */ - gtk_cell_renderer_set_padding - (cell, TEXT_PADDING_LEFT, ROW_PADDING_VERT); - gtk_cell_renderer_set_alignment (cell, 0.0, 0.5); - - /* - * As the width of the entry completion is known in advance - * (as big as the entry you are completing on), we can set - * any fixed width (the 1 is just this random number here) - * Since the height is known too, we avoid computing the actual - * sizes of the cells, which takes a lot of CPU time and does - * not get used anyway. - */ - gtk_cell_renderer_set_fixed_size (cell, 1, -1); - gtk_cell_renderer_text_set_fixed_height_from_font (GTK_CELL_RENDERER_TEXT (cell), 2); - - cell = gtk_cell_renderer_pixbuf_new (); - g_object_set (cell, "follow-state", TRUE, NULL); - gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (completion), - cell, FALSE); - gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (completion), - cell, extracell_data_func, - entry, - NULL); - - /* Pixel-perfect aligment. This just keeps the same margin from - * the border than the favicon on the other side. See above. */ - gtk_cell_renderer_set_padding - (cell, BKMK_PADDING_RIGHT, ROW_PADDING_VERT); - - g_object_set (completion, "inline-selection", TRUE, NULL); - g_signal_connect (completion, "cursor-on-match", - G_CALLBACK (cursor_on_match_cb), entry); - - gtk_entry_set_completion (GTK_ENTRY (entry), completion); - g_object_unref (completion); -} - /** * ephy_location_entry_get_can_undo: * @entry: an #EphyLocationEntry widget @@ -1125,9 +822,8 @@ ephy_location_entry_reset_internal (EphyLocationEntry *entry, ephy_title_widget_set_address (EPHY_TITLE_WIDGET (entry), text); g_free (url); - if (notify) { + if (notify) g_signal_emit (entry, signals[USER_CHANGED], 0); - } entry->user_changed = FALSE; @@ -1167,7 +863,7 @@ ephy_location_entry_reset (EphyLocationEntry *entry) } /** - * ephy_location_entry_activate: + * ephy_location_entry_focus: * @entry: an #EphyLocationEntry widget * * Set focus on @entry and select the text whithin. This is called when the @@ -1175,7 +871,7 @@ ephy_location_entry_reset (EphyLocationEntry *entry) * **/ void -ephy_location_entry_activate (EphyLocationEntry *entry) +ephy_location_entry_focus (EphyLocationEntry *entry) { GtkWidget *toplevel, *widget = GTK_WIDGET (entry); diff --git a/lib/widgets/ephy-location-entry.h b/lib/widgets/ephy-location-entry.h index 490524a09..950d06158 100644 --- a/lib/widgets/ephy-location-entry.h +++ b/lib/widgets/ephy-location-entry.h @@ -23,6 +23,7 @@ #pragma once +#include <dazzle.h> #include <gtk/gtk.h> #include "ephy-security-levels.h" @@ -31,7 +32,7 @@ G_BEGIN_DECLS #define EPHY_TYPE_LOCATION_ENTRY (ephy_location_entry_get_type()) -G_DECLARE_FINAL_TYPE (EphyLocationEntry, ephy_location_entry, EPHY, LOCATION_ENTRY, GtkEntry) +G_DECLARE_FINAL_TYPE (EphyLocationEntry, ephy_location_entry, EPHY, LOCATION_ENTRY, DzlSuggestionEntry) typedef enum { EPHY_LOCATION_ENTRY_BOOKMARK_ICON_HIDDEN, @@ -41,21 +42,6 @@ typedef enum { GtkWidget *ephy_location_entry_new (void); -void ephy_location_entry_set_completion (EphyLocationEntry *entry, - GtkTreeModel *model, - guint text_col, - guint action_col, - guint keywords_col, - guint relevance_col, - guint url_col, - guint extra_col, - guint favicon_col); - -void ephy_location_entry_set_match_func (EphyLocationEntry *entry, - GtkEntryCompletionMatchFunc match_func, - gpointer user_data, - GDestroyNotify notify); - gboolean ephy_location_entry_get_can_undo (EphyLocationEntry *entry); gboolean ephy_location_entry_get_can_redo (EphyLocationEntry *entry); @@ -66,7 +52,7 @@ gboolean ephy_location_entry_reset (EphyLocationEntr void ephy_location_entry_undo_reset (EphyLocationEntry *entry); -void ephy_location_entry_activate (EphyLocationEntry *entry); +void ephy_location_entry_focus (EphyLocationEntry *entry); void ephy_location_entry_set_bookmark_icon_state (EphyLocationEntry *entry, EphyLocationEntryBookmarkIconState state); diff --git a/lib/widgets/meson.build b/lib/widgets/meson.build index 1c5c8492d..c927648d3 100644 --- a/lib/widgets/meson.build +++ b/lib/widgets/meson.build @@ -7,7 +7,6 @@ enums = gnome.mkenums_simple('ephy-widgets-type-builtins', ) libephywidgets_sources = [ - 'contrib/gd-two-lines-renderer.c', 'contrib/nautilus-floating-bar.c', 'ephy-certificate-dialog.c', 'ephy-downloads-popover.c', @@ -30,6 +29,7 @@ libephywidgets_deps = [ gio_dep, glib_dep, gtk_dep, + libdazzle_dep, libsoup_dep, webkit2gtk_dep ] |