|
Packit |
116408 |
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
|
|
Packit |
116408 |
/*
|
|
Packit |
116408 |
* Copyright (C) 2018 Sébastien Wilmet <swilmet@gnome.org>
|
|
Packit |
116408 |
*
|
|
Packit |
116408 |
* This program is free software; you can redistribute it and/or
|
|
Packit |
116408 |
* modify it under the terms of the GNU General Public License as
|
|
Packit |
116408 |
* published by the Free Software Foundation; either version 2 of the
|
|
Packit |
116408 |
* License, or (at your option) any later version.
|
|
Packit |
116408 |
*
|
|
Packit |
116408 |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
116408 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
116408 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
116408 |
* General Public License for more details.
|
|
Packit |
116408 |
*
|
|
Packit |
116408 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
116408 |
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
|
|
Packit |
116408 |
#include "dh-web-view.h"
|
|
Packit |
116408 |
#include <math.h>
|
|
Packit |
116408 |
#include <glib/gi18n.h>
|
|
Packit |
116408 |
|
|
Packit |
116408 |
struct _DhWebViewPrivate {
|
|
Packit |
116408 |
gchar *search_text;
|
|
Packit |
116408 |
gdouble total_scroll_delta_y;
|
|
Packit |
116408 |
};
|
|
Packit |
116408 |
|
|
Packit |
116408 |
static const gdouble zoom_levels[] = {
|
|
Packit |
116408 |
0.5, /* 50% */
|
|
Packit |
116408 |
0.8408964152, /* 75% */
|
|
Packit |
116408 |
1.0, /* 100% */
|
|
Packit |
116408 |
1.1892071149, /* 125% */
|
|
Packit |
116408 |
1.4142135623, /* 150% */
|
|
Packit |
116408 |
1.6817928304, /* 175% */
|
|
Packit |
116408 |
2.0, /* 200% */
|
|
Packit |
116408 |
2.8284271247, /* 300% */
|
|
Packit |
116408 |
4.0 /* 400% */
|
|
Packit |
116408 |
};
|
|
Packit |
116408 |
|
|
Packit |
116408 |
static const guint n_zoom_levels = G_N_ELEMENTS (zoom_levels);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
#define ZOOM_DEFAULT (zoom_levels[2])
|
|
Packit |
116408 |
|
|
Packit |
116408 |
G_DEFINE_TYPE_WITH_PRIVATE (DhWebView, dh_web_view, WEBKIT_TYPE_WEB_VIEW)
|
|
Packit |
116408 |
|
|
Packit |
116408 |
static gint
|
|
Packit |
116408 |
get_current_zoom_level_index (DhWebView *view)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
gdouble zoom_level;
|
|
Packit |
116408 |
gdouble previous;
|
|
Packit |
116408 |
guint i;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
zoom_level = webkit_web_view_get_zoom_level (WEBKIT_WEB_VIEW (view));
|
|
Packit |
116408 |
|
|
Packit |
116408 |
previous = zoom_levels[0];
|
|
Packit |
116408 |
for (i = 1; i < n_zoom_levels; i++) {
|
|
Packit |
116408 |
gdouble current = zoom_levels[i];
|
|
Packit |
116408 |
gdouble mean = sqrt (previous * current);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (zoom_level <= mean)
|
|
Packit |
116408 |
return i - 1;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
previous = current;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
return n_zoom_levels - 1;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
static void
|
|
Packit |
116408 |
bump_zoom_level (DhWebView *view,
|
|
Packit |
116408 |
gint bump_amount)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
gint zoom_level_index;
|
|
Packit |
116408 |
gdouble new_zoom_level;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (bump_amount == 0)
|
|
Packit |
116408 |
return;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
zoom_level_index = get_current_zoom_level_index (view) + bump_amount;
|
|
Packit |
116408 |
zoom_level_index = CLAMP (zoom_level_index, 0, (gint)n_zoom_levels - 1);
|
|
Packit |
116408 |
new_zoom_level = zoom_levels[zoom_level_index];
|
|
Packit |
116408 |
|
|
Packit |
116408 |
webkit_web_view_set_zoom_level (WEBKIT_WEB_VIEW (view), new_zoom_level);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
static gboolean
|
|
Packit |
116408 |
dh_web_view_scroll_event (GtkWidget *widget,
|
|
Packit |
116408 |
GdkEventScroll *scroll_event)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
DhWebView *view = DH_WEB_VIEW (widget);
|
|
Packit |
116408 |
gdouble delta_y;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if ((scroll_event->state & GDK_CONTROL_MASK) == 0)
|
|
Packit |
116408 |
goto chain_up;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
switch (scroll_event->direction) {
|
|
Packit |
116408 |
case GDK_SCROLL_UP:
|
|
Packit |
116408 |
bump_zoom_level (view, 1);
|
|
Packit |
116408 |
return GDK_EVENT_STOP;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
case GDK_SCROLL_DOWN:
|
|
Packit |
116408 |
bump_zoom_level (view, -1);
|
|
Packit |
116408 |
return GDK_EVENT_STOP;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
case GDK_SCROLL_LEFT:
|
|
Packit |
116408 |
case GDK_SCROLL_RIGHT:
|
|
Packit |
116408 |
break;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
case GDK_SCROLL_SMOOTH:
|
|
Packit |
116408 |
gdk_event_get_scroll_deltas ((GdkEvent *)scroll_event, NULL, &delta_y);
|
|
Packit |
116408 |
view->priv->total_scroll_delta_y += delta_y;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Avoiding direct float comparison.
|
|
Packit |
116408 |
* -1 and 1 are the thresholds for bumping the zoom level,
|
|
Packit |
116408 |
* which can be adjusted for taste.
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
if ((gint)view->priv->total_scroll_delta_y <= -1) {
|
|
Packit |
116408 |
view->priv->total_scroll_delta_y = 0.f;
|
|
Packit |
116408 |
bump_zoom_level (view, 1);
|
|
Packit |
116408 |
} else if ((gint)view->priv->total_scroll_delta_y >= 1) {
|
|
Packit |
116408 |
view->priv->total_scroll_delta_y = 0.f;
|
|
Packit |
116408 |
bump_zoom_level (view, -1);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
return GDK_EVENT_STOP;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
default:
|
|
Packit |
116408 |
g_warn_if_reached ();
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
chain_up:
|
|
Packit |
116408 |
if (GTK_WIDGET_CLASS (dh_web_view_parent_class)->scroll_event == NULL)
|
|
Packit |
116408 |
return GDK_EVENT_PROPAGATE;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
return GTK_WIDGET_CLASS (dh_web_view_parent_class)->scroll_event (widget, scroll_event);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
static void
|
|
Packit |
116408 |
dh_web_view_constructed (GObject *object)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
WebKitWebView *view = WEBKIT_WEB_VIEW (object);
|
|
Packit |
116408 |
WebKitSettings *settings;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (G_OBJECT_CLASS (dh_web_view_parent_class)->constructed != NULL)
|
|
Packit |
116408 |
G_OBJECT_CLASS (dh_web_view_parent_class)->constructed (object);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Disable some things we have no need for. */
|
|
Packit |
116408 |
settings = webkit_web_view_get_settings (view);
|
|
Packit |
116408 |
webkit_settings_set_enable_html5_database (settings, FALSE);
|
|
Packit |
116408 |
webkit_settings_set_enable_html5_local_storage (settings, FALSE);
|
|
Packit |
116408 |
webkit_settings_set_enable_plugins (settings, FALSE);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
static void
|
|
Packit |
116408 |
dh_web_view_finalize (GObject *object)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
DhWebView *view = DH_WEB_VIEW (object);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_free (view->priv->search_text);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
G_OBJECT_CLASS (dh_web_view_parent_class)->finalize (object);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
static void
|
|
Packit |
116408 |
dh_web_view_class_init (DhWebViewClass *klass)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
Packit |
116408 |
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
object_class->constructed = dh_web_view_constructed;
|
|
Packit |
116408 |
object_class->finalize = dh_web_view_finalize;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
widget_class->scroll_event = dh_web_view_scroll_event;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
static void
|
|
Packit |
116408 |
dh_web_view_init (DhWebView *view)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
view->priv = dh_web_view_get_instance_private (view);
|
|
Packit |
116408 |
view->priv->total_scroll_delta_y = 0.f;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
gtk_widget_set_hexpand (GTK_WIDGET (view), TRUE);
|
|
Packit |
116408 |
gtk_widget_set_vexpand (GTK_WIDGET (view), TRUE);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
DhWebView *
|
|
Packit |
116408 |
dh_web_view_new (void)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
return g_object_new (DH_TYPE_WEB_VIEW, NULL);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
const gchar *
|
|
Packit |
116408 |
dh_web_view_get_devhelp_title (DhWebView *view)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
const gchar *title;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_return_val_if_fail (DH_IS_WEB_VIEW (view), NULL);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
title = webkit_web_view_get_title (WEBKIT_WEB_VIEW (view));
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (title == NULL || title[0] == '\0')
|
|
Packit |
116408 |
title = _("Empty Page");
|
|
Packit |
116408 |
|
|
Packit |
116408 |
return title;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/*
|
|
Packit |
116408 |
* dh_web_view_set_search_text:
|
|
Packit |
116408 |
* @view: a #DhWebView.
|
|
Packit |
116408 |
* @search_text: (nullable): the search string, or %NULL.
|
|
Packit |
116408 |
*
|
|
Packit |
116408 |
* A more convenient API (for Devhelp needs) than #WebKitFindController. If
|
|
Packit |
116408 |
* @search_text is not empty, it calls webkit_find_controller_search() if not
|
|
Packit |
116408 |
* already done. If @search_text is empty or %NULL, it calls
|
|
Packit |
116408 |
* webkit_find_controller_search_finish().
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
void
|
|
Packit |
116408 |
dh_web_view_set_search_text (DhWebView *view,
|
|
Packit |
116408 |
const gchar *search_text)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
WebKitFindController *find_controller;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_return_if_fail (DH_IS_WEB_VIEW (view));
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (g_strcmp0 (view->priv->search_text, search_text) == 0)
|
|
Packit |
116408 |
return;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_free (view->priv->search_text);
|
|
Packit |
116408 |
view->priv->search_text = g_strdup (search_text);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
find_controller = webkit_web_view_get_find_controller (WEBKIT_WEB_VIEW (view));
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (search_text != NULL && search_text[0] != '\0') {
|
|
Packit |
116408 |
/* If webkit_find_controller_search() is called a second time
|
|
Packit |
116408 |
* with the same parameters it's not a NOP, it launches a new
|
|
Packit |
116408 |
* search, apparently, which screws up search_next() and
|
|
Packit |
116408 |
* search_previous(). So we must call it only once for the same
|
|
Packit |
116408 |
* search string.
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
webkit_find_controller_search (find_controller,
|
|
Packit |
116408 |
search_text,
|
|
Packit |
116408 |
WEBKIT_FIND_OPTIONS_WRAP_AROUND |
|
|
Packit |
116408 |
WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE,
|
|
Packit |
116408 |
G_MAXUINT);
|
|
Packit |
116408 |
} else {
|
|
Packit |
116408 |
/* It's fine to call it several times. But unfortunately it
|
|
Packit |
116408 |
* doesn't change the WebKitFindController:text property. So we
|
|
Packit |
116408 |
* must store our own search_text.
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
webkit_find_controller_search_finish (find_controller);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
void
|
|
Packit |
116408 |
dh_web_view_search_next (DhWebView *view)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
WebKitFindController *find_controller;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_return_if_fail (DH_IS_WEB_VIEW (view));
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (view->priv->search_text == NULL || view->priv->search_text[0] == '\0')
|
|
Packit |
116408 |
return;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
find_controller = webkit_web_view_get_find_controller (WEBKIT_WEB_VIEW (view));
|
|
Packit |
116408 |
webkit_find_controller_search_next (find_controller);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
void
|
|
Packit |
116408 |
dh_web_view_search_previous (DhWebView *view)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
WebKitFindController *find_controller;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_return_if_fail (DH_IS_WEB_VIEW (view));
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (view->priv->search_text == NULL || view->priv->search_text[0] == '\0')
|
|
Packit |
116408 |
return;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
find_controller = webkit_web_view_get_find_controller (WEBKIT_WEB_VIEW (view));
|
|
Packit |
116408 |
webkit_find_controller_search_previous (find_controller);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
gboolean
|
|
Packit |
116408 |
dh_web_view_can_zoom_in (DhWebView *view)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
gint zoom_level_index;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_return_val_if_fail (DH_IS_WEB_VIEW (view), FALSE);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
zoom_level_index = get_current_zoom_level_index (view);
|
|
Packit |
116408 |
return zoom_level_index < ((gint)n_zoom_levels - 1);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
gboolean
|
|
Packit |
116408 |
dh_web_view_can_zoom_out (DhWebView *view)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
gint zoom_level_index;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_return_val_if_fail (DH_IS_WEB_VIEW (view), FALSE);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
zoom_level_index = get_current_zoom_level_index (view);
|
|
Packit |
116408 |
return zoom_level_index > 0;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
gboolean
|
|
Packit |
116408 |
dh_web_view_can_reset_zoom (DhWebView *view)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
gint zoom_level_index;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_return_val_if_fail (DH_IS_WEB_VIEW (view), FALSE);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
zoom_level_index = get_current_zoom_level_index (view);
|
|
Packit |
116408 |
return zoom_levels[zoom_level_index] != ZOOM_DEFAULT;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
void
|
|
Packit |
116408 |
dh_web_view_zoom_in (DhWebView *view)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
g_return_if_fail (DH_IS_WEB_VIEW (view));
|
|
Packit |
116408 |
|
|
Packit |
116408 |
bump_zoom_level (view, 1);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
void
|
|
Packit |
116408 |
dh_web_view_zoom_out (DhWebView *view)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
g_return_if_fail (DH_IS_WEB_VIEW (view));
|
|
Packit |
116408 |
|
|
Packit |
116408 |
bump_zoom_level (view, -1);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
void
|
|
Packit |
116408 |
dh_web_view_reset_zoom (DhWebView *view)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
g_return_if_fail (DH_IS_WEB_VIEW (view));
|
|
Packit |
116408 |
|
|
Packit |
116408 |
webkit_web_view_set_zoom_level (WEBKIT_WEB_VIEW (view), ZOOM_DEFAULT);
|
|
Packit |
116408 |
}
|