10c5ac4597
So prefetching in private mode is disabled regardless of whether prefetching is done in Midori or in new WebKit versions. Menu items also adhere to that same setting now. And use the chance to correct version checks.
5792 lines
196 KiB
C
5792 lines
196 KiB
C
/*
|
||
Copyright (C) 2007-2010 Christian Dywan <christian@twotoasts.de>
|
||
Copyright (C) 2009 Jean-François Guchens <zcx000@gmail.com>
|
||
|
||
This library 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.1 of the License, or (at your option) any later version.
|
||
|
||
See the file COPYING for the full license text.
|
||
*/
|
||
|
||
#if HAVE_CONFIG_H
|
||
#include <config.h>
|
||
#endif
|
||
|
||
#include "midori-view.h"
|
||
#include "midori-stock.h"
|
||
#include "midori-browser.h"
|
||
|
||
#include "marshal.h"
|
||
#include "sokoke.h"
|
||
|
||
#include <string.h>
|
||
#include <stdlib.h>
|
||
#include <glib/gi18n.h>
|
||
#include <glib/gprintf.h>
|
||
#include <glib/gstdio.h>
|
||
#include <gdk/gdkkeysyms.h>
|
||
#include <webkit/webkit.h>
|
||
|
||
#if HAVE_UNISTD_H
|
||
#include <unistd.h>
|
||
#endif
|
||
|
||
#ifndef G_OS_WIN32
|
||
#include <sys/utsname.h>
|
||
#endif
|
||
|
||
/* This is unstable API, so we need to declare it */
|
||
gchar*
|
||
webkit_web_view_get_selected_text (WebKitWebView* web_view);
|
||
/* This is public API since WebKitGTK+ 1.1.6 */
|
||
#if !WEBKIT_CHECK_VERSION (1, 1, 6)
|
||
void
|
||
webkit_web_frame_print (WebKitWebFrame* web_frame);
|
||
#endif
|
||
|
||
GdkPixbuf*
|
||
midori_search_action_get_icon (KatzeItem* item,
|
||
GtkWidget* widget,
|
||
const gchar** icon_name);
|
||
|
||
static void
|
||
midori_view_construct_web_view (MidoriView* view);
|
||
|
||
static void
|
||
midori_view_item_meta_data_changed (KatzeItem* item,
|
||
const gchar* key,
|
||
MidoriView* view);
|
||
|
||
static void
|
||
_midori_view_set_settings (MidoriView* view,
|
||
MidoriWebSettings* settings);
|
||
|
||
struct _MidoriView
|
||
{
|
||
GtkVBox parent_instance;
|
||
|
||
gchar* uri;
|
||
gboolean special;
|
||
gchar* title;
|
||
MidoriSecurity security;
|
||
gchar* mime_type;
|
||
GdkPixbuf* icon;
|
||
gchar* icon_uri;
|
||
gdouble progress;
|
||
MidoriLoadStatus load_status;
|
||
gboolean minimized;
|
||
gchar* statusbar_text;
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 15)
|
||
WebKitHitTestResult* hit_test;
|
||
#endif
|
||
gchar* link_uri;
|
||
gboolean has_selection;
|
||
gchar* selected_text;
|
||
MidoriWebSettings* settings;
|
||
GtkWidget* web_view;
|
||
GtkWidget* thumb_view;
|
||
KatzeArray* news_feeds;
|
||
|
||
gchar* news_aggregator;
|
||
gboolean middle_click_opens_selection;
|
||
gboolean open_tabs_in_the_background;
|
||
gboolean close_buttons_on_tabs;
|
||
MidoriNewPage open_new_pages_in;
|
||
gint find_links;
|
||
gint alerts;
|
||
|
||
GtkWidget* menu_item;
|
||
GtkWidget* tab_label;
|
||
GtkWidget* tab_icon;
|
||
GtkWidget* tab_title;
|
||
GtkWidget* tab_close;
|
||
KatzeItem* item;
|
||
gint scrollh, scrollv;
|
||
gboolean back_forward_set;
|
||
GHashTable* memory;
|
||
GtkWidget* scrolled_window;
|
||
};
|
||
|
||
struct _MidoriViewClass
|
||
{
|
||
GtkVBoxClass parent_class;
|
||
};
|
||
|
||
G_DEFINE_TYPE (MidoriView, midori_view, GTK_TYPE_VBOX);
|
||
|
||
GType
|
||
midori_load_status_get_type (void)
|
||
{
|
||
static GType type = 0;
|
||
static const GEnumValue values[] = {
|
||
{ MIDORI_LOAD_PROVISIONAL, "MIDORI_LOAD_PROVISIONAL", "Load Provisional" },
|
||
{ MIDORI_LOAD_COMMITTED, "MIDORI_LOAD_COMMITTED", "Load Committed" },
|
||
{ MIDORI_LOAD_FINISHED, "MIDORI_LOAD_FINISHED", "Load Finished" },
|
||
{ 0, NULL, NULL }
|
||
};
|
||
|
||
if (type)
|
||
return type;
|
||
|
||
type = g_enum_register_static ("MidoriLoadStatus", values);
|
||
return type;
|
||
}
|
||
|
||
GType
|
||
midori_new_view_get_type (void)
|
||
{
|
||
static GType type = 0;
|
||
if (!type)
|
||
{
|
||
static const GEnumValue values[] = {
|
||
{ MIDORI_NEW_VIEW_TAB, "MIDORI_NEW_VIEW_TAB", "New view in a tab" },
|
||
{ MIDORI_NEW_VIEW_BACKGROUND, "MIDORI_NEW_VIEW_BACKGROUND",
|
||
"New view in a background tab" },
|
||
{ MIDORI_NEW_VIEW_WINDOW, "MIDORI_NEW_VIEW_WINDOW",
|
||
"New view in a window" },
|
||
{ 0, NULL, NULL }
|
||
};
|
||
type = g_enum_register_static ("MidoriNewView", values);
|
||
}
|
||
return type;
|
||
}
|
||
|
||
GType
|
||
midori_security_get_type (void)
|
||
{
|
||
static GType type = 0;
|
||
if (!type)
|
||
{
|
||
static const GEnumValue values[] = {
|
||
{ MIDORI_SECURITY_NONE, "MIDORI_SECURITY_NONE", "No security" },
|
||
{ MIDORI_SECURITY_UNKNOWN, "MIDORI_SECURITY_UNKNOWN", "Security unknown" },
|
||
{ MIDORI_SECURITY_TRUSTED, "MIDORI_SECURITY_TRUSTED", "Trusted security" },
|
||
{ 0, NULL, NULL }
|
||
};
|
||
type = g_enum_register_static ("MidoriSecurity", values);
|
||
}
|
||
return type;
|
||
}
|
||
|
||
enum
|
||
{
|
||
PROP_0,
|
||
|
||
PROP_URI,
|
||
PROP_TITLE,
|
||
PROP_SECURITY,
|
||
PROP_MIME_TYPE,
|
||
PROP_ICON,
|
||
PROP_LOAD_STATUS,
|
||
PROP_PROGRESS,
|
||
PROP_MINIMIZED,
|
||
PROP_ZOOM_LEVEL,
|
||
PROP_NEWS_FEEDS,
|
||
PROP_STATUSBAR_TEXT,
|
||
PROP_SETTINGS
|
||
};
|
||
|
||
enum {
|
||
ACTIVATE_ACTION,
|
||
CONSOLE_MESSAGE,
|
||
CONTEXT_READY,
|
||
ATTACH_INSPECTOR,
|
||
DETACH_INSPECTOR,
|
||
NEW_TAB,
|
||
NEW_WINDOW,
|
||
NEW_VIEW,
|
||
DOWNLOAD_REQUESTED,
|
||
SEARCH_TEXT,
|
||
ADD_BOOKMARK,
|
||
SAVE_AS,
|
||
ADD_SPEED_DIAL,
|
||
|
||
LAST_SIGNAL
|
||
};
|
||
|
||
static guint signals[LAST_SIGNAL];
|
||
|
||
static void
|
||
midori_view_finalize (GObject* object);
|
||
|
||
static void
|
||
midori_view_set_property (GObject* object,
|
||
guint prop_id,
|
||
const GValue* value,
|
||
GParamSpec* pspec);
|
||
|
||
static void
|
||
midori_view_get_property (GObject* object,
|
||
guint prop_id,
|
||
GValue* value,
|
||
GParamSpec* pspec);
|
||
|
||
static gboolean
|
||
midori_view_focus_in_event (GtkWidget* widget,
|
||
GdkEventFocus* event);
|
||
|
||
static void
|
||
midori_view_settings_notify_cb (MidoriWebSettings* settings,
|
||
GParamSpec* pspec,
|
||
MidoriView* view);
|
||
|
||
static void
|
||
midori_view_speed_dial_save (MidoriView* view,
|
||
const gchar* message);
|
||
|
||
static void
|
||
midori_view_class_init (MidoriViewClass* class)
|
||
{
|
||
GObjectClass* gobject_class;
|
||
GtkWidgetClass* gtkwidget_class;
|
||
GParamFlags flags;
|
||
|
||
signals[ACTIVATE_ACTION] = g_signal_new (
|
||
"activate-action",
|
||
G_TYPE_FROM_CLASS (class),
|
||
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||
0,
|
||
0,
|
||
NULL,
|
||
g_cclosure_marshal_VOID__STRING,
|
||
G_TYPE_NONE, 1,
|
||
G_TYPE_STRING);
|
||
|
||
signals[CONSOLE_MESSAGE] = g_signal_new (
|
||
"console-message",
|
||
G_TYPE_FROM_CLASS (class),
|
||
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||
0,
|
||
0,
|
||
NULL,
|
||
midori_cclosure_marshal_VOID__STRING_INT_STRING,
|
||
G_TYPE_NONE, 3,
|
||
G_TYPE_STRING,
|
||
G_TYPE_INT,
|
||
G_TYPE_STRING);
|
||
|
||
signals[CONTEXT_READY] = g_signal_new (
|
||
"context-ready",
|
||
G_TYPE_FROM_CLASS (class),
|
||
(GSignalFlags)(G_SIGNAL_RUN_LAST),
|
||
0,
|
||
0,
|
||
NULL,
|
||
g_cclosure_marshal_VOID__POINTER,
|
||
G_TYPE_NONE, 1,
|
||
G_TYPE_POINTER);
|
||
|
||
signals[ATTACH_INSPECTOR] = g_signal_new (
|
||
"attach-inspector",
|
||
G_TYPE_FROM_CLASS (class),
|
||
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||
0,
|
||
0,
|
||
NULL,
|
||
g_cclosure_marshal_VOID__OBJECT,
|
||
G_TYPE_NONE, 1,
|
||
GTK_TYPE_WIDGET);
|
||
|
||
/**
|
||
* MidoriView::detach-inspector:
|
||
* @view: the object on which the signal is emitted
|
||
*
|
||
* Emitted when an open inspector that was previously
|
||
* attached to the window is now detached again.
|
||
*
|
||
* Since: 0.3.4
|
||
*/
|
||
signals[DETACH_INSPECTOR] = g_signal_new (
|
||
"detach-inspector",
|
||
G_TYPE_FROM_CLASS (class),
|
||
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||
0,
|
||
0,
|
||
NULL,
|
||
g_cclosure_marshal_VOID__OBJECT,
|
||
G_TYPE_NONE, 1,
|
||
GTK_TYPE_WIDGET);
|
||
|
||
signals[NEW_TAB] = g_signal_new (
|
||
"new-tab",
|
||
G_TYPE_FROM_CLASS (class),
|
||
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||
0,
|
||
0,
|
||
NULL,
|
||
midori_cclosure_marshal_VOID__STRING_BOOLEAN,
|
||
G_TYPE_NONE, 2,
|
||
G_TYPE_STRING,
|
||
G_TYPE_BOOLEAN);
|
||
|
||
signals[NEW_WINDOW] = g_signal_new (
|
||
"new-window",
|
||
G_TYPE_FROM_CLASS (class),
|
||
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||
0,
|
||
0,
|
||
NULL,
|
||
g_cclosure_marshal_VOID__STRING,
|
||
G_TYPE_NONE, 1,
|
||
G_TYPE_STRING);
|
||
|
||
/**
|
||
* MidoriView::new-view:
|
||
* @view: the object on which the signal is emitted
|
||
* @new_view: a newly created view
|
||
* @where: where to open the view
|
||
*
|
||
* Emitted when a new view is created. The value of
|
||
* @where determines where to open the view according
|
||
* to how it was opened and user preferences.
|
||
*
|
||
* Since: 0.1.2
|
||
*/
|
||
signals[NEW_VIEW] = g_signal_new (
|
||
"new-view",
|
||
G_TYPE_FROM_CLASS (class),
|
||
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||
0,
|
||
0,
|
||
NULL,
|
||
midori_cclosure_marshal_VOID__OBJECT_ENUM,
|
||
G_TYPE_NONE, 2,
|
||
MIDORI_TYPE_VIEW,
|
||
MIDORI_TYPE_NEW_VIEW);
|
||
|
||
/**
|
||
* MidoriView::download-requested:
|
||
* @view: the object on which the signal is emitted
|
||
* @download: a new download
|
||
*
|
||
* Emitted when a new download is requested, if a
|
||
* file cannot be displayed or a download was started
|
||
* from the context menu.
|
||
*
|
||
* If the download should be accepted, a callback
|
||
* has to return %TRUE, and the download will also
|
||
* be started automatically.
|
||
*
|
||
* Note: This requires WebKitGTK 1.1.3.
|
||
*
|
||
* Return value: %TRUE if the download was handled
|
||
*
|
||
* Since: 0.1.5
|
||
*/
|
||
signals[DOWNLOAD_REQUESTED] = g_signal_new (
|
||
"download-requested",
|
||
G_TYPE_FROM_CLASS (class),
|
||
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||
0,
|
||
g_signal_accumulator_true_handled,
|
||
NULL,
|
||
midori_cclosure_marshal_BOOLEAN__OBJECT,
|
||
G_TYPE_BOOLEAN, 1,
|
||
G_TYPE_OBJECT);
|
||
|
||
/**
|
||
* MidoriView::search-text:
|
||
* @view: the object on which the signal is emitted
|
||
* @found: whether the search was successful
|
||
* @typing: whether the search was initiated by typing
|
||
*
|
||
* Emitted when a search is performed. Either manually
|
||
* invoked or automatically by typing. The value of typing
|
||
* is actually the text the user typed.
|
||
*
|
||
* Note that in 0.1.3 the argument @typing was introduced.
|
||
*/
|
||
signals[SEARCH_TEXT] = g_signal_new (
|
||
"search-text",
|
||
G_TYPE_FROM_CLASS (class),
|
||
(GSignalFlags)(G_SIGNAL_RUN_LAST),
|
||
0,
|
||
0,
|
||
NULL,
|
||
midori_cclosure_marshal_VOID__BOOLEAN_STRING,
|
||
G_TYPE_NONE, 2,
|
||
G_TYPE_BOOLEAN,
|
||
G_TYPE_STRING);
|
||
|
||
/**
|
||
* MidoriView::add-bookmark:
|
||
* @view: the object on which the signal is emitted
|
||
* @uri: the bookmark URI
|
||
*
|
||
* Emitted when a bookmark is added.
|
||
*
|
||
* Deprecated: 0.2.7
|
||
*/
|
||
signals[ADD_BOOKMARK] = g_signal_new (
|
||
"add-bookmark",
|
||
G_TYPE_FROM_CLASS (class),
|
||
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||
0,
|
||
0,
|
||
NULL,
|
||
g_cclosure_marshal_VOID__STRING,
|
||
G_TYPE_NONE, 1,
|
||
G_TYPE_STRING);
|
||
|
||
signals[SAVE_AS] = g_signal_new (
|
||
"save-as",
|
||
G_TYPE_FROM_CLASS (class),
|
||
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||
0,
|
||
0,
|
||
NULL,
|
||
g_cclosure_marshal_VOID__STRING,
|
||
G_TYPE_NONE, 1,
|
||
G_TYPE_STRING);
|
||
|
||
/**
|
||
* MidoriView::add-speed-dial:
|
||
* @view: the object on which the signal is emitted
|
||
* @uri: the URI to add to the speed dial
|
||
*
|
||
* Emitted when an URI is added to the spee dial page.
|
||
*
|
||
* Since: 0.1.7
|
||
*/
|
||
signals[ADD_SPEED_DIAL] = g_signal_new (
|
||
"add-speed-dial",
|
||
G_TYPE_FROM_CLASS (class),
|
||
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||
0,
|
||
0,
|
||
NULL,
|
||
g_cclosure_marshal_VOID__STRING,
|
||
G_TYPE_NONE, 1,
|
||
G_TYPE_STRING);
|
||
|
||
gobject_class = G_OBJECT_CLASS (class);
|
||
gobject_class->finalize = midori_view_finalize;
|
||
gobject_class->set_property = midori_view_set_property;
|
||
gobject_class->get_property = midori_view_get_property;
|
||
|
||
gtkwidget_class = GTK_WIDGET_CLASS (class);
|
||
gtkwidget_class->focus_in_event = midori_view_focus_in_event;
|
||
|
||
flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS;
|
||
|
||
g_object_class_install_property (gobject_class,
|
||
PROP_URI,
|
||
g_param_spec_string (
|
||
"uri",
|
||
"Uri",
|
||
"The URI of the currently loaded page",
|
||
"about:blank",
|
||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||
|
||
g_object_class_install_property (gobject_class,
|
||
PROP_TITLE,
|
||
g_param_spec_string (
|
||
"title",
|
||
"Title",
|
||
"The title of the currently loaded page",
|
||
NULL,
|
||
flags));
|
||
|
||
/**
|
||
* MidoriView:security:
|
||
*
|
||
* The security status of the loaded page.
|
||
*
|
||
* Since: 0.2.5
|
||
*/
|
||
g_object_class_install_property (gobject_class,
|
||
PROP_SECURITY,
|
||
g_param_spec_enum (
|
||
"security",
|
||
"Security",
|
||
"The security of the currently loaded page",
|
||
MIDORI_TYPE_SECURITY,
|
||
MIDORI_SECURITY_NONE,
|
||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||
|
||
/**
|
||
* MidoriView:mime-type:
|
||
*
|
||
* The MIME type of the currently loaded page.
|
||
*
|
||
* Since: 0.1.2
|
||
*/
|
||
g_object_class_install_property (gobject_class,
|
||
PROP_MIME_TYPE,
|
||
g_param_spec_string (
|
||
"mime-type",
|
||
"MIME Type",
|
||
"The MIME type of the currently loaded page",
|
||
"text/html",
|
||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||
|
||
g_object_class_install_property (gobject_class,
|
||
PROP_ICON,
|
||
g_param_spec_object (
|
||
"icon",
|
||
"Icon",
|
||
"The icon of the view",
|
||
GDK_TYPE_PIXBUF,
|
||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||
|
||
g_object_class_install_property (gobject_class,
|
||
PROP_LOAD_STATUS,
|
||
g_param_spec_enum (
|
||
"load-status",
|
||
"Load Status",
|
||
"The current loading status",
|
||
MIDORI_TYPE_LOAD_STATUS,
|
||
MIDORI_LOAD_FINISHED,
|
||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||
|
||
g_object_class_install_property (gobject_class,
|
||
PROP_PROGRESS,
|
||
g_param_spec_double (
|
||
"progress",
|
||
"Progress",
|
||
"The current loading progress",
|
||
0.0, 1.0, 0.0,
|
||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||
|
||
/**
|
||
* MidoriView:minimized:
|
||
*
|
||
* Whether the view is minimized or in normal state.
|
||
*
|
||
* Minimizing a view indicates that only the icon should
|
||
* be advertised rather than the full blown tab label and
|
||
* it might otherwise be presented specially.
|
||
*
|
||
* Since: 0.1.8
|
||
*/
|
||
g_object_class_install_property (gobject_class,
|
||
PROP_MINIMIZED,
|
||
g_param_spec_boolean (
|
||
"minimized",
|
||
"Minimized",
|
||
"Whether the view is minimized or in normal state",
|
||
FALSE,
|
||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||
|
||
g_object_class_install_property (gobject_class,
|
||
PROP_ZOOM_LEVEL,
|
||
g_param_spec_float (
|
||
"zoom-level",
|
||
"Zoom Level",
|
||
"The current zoom level",
|
||
G_MINFLOAT,
|
||
G_MAXFLOAT,
|
||
1.0f,
|
||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||
|
||
/**
|
||
* MidoriView:news-feeds:
|
||
*
|
||
* The news feeds advertised by the currently loaded page.
|
||
*
|
||
* Since: 0.1.7
|
||
*/
|
||
g_object_class_install_property (gobject_class,
|
||
PROP_NEWS_FEEDS,
|
||
g_param_spec_object (
|
||
"news-feeds",
|
||
"News Feeds",
|
||
"The list of available news feeds",
|
||
KATZE_TYPE_ARRAY,
|
||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||
|
||
g_object_class_install_property (gobject_class,
|
||
PROP_STATUSBAR_TEXT,
|
||
g_param_spec_string (
|
||
"statusbar-text",
|
||
"Statusbar Text",
|
||
"The text displayed in the statusbar",
|
||
"",
|
||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||
|
||
g_object_class_install_property (gobject_class,
|
||
PROP_SETTINGS,
|
||
g_param_spec_object (
|
||
"settings",
|
||
"Settings",
|
||
"The associated settings",
|
||
MIDORI_TYPE_WEB_SETTINGS,
|
||
flags));
|
||
}
|
||
|
||
static void
|
||
midori_view_set_title (MidoriView* view, const gchar* title)
|
||
{
|
||
katze_assign (view->title, g_strdup (title));
|
||
#ifndef G_OS_WIN32
|
||
/* If left-to-right text is combined with right-to-left text the default
|
||
behaviour of Pango can result in awkwardly aligned text. For example
|
||
"بستيان نوصر (hadess) | An era comes to an end - Midori" becomes
|
||
"hadess) | An era comes to an end - Midori) بستيان نوصر". So to prevent
|
||
this we insert an LRE character before the title which indicates that
|
||
we want left-to-right but retains the direction of right-to-left text. */
|
||
if (view->title && !g_str_has_prefix (view->title, ""))
|
||
{
|
||
gchar* new_title = g_strconcat ("", view->title, NULL);
|
||
katze_assign (view->title, new_title);
|
||
}
|
||
#endif
|
||
#define title midori_view_get_display_title (view)
|
||
if (view->tab_label)
|
||
{
|
||
/* If the title starts with the presumed name of the website, we
|
||
ellipsize differently, to emphasize the subtitle */
|
||
if (gtk_label_get_angle (GTK_LABEL (view->tab_title)) == 0.0)
|
||
{
|
||
SoupURI* uri = soup_uri_new (view->uri);
|
||
const gchar* host = uri ? (uri->host ? uri->host : "") : "";
|
||
const gchar* name = g_str_has_prefix (host, "www.") ? &host[4] : host;
|
||
guint i = 0;
|
||
while (name[i++])
|
||
if (name[i] == '.')
|
||
break;
|
||
if (!g_ascii_strncasecmp (title, name, i))
|
||
gtk_label_set_ellipsize (GTK_LABEL (view->tab_title), PANGO_ELLIPSIZE_START);
|
||
else
|
||
gtk_label_set_ellipsize (GTK_LABEL (view->tab_title), PANGO_ELLIPSIZE_END);
|
||
if (uri)
|
||
soup_uri_free (uri);
|
||
}
|
||
gtk_label_set_text (GTK_LABEL (view->tab_title), title);
|
||
gtk_widget_set_tooltip_text (view->tab_icon, title);
|
||
gtk_widget_set_tooltip_text (view->tab_title, title);
|
||
}
|
||
if (view->menu_item)
|
||
gtk_label_set_text (GTK_LABEL (gtk_bin_get_child (GTK_BIN (
|
||
view->menu_item))), title);
|
||
katze_item_set_name (view->item, title);
|
||
#undef title
|
||
}
|
||
|
||
static void
|
||
midori_view_apply_icon (MidoriView* view,
|
||
GdkPixbuf* icon,
|
||
const gchar* icon_name)
|
||
{
|
||
katze_item_set_icon (view->item, icon_name);
|
||
katze_object_assign (view->icon, icon);
|
||
g_object_notify (G_OBJECT (view), "icon");
|
||
|
||
if (view->tab_icon)
|
||
{
|
||
if (icon_name)
|
||
katze_throbber_set_static_icon_name (KATZE_THROBBER (view->tab_icon),
|
||
icon_name);
|
||
else
|
||
katze_throbber_set_static_pixbuf (KATZE_THROBBER (view->tab_icon),
|
||
view->icon);
|
||
}
|
||
if (view->menu_item)
|
||
{
|
||
GtkWidget* image;
|
||
if (icon_name)
|
||
image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
|
||
else
|
||
image = gtk_image_new_from_pixbuf (view->icon);
|
||
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (view->menu_item), image);
|
||
}
|
||
}
|
||
|
||
static gboolean
|
||
midori_view_mime_icon (MidoriView* view,
|
||
GtkIconTheme* icon_theme,
|
||
const gchar* format,
|
||
const gchar* part1,
|
||
const gchar* part2)
|
||
{
|
||
gchar* icon_name;
|
||
GdkPixbuf* icon;
|
||
|
||
icon_name = part2 ? g_strdup_printf (format, part1, part2)
|
||
: g_strdup_printf (format, part1);
|
||
if (!(icon = gtk_icon_theme_load_icon (icon_theme, icon_name, 16, 0, NULL)))
|
||
{
|
||
g_free (icon_name);
|
||
return FALSE;
|
||
}
|
||
|
||
g_object_ref (icon);
|
||
midori_view_apply_icon (view, icon, icon_name);
|
||
g_free (icon_name);
|
||
return TRUE;
|
||
}
|
||
|
||
static void
|
||
midori_view_update_icon (MidoriView* view,
|
||
GdkPixbuf* icon)
|
||
{
|
||
GdkScreen* screen;
|
||
GtkIconTheme* theme;
|
||
gchar** parts = NULL;
|
||
|
||
if (icon)
|
||
{
|
||
midori_view_apply_icon (view, icon, NULL);
|
||
return;
|
||
}
|
||
|
||
if (!((screen = gtk_widget_get_screen (GTK_WIDGET (view)))
|
||
&& (theme = gtk_icon_theme_get_for_screen (screen))))
|
||
return;
|
||
|
||
if (!((parts = g_strsplit (view->mime_type, "/", 2)) && (*parts && parts[1])))
|
||
{
|
||
g_strfreev (parts);
|
||
/* This is a hack to have a Find icon in the location while the
|
||
blank page has a File icon. */
|
||
icon = gtk_widget_render_icon (GTK_WIDGET (view),
|
||
GTK_STOCK_FIND, GTK_ICON_SIZE_MENU, NULL);
|
||
midori_view_apply_icon (view, icon, GTK_STOCK_FILE);
|
||
return;
|
||
}
|
||
|
||
if (midori_view_mime_icon (view, theme, "%s-%s", *parts, parts[1]))
|
||
return;
|
||
if (midori_view_mime_icon (view, theme, "gnome-mime-%s-%s", *parts, parts[1]))
|
||
return;
|
||
if (midori_view_mime_icon (view, theme, "%s-x-generic", *parts, NULL))
|
||
return;
|
||
if (midori_view_mime_icon (view, theme, "gnome-mime-%s-x-generic", *parts, NULL))
|
||
return;
|
||
|
||
icon = gtk_widget_render_icon (GTK_WIDGET (view),
|
||
GTK_STOCK_FILE, GTK_ICON_SIZE_MENU, NULL);
|
||
midori_view_apply_icon (view, icon, NULL);
|
||
}
|
||
|
||
static void
|
||
midori_view_icon_cb (GdkPixbuf* icon,
|
||
MidoriView* view)
|
||
{
|
||
midori_view_update_icon (view, icon);
|
||
}
|
||
|
||
typedef void (*KatzeNetIconCb) (GdkPixbuf* icon,
|
||
MidoriView* view);
|
||
|
||
typedef struct
|
||
{
|
||
gchar* icon_file;
|
||
gchar* icon_uri;
|
||
MidoriView* view;
|
||
} KatzeNetIconPriv;
|
||
|
||
static void
|
||
katze_net_icon_priv_free (KatzeNetIconPriv* priv)
|
||
{
|
||
g_free (priv->icon_file);
|
||
g_free (priv->icon_uri);
|
||
g_slice_free (KatzeNetIconPriv, priv);
|
||
}
|
||
|
||
static gboolean
|
||
katze_net_icon_status_cb (KatzeNetRequest* request,
|
||
KatzeNetIconPriv* priv)
|
||
{
|
||
switch (request->status)
|
||
{
|
||
case KATZE_NET_VERIFIED:
|
||
if (request->mime_type && strncmp (request->mime_type, "image/", 6))
|
||
{
|
||
katze_net_icon_priv_free (priv);
|
||
return FALSE;
|
||
}
|
||
break;
|
||
case KATZE_NET_MOVED:
|
||
break;
|
||
default:
|
||
katze_net_icon_priv_free (priv);
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static void
|
||
katze_net_icon_transfer_cb (KatzeNetRequest* request,
|
||
KatzeNetIconPriv* priv)
|
||
{
|
||
GdkPixbuf* pixbuf;
|
||
FILE* fp;
|
||
GdkPixbuf* pixbuf_scaled;
|
||
gint icon_width, icon_height;
|
||
size_t ret;
|
||
GtkSettings* settings;
|
||
|
||
if (request->status == KATZE_NET_MOVED)
|
||
return;
|
||
|
||
pixbuf = NULL;
|
||
if (request->data)
|
||
{
|
||
if ((fp = fopen (priv->icon_file, "wb")))
|
||
{
|
||
ret = fwrite (request->data, 1, request->length, fp);
|
||
fclose (fp);
|
||
if ((ret - request->length) != 0)
|
||
{
|
||
g_warning ("Error writing to file %s "
|
||
"in katze_net_icon_transfer_cb()", priv->icon_file);
|
||
}
|
||
pixbuf = gdk_pixbuf_new_from_file (priv->icon_file, NULL);
|
||
}
|
||
else
|
||
pixbuf = katze_pixbuf_new_from_buffer ((guchar*)request->data,
|
||
request->length, request->mime_type, NULL);
|
||
if (pixbuf)
|
||
g_object_ref (pixbuf);
|
||
g_hash_table_insert (priv->view->memory,
|
||
g_strdup (priv->icon_file), pixbuf);
|
||
}
|
||
|
||
if (!pixbuf)
|
||
{
|
||
midori_view_icon_cb (NULL, priv->view);
|
||
katze_net_icon_priv_free (priv);
|
||
return;
|
||
}
|
||
|
||
settings = gtk_widget_get_settings (priv->view->web_view);
|
||
gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU,
|
||
&icon_width, &icon_height);
|
||
pixbuf_scaled = gdk_pixbuf_scale_simple (pixbuf, icon_width, icon_height,
|
||
GDK_INTERP_BILINEAR);
|
||
g_object_unref (pixbuf);
|
||
|
||
katze_assign (priv->view->icon_uri, g_strdup (priv->icon_uri));
|
||
midori_view_icon_cb (pixbuf_scaled, priv->view);
|
||
katze_net_icon_priv_free (priv);
|
||
}
|
||
|
||
static void
|
||
_midori_web_view_load_icon (MidoriView* view)
|
||
{
|
||
GdkPixbuf* pixbuf;
|
||
KatzeNetIconPriv* priv;
|
||
gchar* icon_uri;
|
||
gchar* icon_file;
|
||
gint icon_width, icon_height;
|
||
GdkPixbuf* pixbuf_scaled;
|
||
GtkSettings* settings;
|
||
|
||
pixbuf = NULL;
|
||
icon_uri = g_strdup (view->icon_uri);
|
||
|
||
if ((icon_uri && g_str_has_prefix (icon_uri, "http"))
|
||
|| (view->uri && g_str_has_prefix (view->uri, "http")))
|
||
{
|
||
if (!icon_uri)
|
||
{
|
||
guint i = 8;
|
||
while (view->uri[i] != '\0' && view->uri[i] != '/')
|
||
i++;
|
||
if (view->uri[i] == '/')
|
||
{
|
||
gchar* path = g_strndup (view->uri, i);
|
||
icon_uri = g_strdup_printf ("%s/favicon.ico", path);
|
||
g_free (path);
|
||
}
|
||
else
|
||
icon_uri = g_strdup_printf ("%s/favicon.ico", view->uri);
|
||
}
|
||
|
||
icon_file = katze_net_get_cached_path (NULL, icon_uri, "icons");
|
||
if (g_hash_table_lookup_extended (view->memory,
|
||
icon_file, NULL, (gpointer)&pixbuf))
|
||
{
|
||
g_free (icon_file);
|
||
if (pixbuf)
|
||
{
|
||
g_object_ref (pixbuf);
|
||
katze_assign (view->icon_uri, icon_uri);
|
||
}
|
||
}
|
||
else if ((pixbuf = gdk_pixbuf_new_from_file (icon_file, NULL)))
|
||
{
|
||
g_free (icon_file);
|
||
katze_assign (view->icon_uri, icon_uri);
|
||
}
|
||
else if (!view->special)
|
||
{
|
||
priv = g_slice_new (KatzeNetIconPriv);
|
||
priv->icon_file = icon_file;
|
||
priv->icon_uri = icon_uri;
|
||
priv->view = view;
|
||
|
||
katze_net_load_uri (NULL, icon_uri,
|
||
(KatzeNetStatusCb)katze_net_icon_status_cb,
|
||
(KatzeNetTransferCb)katze_net_icon_transfer_cb, priv);
|
||
}
|
||
}
|
||
|
||
if (pixbuf)
|
||
{
|
||
settings = gtk_widget_get_settings (view->web_view);
|
||
gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU,
|
||
&icon_width, &icon_height);
|
||
pixbuf_scaled = gdk_pixbuf_scale_simple (pixbuf, icon_width,
|
||
icon_height, GDK_INTERP_BILINEAR);
|
||
g_object_unref (pixbuf);
|
||
pixbuf = pixbuf_scaled;
|
||
}
|
||
|
||
midori_view_update_icon (view, pixbuf);
|
||
}
|
||
|
||
static void
|
||
midori_view_update_load_status (MidoriView* view,
|
||
MidoriLoadStatus load_status)
|
||
{
|
||
if (view->load_status == load_status)
|
||
return;
|
||
|
||
if (load_status == MIDORI_LOAD_FINISHED)
|
||
view->special = FALSE;
|
||
|
||
view->load_status = load_status;
|
||
g_object_notify (G_OBJECT (view), "load-status");
|
||
|
||
if (view->tab_icon)
|
||
katze_throbber_set_animated (KATZE_THROBBER (view->tab_icon),
|
||
view->load_status != MIDORI_LOAD_FINISHED);
|
||
}
|
||
|
||
static gboolean
|
||
midori_view_web_view_navigation_decision_cb (WebKitWebView* web_view,
|
||
WebKitWebFrame* web_frame,
|
||
WebKitNetworkRequest* request,
|
||
WebKitWebNavigationAction* action,
|
||
WebKitWebPolicyDecision* decision,
|
||
MidoriView* view)
|
||
{
|
||
JSContextRef js_context;
|
||
gchar* result;
|
||
const gchar* uri = webkit_network_request_get_uri (request);
|
||
if (g_str_has_prefix (uri, "mailto:") || sokoke_external_uri (uri))
|
||
{
|
||
if (sokoke_show_uri (gtk_widget_get_screen (GTK_WIDGET (web_view)),
|
||
uri, GDK_CURRENT_TIME, NULL))
|
||
{
|
||
webkit_web_policy_decision_ignore (decision);
|
||
return TRUE;
|
||
}
|
||
}
|
||
view->special = FALSE;
|
||
|
||
/* Remove link labels */
|
||
js_context = webkit_web_frame_get_global_context (web_frame);
|
||
result = sokoke_js_script_eval (js_context,
|
||
"(function (links) {"
|
||
"if (links != undefined && links.length > 0) {"
|
||
" for (var i = links.length - 1; i >= 0; i--) {"
|
||
" var parent = links[i].parentNode;"
|
||
" parent.removeChild(links[i]); } } }) ("
|
||
"document.getElementsByClassName ('midoriHKD87346'));",
|
||
NULL);
|
||
g_free (result);
|
||
result = sokoke_js_script_eval (js_context,
|
||
"(function (links) {"
|
||
"if (links != undefined && links.length > 0) {"
|
||
" for (var i = links.length - 1; i >= 0; i--) {"
|
||
" var parent = links[i].parentNode;"
|
||
" parent.removeChild(links[i]); } } }) ("
|
||
"document.getElementsByClassName ('midori_access_key_fc04de'));",
|
||
NULL);
|
||
g_free (result);
|
||
view->find_links = -1;
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
static void
|
||
webkit_web_view_load_started_cb (WebKitWebView* web_view,
|
||
WebKitWebFrame* web_frame,
|
||
MidoriView* view)
|
||
{
|
||
g_object_freeze_notify (G_OBJECT (view));
|
||
|
||
midori_view_update_load_status (view, MIDORI_LOAD_PROVISIONAL);
|
||
view->progress = 0.0;
|
||
g_object_notify (G_OBJECT (view), "progress");
|
||
|
||
g_object_thaw_notify (G_OBJECT (view));
|
||
}
|
||
|
||
static void
|
||
webkit_web_view_load_committed_cb (WebKitWebView* web_view,
|
||
WebKitWebFrame* web_frame,
|
||
MidoriView* view)
|
||
{
|
||
const gchar* uri;
|
||
GList* children;
|
||
|
||
g_object_freeze_notify (G_OBJECT (view));
|
||
|
||
uri = webkit_web_frame_get_uri (web_frame);
|
||
g_return_if_fail (uri != NULL);
|
||
katze_assign (view->icon_uri, NULL);
|
||
|
||
children = gtk_container_get_children (GTK_CONTAINER (view));
|
||
for (; children; children = g_list_next (children))
|
||
if (g_object_get_data (G_OBJECT (children->data), "midori-infobar-cb"))
|
||
gtk_widget_destroy (children->data);
|
||
view->alerts = 0;
|
||
|
||
if (g_strcmp0 (uri, katze_item_get_uri (view->item)))
|
||
{
|
||
katze_assign (view->uri, sokoke_format_uri_for_display (uri));
|
||
katze_item_set_uri (view->item, uri);
|
||
}
|
||
|
||
katze_item_set_added (view->item, time (NULL));
|
||
katze_item_set_meta_integer (view->item, "history-step", -1);
|
||
|
||
g_object_notify (G_OBJECT (view), "uri");
|
||
g_object_set (view, "title", NULL, NULL);
|
||
|
||
midori_view_update_icon (view, NULL);
|
||
|
||
if (!strncmp (uri, "https", 5))
|
||
{
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 14) && defined (HAVE_LIBSOUP_2_29_91)
|
||
WebKitWebDataSource *source;
|
||
WebKitNetworkRequest *request;
|
||
SoupMessage *message;
|
||
|
||
source = webkit_web_frame_get_data_source (web_frame);
|
||
request = webkit_web_data_source_get_request (source);
|
||
message = webkit_network_request_get_message (request);
|
||
|
||
if (message
|
||
&& soup_message_get_flags (message) & SOUP_MESSAGE_CERTIFICATE_TRUSTED)
|
||
view->security = MIDORI_SECURITY_TRUSTED;
|
||
else
|
||
#endif
|
||
view->security = MIDORI_SECURITY_UNKNOWN;
|
||
}
|
||
else
|
||
view->security = MIDORI_SECURITY_NONE;
|
||
g_object_notify (G_OBJECT (view), "security");
|
||
|
||
view->find_links = -1;
|
||
midori_view_update_load_status (view, MIDORI_LOAD_COMMITTED);
|
||
|
||
g_object_thaw_notify (G_OBJECT (view));
|
||
|
||
}
|
||
|
||
static void
|
||
webkit_web_view_progress_changed_cb (WebKitWebView* web_view,
|
||
gint progress,
|
||
MidoriView* view)
|
||
{
|
||
view->progress = progress ? progress / 100.0 : 0.0;
|
||
g_object_notify (G_OBJECT (view), "progress");
|
||
}
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 14)
|
||
static void
|
||
midori_view_web_view_resource_request_cb (WebKitWebView* web_view,
|
||
WebKitWebFrame* web_frame,
|
||
WebKitWebResource* web_resource,
|
||
WebKitNetworkRequest* request,
|
||
WebKitNetworkResponse* response,
|
||
MidoriView* view)
|
||
{
|
||
const gchar* uri = webkit_network_request_get_uri (request);
|
||
|
||
/* Only apply custom URIs to special pages for security purposes */
|
||
if (!view->special)
|
||
return;
|
||
|
||
if (g_str_has_prefix (uri, "res://"))
|
||
{
|
||
gchar* filename = g_build_filename ("midori/res", &uri[5], NULL);
|
||
gchar* filepath = sokoke_find_data_filename (filename);
|
||
gchar* file_uri;
|
||
|
||
g_free (filename);
|
||
file_uri = g_filename_to_uri (filepath, NULL, NULL);
|
||
g_free (filepath);
|
||
webkit_network_request_set_uri (request, file_uri);
|
||
g_free (file_uri);
|
||
}
|
||
else if (g_str_has_prefix (uri, "thumb://"))
|
||
{
|
||
gchar* file_path = g_build_filename (g_get_user_cache_dir (), "midori", "thumbnails",
|
||
g_strdup (uri + 8), NULL);
|
||
gchar* file_uri = g_filename_to_uri (file_path, NULL, NULL);
|
||
webkit_network_request_set_uri (request, file_uri);
|
||
g_free (file_uri);
|
||
g_free (file_path);
|
||
}
|
||
else if (g_str_has_prefix (uri, "stock://"))
|
||
{
|
||
GdkPixbuf* pixbuf;
|
||
const gchar* icon_name = &uri[8] ? &uri[8] : "";
|
||
gint icon_size = GTK_ICON_SIZE_MENU;
|
||
GdkScreen* screen = gtk_widget_get_screen (GTK_WIDGET (view));
|
||
GtkIconTheme* icon_theme = gtk_icon_theme_get_for_screen (screen);
|
||
gint real_icon_size;
|
||
GtkIconInfo* icon_info;
|
||
const gchar* icon_filename;
|
||
|
||
if (g_ascii_isalpha (icon_name[0]))
|
||
icon_size = strstr (icon_name, "dialog") ?
|
||
GTK_ICON_SIZE_DIALOG : GTK_ICON_SIZE_BUTTON;
|
||
else if (g_ascii_isdigit (icon_name[0]))
|
||
{
|
||
guint i = 0;
|
||
while (icon_name[i])
|
||
if (icon_name[i++] == '/')
|
||
{
|
||
gchar* size = g_strndup (icon_name, i - 1);
|
||
icon_size = atoi (size);
|
||
/* Compatibility: map pixel to symbolic size */
|
||
if (icon_size == 16)
|
||
icon_size = GTK_ICON_SIZE_MENU;
|
||
g_free (size);
|
||
icon_name = &icon_name[i];
|
||
}
|
||
}
|
||
|
||
/* If available, load SVG icon as SVG markup */
|
||
icon_size = gtk_icon_size_lookup_for_settings (
|
||
gtk_widget_get_settings (GTK_WIDGET (view)),
|
||
icon_size, &real_icon_size, &real_icon_size);
|
||
icon_info = gtk_icon_theme_lookup_icon (icon_theme, icon_name,
|
||
real_icon_size, GTK_ICON_LOOKUP_FORCE_SVG);
|
||
icon_filename = icon_info ? gtk_icon_info_get_filename (icon_info) : NULL;
|
||
if (icon_filename && g_str_has_suffix (icon_filename, ".svg"))
|
||
{
|
||
gchar* buffer;
|
||
gsize buffer_size;
|
||
if (g_file_get_contents (icon_filename, &buffer, &buffer_size, NULL))
|
||
{
|
||
gchar* encoded = g_base64_encode ((guchar*)buffer, buffer_size);
|
||
gchar* data_uri = g_strconcat ("data:image/svg+xml;base64,", encoded, NULL);
|
||
g_free (buffer);
|
||
g_free (encoded);
|
||
webkit_network_request_set_uri (request, data_uri);
|
||
g_free (data_uri);
|
||
return;
|
||
}
|
||
}
|
||
|
||
/* Render icon as a PNG at the desired size */
|
||
pixbuf = gtk_widget_render_icon (GTK_WIDGET (view), icon_name, icon_size, NULL);
|
||
if (!pixbuf)
|
||
pixbuf = gtk_widget_render_icon (GTK_WIDGET (view),
|
||
GTK_STOCK_MISSING_IMAGE, icon_size, NULL);
|
||
if (pixbuf)
|
||
{
|
||
gboolean success;
|
||
gchar* buffer;
|
||
gsize buffer_size;
|
||
gchar* encoded;
|
||
gchar* data_uri;
|
||
|
||
success = gdk_pixbuf_save_to_buffer (pixbuf, &buffer, &buffer_size, "png", NULL, NULL);
|
||
g_object_unref (pixbuf);
|
||
if (!success)
|
||
return;
|
||
|
||
encoded = g_base64_encode ((guchar*)buffer, buffer_size);
|
||
g_free (buffer);
|
||
data_uri = g_strconcat ("data:image/png;base64,", encoded, NULL);
|
||
g_free (encoded);
|
||
webkit_network_request_set_uri (request, data_uri);
|
||
g_free (data_uri);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
#define HAVE_GTK_INFO_BAR GTK_CHECK_VERSION (2, 18, 0)
|
||
|
||
#if HAVE_GTK_INFO_BAR
|
||
static void
|
||
midori_view_infobar_response_cb (GtkWidget* infobar,
|
||
gint response,
|
||
gpointer data_object)
|
||
{
|
||
void (*response_cb) (GtkWidget*, gint, gpointer);
|
||
response_cb = g_object_get_data (G_OBJECT (infobar), "midori-infobar-cb");
|
||
response_cb (infobar, response, data_object);
|
||
gtk_widget_destroy (infobar);
|
||
}
|
||
#else
|
||
static void
|
||
midori_view_info_bar_button_cb (GtkWidget* button,
|
||
gpointer data_object)
|
||
{
|
||
GtkWidget* infobar = gtk_widget_get_parent (gtk_widget_get_parent (button));
|
||
gint response = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "midori-infobar-response"));
|
||
void (*response_cb) (GtkWidget*, gint, gpointer);
|
||
response_cb = g_object_get_data (G_OBJECT (infobar), "midori-infobar-cb");
|
||
response_cb (infobar, response, data_object);
|
||
gtk_widget_destroy (infobar);
|
||
}
|
||
#endif
|
||
|
||
/**
|
||
* midori_view_add_info_bar
|
||
* @view: a #MidoriView
|
||
* @message_type: a #GtkMessageType
|
||
* @message: a message string
|
||
* @response_cb: a response callback
|
||
* @user_data: user data passed to the callback
|
||
* @first_button_text: button text or stock ID
|
||
* @...: first response ID, then more text - response ID pairs
|
||
*
|
||
* Adds an infobar (or equivalent) to the view. Activation of a
|
||
* button invokes the specified callback. The infobar is
|
||
* automatically destroyed if the location changes or reloads.
|
||
*
|
||
* Return value: an infobar widget
|
||
*
|
||
* Since: 0.2.9
|
||
**/
|
||
GtkWidget*
|
||
midori_view_add_info_bar (MidoriView* view,
|
||
GtkMessageType message_type,
|
||
const gchar* message,
|
||
GCallback response_cb,
|
||
gpointer data_object,
|
||
const gchar* first_button_text,
|
||
...)
|
||
{
|
||
GtkWidget* infobar;
|
||
GtkWidget* action_area;
|
||
GtkWidget* content_area;
|
||
va_list args;
|
||
const gchar* button_text;
|
||
|
||
g_return_val_if_fail (message != NULL, NULL);
|
||
g_return_val_if_fail (response_cb != NULL, NULL);
|
||
|
||
va_start (args, first_button_text);
|
||
|
||
#if HAVE_GTK_INFO_BAR
|
||
infobar = gtk_info_bar_new ();
|
||
for (button_text = first_button_text; button_text;
|
||
button_text = va_arg (args, const gchar*))
|
||
{
|
||
gint response_id = va_arg (args, gint);
|
||
gtk_info_bar_add_button (GTK_INFO_BAR (infobar),
|
||
button_text, response_id);
|
||
}
|
||
gtk_info_bar_set_message_type (GTK_INFO_BAR (infobar), message_type);
|
||
content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (infobar));
|
||
action_area = gtk_info_bar_get_action_area (GTK_INFO_BAR (infobar));
|
||
gtk_orientable_set_orientation (GTK_ORIENTABLE (action_area),
|
||
GTK_ORIENTATION_HORIZONTAL);
|
||
g_signal_connect (infobar, "response",
|
||
G_CALLBACK (midori_view_infobar_response_cb), data_object);
|
||
#else
|
||
infobar = gtk_hbox_new (FALSE, 0);
|
||
gtk_container_set_border_width (GTK_CONTAINER (infobar), 4);
|
||
|
||
content_area = gtk_hbox_new (FALSE, 0);
|
||
gtk_box_pack_start (GTK_BOX (infobar), content_area, TRUE, TRUE, 0);
|
||
action_area = gtk_hbutton_box_new ();
|
||
for (button_text = first_button_text; button_text;
|
||
button_text = va_arg (args, const gchar*))
|
||
{
|
||
gint response_id = va_arg (args, gint);
|
||
GtkWidget* button = gtk_button_new_with_mnemonic (button_text);
|
||
g_object_set_data (G_OBJECT (button), "midori-infobar-response",
|
||
GINT_TO_POINTER (response_id));
|
||
g_signal_connect (button, "clicked",
|
||
G_CALLBACK (midori_view_info_bar_button_cb), data_object);
|
||
gtk_box_pack_start (GTK_BOX (action_area), button, FALSE, FALSE, 0);
|
||
if (response_id == GTK_RESPONSE_HELP)
|
||
gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (action_area),
|
||
button, TRUE);
|
||
}
|
||
gtk_box_pack_start (GTK_BOX (infobar), action_area, FALSE, FALSE, 0);
|
||
#endif
|
||
|
||
va_end (args);
|
||
gtk_container_add (GTK_CONTAINER (content_area), gtk_label_new (message));
|
||
gtk_widget_show_all (infobar);
|
||
gtk_box_pack_start (GTK_BOX (view), infobar, FALSE, FALSE, 0);
|
||
gtk_box_reorder_child (GTK_BOX (view), infobar, 0);
|
||
g_object_set_data (G_OBJECT (infobar), "midori-infobar-cb", response_cb);
|
||
return infobar;
|
||
}
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 14)
|
||
static void
|
||
midori_view_database_response_cb (GtkWidget* infobar,
|
||
gint response,
|
||
WebKitWebDatabase* database)
|
||
{
|
||
if (response != GTK_RESPONSE_ACCEPT)
|
||
{
|
||
WebKitSecurityOrigin* origin = webkit_web_database_get_security_origin (database);
|
||
webkit_security_origin_set_web_database_quota (origin, 0);
|
||
webkit_web_database_remove (database);
|
||
}
|
||
/* TODO: Remember the decision */
|
||
}
|
||
|
||
static void
|
||
midori_view_web_view_database_quota_exceeded_cb (WebKitWebView* web_view,
|
||
WebKitWebFrame* web_frame,
|
||
WebKitWebDatabase* database,
|
||
MidoriView* view)
|
||
{
|
||
const gchar* uri = webkit_web_frame_get_uri (web_frame);
|
||
const gchar* hostname = sokoke_hostname_from_uri (uri, NULL);
|
||
gchar* message = g_strdup_printf (_("%s wants to save an HTML5 database."),
|
||
hostname && *hostname ? hostname : uri);
|
||
midori_view_add_info_bar (view, GTK_MESSAGE_QUESTION, message,
|
||
G_CALLBACK (midori_view_database_response_cb), database,
|
||
_("_Deny"), GTK_RESPONSE_REJECT, _("_Allow"), GTK_RESPONSE_ACCEPT,
|
||
NULL);
|
||
g_free (message);
|
||
}
|
||
#endif
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 23)
|
||
static void
|
||
midori_view_location_response_cb (GtkWidget* infobar,
|
||
gint response,
|
||
WebKitGeolocationPolicyDecision* decision)
|
||
{
|
||
if (response == GTK_RESPONSE_ACCEPT)
|
||
webkit_geolocation_policy_allow (decision);
|
||
else
|
||
webkit_geolocation_policy_deny (decision);
|
||
}
|
||
|
||
static gboolean
|
||
midori_view_web_view_geolocation_decision_cb (WebKitWebView* web_view,
|
||
WebKitWebFrame* web_frame,
|
||
WebKitGeolocationPolicyDecision* decision,
|
||
MidoriView* view)
|
||
{
|
||
const gchar* uri = webkit_web_frame_get_uri (web_frame);
|
||
const gchar* hostname = sokoke_hostname_from_uri (uri, NULL);
|
||
gchar* message = g_strdup_printf (_("%s wants to know your location."),
|
||
hostname && *hostname ? hostname : uri);
|
||
midori_view_add_info_bar (view, GTK_MESSAGE_QUESTION,
|
||
message, G_CALLBACK (midori_view_location_response_cb), decision,
|
||
_("_Deny"), GTK_RESPONSE_REJECT, _("_Allow"), GTK_RESPONSE_ACCEPT,
|
||
NULL);
|
||
g_free (message);
|
||
return TRUE;
|
||
}
|
||
#endif
|
||
|
||
static void
|
||
midori_view_load_alternate_string (MidoriView* view,
|
||
const gchar* data,
|
||
const gchar* res_root,
|
||
const gchar* uri,
|
||
WebKitWebFrame* web_frame)
|
||
{
|
||
WebKitWebView* web_view = WEBKIT_WEB_VIEW (view->web_view);
|
||
if (!web_frame)
|
||
web_frame = webkit_web_view_get_main_frame (web_view);
|
||
view->special = TRUE;
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 14)
|
||
webkit_web_frame_load_alternate_string (
|
||
web_frame, data, uri, uri);
|
||
#elif WEBKIT_CHECK_VERSION (1, 1, 6)
|
||
webkit_web_frame_load_alternate_string (
|
||
web_frame, data, res_root, uri);
|
||
#else
|
||
webkit_web_view_load_html_string (
|
||
web_view, data, res_root);
|
||
#endif
|
||
}
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 6)
|
||
static gboolean
|
||
midori_view_display_error (MidoriView* view,
|
||
const gchar* uri,
|
||
const gchar* title,
|
||
const gchar* message,
|
||
const gchar* description,
|
||
const gchar* try_again,
|
||
WebKitWebFrame* web_frame)
|
||
{
|
||
gchar* template_file = g_build_filename ("midori", "res", "error.html", NULL);
|
||
gchar* path = sokoke_find_data_filename (template_file);
|
||
gchar* template;
|
||
|
||
g_free (template_file);
|
||
if (g_file_get_contents (path, &template, NULL, NULL))
|
||
{
|
||
#if !WEBKIT_CHECK_VERSION (1, 1, 14)
|
||
SoupServer* res_server;
|
||
guint port;
|
||
#endif
|
||
gchar* res_root;
|
||
gchar* stock_root;
|
||
gchar* title_escaped;
|
||
gchar* result;
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 14)
|
||
res_root = g_strdup ("res:/");
|
||
stock_root = g_strdup ("stock:/");
|
||
#else
|
||
res_server = sokoke_get_res_server ();
|
||
port = soup_server_get_port (res_server);
|
||
res_root = g_strdup_printf ("http://localhost:%d/res", port);
|
||
stock_root = g_strdup_printf ("http://localhost:%d/stock", port);
|
||
#endif
|
||
|
||
title_escaped = g_markup_escape_text (title, -1);
|
||
result = sokoke_replace_variables (template,
|
||
"{title}", title_escaped,
|
||
"{message}", message,
|
||
"{description}", description,
|
||
"{tryagain}", try_again,
|
||
"{res}", res_root,
|
||
"{stock}", stock_root,
|
||
NULL);
|
||
g_free (title_escaped);
|
||
g_free (template);
|
||
|
||
midori_view_load_alternate_string (view,
|
||
result, res_root, uri, web_frame);
|
||
|
||
g_free (res_root);
|
||
g_free (stock_root);
|
||
g_free (result);
|
||
g_free (path);
|
||
|
||
return TRUE;
|
||
}
|
||
g_free (path);
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
static gboolean
|
||
webkit_web_view_load_error_cb (WebKitWebView* web_view,
|
||
WebKitWebFrame* web_frame,
|
||
const gchar* uri,
|
||
GError* error,
|
||
MidoriView* view)
|
||
{
|
||
gchar* title;
|
||
gchar* message;
|
||
gboolean result;
|
||
|
||
switch (error->code)
|
||
{
|
||
case WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD:
|
||
/* A plugin will take over. That's expected, it's not fatal. */
|
||
return FALSE;
|
||
}
|
||
|
||
title = g_strdup_printf (_("Error - %s"), uri);
|
||
message = g_strdup_printf (_("The page '%s' couldn't be loaded."), uri);
|
||
result = midori_view_display_error (view, uri, title,
|
||
message, error->message, _("Try again"), web_frame);
|
||
g_free (message);
|
||
g_free (title);
|
||
return result;
|
||
}
|
||
#else
|
||
static void
|
||
webkit_web_frame_load_done_cb (WebKitWebFrame* web_frame,
|
||
gboolean success,
|
||
MidoriView* view)
|
||
{
|
||
gchar* title;
|
||
gchar* data;
|
||
gchar* logo_path;
|
||
gchar* logo_uri;
|
||
|
||
if (!success)
|
||
{
|
||
/* i18n: The title of the 404 - Not found error page */
|
||
title = g_strdup_printf (_("Not found - %s"), view->uri);
|
||
katze_assign (view->title, title);
|
||
logo_path = sokoke_find_data_filename ("midori/logo-shade.png");
|
||
logo_uri = g_filename_to_uri (logo_path, NULL, NULL);
|
||
g_free (logo_path);
|
||
data = g_strdup_printf (
|
||
"<html><head><title>%s</title></head>"
|
||
"<body><h1>%s</h1>"
|
||
"<img src=\"%s\" "
|
||
"style=\"position: absolute; right: 15px; bottom: 15px; z-index: -9;\">"
|
||
"<p />The page you were opening doesn't exist."
|
||
"<p />Try to <a href=\"%s\">load the page again</a>, "
|
||
"or move on to another page."
|
||
"</body></html>",
|
||
title, title, logo_uri, view->uri);
|
||
webkit_web_view_load_html_string (
|
||
WEBKIT_WEB_VIEW (view->web_view), data, view->uri);
|
||
g_free (title);
|
||
g_free (data);
|
||
g_free (logo_uri);
|
||
}
|
||
|
||
midori_view_update_load_status (view, MIDORI_LOAD_FINISHED);
|
||
}
|
||
#endif
|
||
|
||
static void
|
||
midori_view_apply_scroll_position (MidoriView* view)
|
||
{
|
||
if (view->scrollh > -2)
|
||
{
|
||
if (view->scrollh > 0)
|
||
{
|
||
GtkScrolledWindow* scrolled = GTK_SCROLLED_WINDOW (view->scrolled_window);
|
||
GtkAdjustment* adjustment = gtk_scrolled_window_get_hadjustment (scrolled);
|
||
gtk_adjustment_set_value (adjustment, view->scrollh);
|
||
}
|
||
view->scrollh = -3;
|
||
}
|
||
if (view->scrollv > -2)
|
||
{
|
||
if (view->scrollv > 0)
|
||
{
|
||
GtkScrolledWindow* scrolled = GTK_SCROLLED_WINDOW (view->scrolled_window);
|
||
GtkAdjustment* adjustment = gtk_scrolled_window_get_vadjustment (scrolled);
|
||
gtk_adjustment_set_value (adjustment, view->scrollv);
|
||
}
|
||
view->scrollv = -3;
|
||
}
|
||
}
|
||
|
||
static void
|
||
webkit_web_view_load_finished_cb (WebKitWebView* web_view,
|
||
WebKitWebFrame* web_frame,
|
||
MidoriView* view)
|
||
{
|
||
g_object_freeze_notify (G_OBJECT (view));
|
||
|
||
/* TODO: Find a better condition than a finished load.
|
||
Apparently WEBKIT_LOAD_FIRST_VISUALLY_NON_EMPTY_LAYOUT is too early. */
|
||
midori_view_apply_scroll_position (view);
|
||
|
||
view->progress = 1.0;
|
||
g_object_notify (G_OBJECT (view), "progress");
|
||
midori_view_update_load_status (view, MIDORI_LOAD_FINISHED);
|
||
|
||
if (1)
|
||
{
|
||
JSContextRef js_context = webkit_web_frame_get_global_context (web_frame);
|
||
/* This snippet joins the available news feeds into a string like this:
|
||
URI1|title1,URI2|title2
|
||
FIXME: Ensure separators contained in the string can't break it */
|
||
gchar* value = sokoke_js_script_eval (js_context,
|
||
"(function (l) { var f = new Array (); for (i in l) "
|
||
"{ var t = l[i].type; var r = l[i].rel; "
|
||
"if (t && (t.indexOf ('rss') != -1 || t.indexOf ('atom') != -1)) "
|
||
"f.push (l[i].href + '|' + l[i].title);"
|
||
#if !WEBKIT_CHECK_VERSION (1, 1, 18)
|
||
"else if (r && r.indexOf ('icon') != -1) f.push (l[i].href); "
|
||
#endif
|
||
"} return f; })("
|
||
"document.getElementsByTagName ('link'));", NULL);
|
||
gchar** items = g_strsplit (value, ",", 0);
|
||
guint i = 0;
|
||
gchar* default_uri = NULL;
|
||
|
||
katze_array_clear (view->news_feeds);
|
||
if (items != NULL)
|
||
while (items[i] != NULL)
|
||
{
|
||
gchar** parts = g_strsplit (items[i], "|", 2);
|
||
if (parts == NULL)
|
||
;
|
||
else if (*parts && parts[1])
|
||
{
|
||
KatzeItem* item = g_object_new (KATZE_TYPE_ITEM,
|
||
"uri", parts[0], "name", parts[1], NULL);
|
||
katze_array_add_item (view->news_feeds, item);
|
||
g_object_unref (item);
|
||
if (!default_uri)
|
||
default_uri = g_strdup (parts[0]);
|
||
}
|
||
#if !WEBKIT_CHECK_VERSION (1, 1, 18)
|
||
else
|
||
katze_assign (view->icon_uri, g_strdup (*parts));
|
||
#endif
|
||
|
||
g_strfreev (parts);
|
||
i++;
|
||
}
|
||
g_strfreev (items);
|
||
g_object_set_data_full (G_OBJECT (view), "news-feeds", default_uri, g_free);
|
||
g_free (value);
|
||
/* Ensure load-status is notified again, whether it changed or not */
|
||
g_object_notify (G_OBJECT (view), "load-status");
|
||
}
|
||
|
||
_midori_web_view_load_icon (view);
|
||
|
||
g_object_thaw_notify (G_OBJECT (view));
|
||
}
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 18)
|
||
static void
|
||
midori_web_view_notify_icon_uri_cb (WebKitWebView* web_view,
|
||
GParamSpec* pspec,
|
||
MidoriView* view)
|
||
{
|
||
const gchar* icon_uri = webkit_web_view_get_icon_uri (web_view);
|
||
katze_assign (view->icon_uri, g_strdup (icon_uri));
|
||
_midori_web_view_load_icon (view);
|
||
}
|
||
#endif
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 4)
|
||
static void
|
||
webkit_web_view_notify_uri_cb (WebKitWebView* web_view,
|
||
GParamSpec* pspec,
|
||
MidoriView* view)
|
||
{
|
||
katze_assign (view->uri, g_strdup (webkit_web_view_get_uri (web_view)));
|
||
g_object_notify (G_OBJECT (view), "uri");
|
||
}
|
||
|
||
static void
|
||
webkit_web_view_notify_title_cb (WebKitWebView* web_view,
|
||
GParamSpec* pspec,
|
||
MidoriView* view)
|
||
{
|
||
const gchar* title = webkit_web_view_get_title (web_view);
|
||
midori_view_set_title (view, title);
|
||
g_object_notify (G_OBJECT (view), "title");
|
||
}
|
||
#else
|
||
static void
|
||
webkit_web_view_title_changed_cb (WebKitWebView* web_view,
|
||
WebKitWebFrame* web_frame,
|
||
const gchar* title,
|
||
MidoriView* view)
|
||
{
|
||
g_object_set (view, "title", title, NULL);
|
||
}
|
||
#endif
|
||
|
||
static void
|
||
webkit_web_view_statusbar_text_changed_cb (WebKitWebView* web_view,
|
||
const gchar* text,
|
||
MidoriView* view)
|
||
{
|
||
g_object_set (G_OBJECT (view), "statusbar-text", text, NULL);
|
||
}
|
||
|
||
static gboolean
|
||
midori_view_web_view_leave_notify_event_cb (WebKitWebView* web_view,
|
||
GdkEventCrossing* event,
|
||
MidoriView* view)
|
||
{
|
||
g_object_set (G_OBJECT (view), "statusbar-text", NULL, NULL);
|
||
return FALSE;
|
||
}
|
||
|
||
static void
|
||
webkit_web_view_hovering_over_link_cb (WebKitWebView* web_view,
|
||
const gchar* tooltip,
|
||
const gchar* link_uri,
|
||
MidoriView* view)
|
||
{
|
||
#if !(WEBKIT_CHECK_VERSION (1, 3, 1) && defined (HAVE_LIBSOUP_2_29_3))
|
||
sokoke_prefetch_uri (view->settings, link_uri, NULL, NULL);
|
||
#endif
|
||
|
||
katze_assign (view->link_uri, g_strdup (link_uri));
|
||
if (link_uri && g_str_has_prefix (link_uri, "mailto:"))
|
||
{
|
||
gchar* text = g_strdup_printf (_("Send a message to %s"), &link_uri[7]);
|
||
g_object_set (view, "statusbar-text", text, NULL);
|
||
g_free (text);
|
||
}
|
||
else
|
||
g_object_set (view, "statusbar-text", link_uri, NULL);
|
||
}
|
||
|
||
static void
|
||
midori_view_ensure_link_uri (MidoriView* view,
|
||
gint *x,
|
||
gint *y,
|
||
GdkEventButton* event)
|
||
{
|
||
g_return_if_fail (MIDORI_IS_VIEW (view));
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 15)
|
||
if (view->web_view && gtk_widget_get_window (view->web_view))
|
||
{
|
||
GdkEventButton ev;
|
||
|
||
if (!event) {
|
||
gint ex, ey;
|
||
event = &ev;
|
||
gdk_window_get_pointer (gtk_widget_get_window (view->web_view), &ex, &ey, NULL);
|
||
event->x = ex;
|
||
event->y = ey;
|
||
}
|
||
|
||
if (x != NULL)
|
||
*x = event->x;
|
||
if (y != NULL)
|
||
*y = event->y;
|
||
|
||
katze_object_assign (view->hit_test,
|
||
g_object_ref (
|
||
webkit_web_view_get_hit_test_result (
|
||
WEBKIT_WEB_VIEW (view->web_view), event)));
|
||
katze_assign (view->link_uri,
|
||
katze_object_get_string (view->hit_test, "link-uri"));
|
||
}
|
||
#endif
|
||
}
|
||
|
||
#define MIDORI_KEYS_MODIFIER_MASK (GDK_SHIFT_MASK | GDK_CONTROL_MASK \
|
||
| GDK_MOD1_MASK | GDK_META_MASK | GDK_SUPER_MASK | GDK_HYPER_MASK )
|
||
|
||
static gboolean
|
||
gtk_widget_button_press_event_cb (WebKitWebView* web_view,
|
||
GdkEventButton* event,
|
||
MidoriView* view)
|
||
{
|
||
GtkClipboard* clipboard;
|
||
gchar* uri;
|
||
gchar* new_uri;
|
||
const gchar* link_uri;
|
||
gboolean background;
|
||
|
||
event->state = event->state & MIDORI_KEYS_MODIFIER_MASK;
|
||
midori_view_ensure_link_uri (view, NULL, NULL, event);
|
||
link_uri = midori_view_get_link_uri (view);
|
||
|
||
switch (event->button)
|
||
{
|
||
case 1:
|
||
if (!link_uri)
|
||
return FALSE;
|
||
if (MIDORI_MOD_NEW_TAB (event->state))
|
||
{
|
||
/* Open link in new tab */
|
||
background = view->open_tabs_in_the_background;
|
||
if (MIDORI_MOD_BACKGROUND (event->state))
|
||
background = !background;
|
||
g_signal_emit (view, signals[NEW_TAB], 0, link_uri, background);
|
||
return TRUE;
|
||
}
|
||
else if (MIDORI_MOD_NEW_WINDOW (event->state))
|
||
{
|
||
/* Open link in new window */
|
||
g_signal_emit (view, signals[NEW_WINDOW], 0, link_uri);
|
||
return TRUE;
|
||
}
|
||
break;
|
||
case 2:
|
||
if (link_uri)
|
||
{
|
||
/* Open link in new tab */
|
||
background = view->open_tabs_in_the_background;
|
||
if (MIDORI_MOD_BACKGROUND (event->state))
|
||
background = !background;
|
||
g_signal_emit (view, signals[NEW_TAB], 0, link_uri, background);
|
||
return TRUE;
|
||
}
|
||
else if (MIDORI_MOD_SCROLL (event->state))
|
||
{
|
||
midori_view_set_zoom_level (MIDORI_VIEW (view), 1.0);
|
||
return FALSE; /* Allow Ctrl + Middle click */
|
||
}
|
||
else if (view->middle_click_opens_selection)
|
||
{
|
||
gboolean is_editable;
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 15)
|
||
WebKitHitTestResult* result;
|
||
WebKitHitTestResultContext context;
|
||
|
||
result = webkit_web_view_get_hit_test_result (web_view, event);
|
||
context = katze_object_get_int (result, "context");
|
||
is_editable = context & WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE;
|
||
g_object_unref (result);
|
||
#else
|
||
is_editable = webkit_web_view_can_paste_clipboard (WEBKIT_WEB_VIEW (view->web_view));
|
||
#endif
|
||
if (is_editable)
|
||
return FALSE;
|
||
|
||
clipboard = gtk_clipboard_get_for_display (
|
||
gtk_widget_get_display (GTK_WIDGET (view)),
|
||
GDK_SELECTION_PRIMARY);
|
||
if ((uri = gtk_clipboard_wait_for_text (clipboard)))
|
||
{
|
||
guint i = 0;
|
||
while (uri[i++] != '\0')
|
||
if (uri[i] == '\n' || uri[i] == '\r')
|
||
uri[i] = ' ';
|
||
g_strstrip (uri);
|
||
|
||
/* Hold Alt to search for the selected word */
|
||
if (event->state & GDK_MOD1_MASK)
|
||
{
|
||
new_uri = sokoke_magic_uri (uri);
|
||
if (!new_uri)
|
||
{
|
||
gchar* search;
|
||
g_object_get (view->settings, "location-entry-search",
|
||
&search, NULL);
|
||
new_uri = sokoke_search_uri (search, uri);
|
||
}
|
||
katze_assign (uri, new_uri);
|
||
}
|
||
else if (!strstr (uri, "://"))
|
||
{
|
||
g_free (uri);
|
||
return FALSE;
|
||
}
|
||
|
||
if (MIDORI_MOD_NEW_TAB (event->state))
|
||
{
|
||
background = view->open_tabs_in_the_background;
|
||
if (MIDORI_MOD_BACKGROUND (event->state))
|
||
background = !background;
|
||
g_signal_emit (view, signals[NEW_TAB], 0, uri, background);
|
||
}
|
||
else
|
||
{
|
||
midori_view_set_uri (MIDORI_VIEW (view), uri);
|
||
gtk_widget_grab_focus (GTK_WIDGET (view));
|
||
}
|
||
g_free (uri);
|
||
return TRUE;
|
||
}
|
||
}
|
||
break;
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 15)
|
||
case 3:
|
||
if (event->state & GDK_CONTROL_MASK)
|
||
{
|
||
/* Ctrl + Right-click suppresses javascript button handling */
|
||
GtkWidget* menu = gtk_menu_new ();
|
||
midori_view_populate_popup (view, menu, TRUE);
|
||
katze_widget_popup (GTK_WIDGET (web_view), GTK_MENU (menu), event,
|
||
KATZE_MENU_POSITION_CURSOR);
|
||
return TRUE;
|
||
}
|
||
break;
|
||
#endif
|
||
case 8:
|
||
midori_view_go_back (view);
|
||
return TRUE;
|
||
case 9:
|
||
midori_view_go_forward (view);
|
||
return TRUE;
|
||
/*
|
||
* On some fancier mice the scroll wheel can be used to scroll horizontally.
|
||
* A middle click usually registers both a middle click (2) and a
|
||
* horizontal scroll (11 or 12).
|
||
* We catch horizontal scrolls and ignore them to prevent middle clicks from
|
||
* accidentally being interpreted as first button clicks.
|
||
*/
|
||
case 11:
|
||
return TRUE;
|
||
case 12:
|
||
return TRUE;
|
||
}
|
||
|
||
/* We propagate the event, since it may otherwise be stuck in WebKit */
|
||
g_signal_emit_by_name (view, "event", event, &background);
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
static gboolean
|
||
gtk_widget_key_press_event_cb (WebKitWebView* web_view,
|
||
GdkEventKey* event,
|
||
MidoriView* view)
|
||
{
|
||
guint character;
|
||
gint digit = g_ascii_digit_value (event->keyval);
|
||
|
||
event->state = event->state & MIDORI_KEYS_MODIFIER_MASK;
|
||
|
||
/* Handle oddities in Russian keyboard layouts */
|
||
if (event->hardware_keycode == ';')
|
||
event->keyval = ',';
|
||
else if (event->hardware_keycode == '<')
|
||
event->keyval = '.';
|
||
|
||
/* Find links by number: . to show links, type number, Return to go */
|
||
if (event->keyval == '.'
|
||
|| (view->find_links > -1
|
||
&& (digit != -1 || event->keyval == GDK_Return || event->keyval == GDK_Escape)))
|
||
{
|
||
WebKitWebFrame* web_frame = webkit_web_view_get_main_frame (web_view);
|
||
JSContextRef js_context = webkit_web_frame_get_global_context (web_frame);
|
||
gchar* result;
|
||
|
||
if (view->find_links == -1)
|
||
{
|
||
result = sokoke_js_script_eval (js_context,
|
||
" var style_func = (function (selector, rule) { "
|
||
" var style = document.createElement ('style');"
|
||
" style.setAttribute ('type', 'text/css');"
|
||
" var heads = document.getElementsByTagName ('head');"
|
||
" heads[0].appendChild (style);"
|
||
" document.styleSheets[0].insertRule (selector + ' ' + rule);"
|
||
" } );"
|
||
" style_func ('.midoriHKD87346', '{ "
|
||
" font-size:small !important; font-weight:bold !important;"
|
||
" z-index:500; border-radius:0.3em; line-height:1 !important;"
|
||
" background: white !important; color: black !important;"
|
||
" border:1px solid gray; padding:0 0.1em !important;"
|
||
" position:absolute; display:inline !important; }');"
|
||
" style_func ('.midori_access_key_fc04de', '{ "
|
||
" font-size:small !important; font-weight:bold !important;"
|
||
" z-index:500; border-radius:0.3em; line-height:1 !important;"
|
||
" background: black !important; color: white !important;"
|
||
" border:1px solid gray; padding:0 0.1em 0.2em 0.1em !important;"
|
||
" position:absolute; display:inline !important; }');"
|
||
" var label_count = 0;"
|
||
" for (i in document.links) {"
|
||
" if (document.links[i].href && document.links[i].insertBefore) {"
|
||
" var child = document.createElement ('span');"
|
||
" if (document.links[i].accessKey && isNaN (document.links[i].accessKey)) {"
|
||
" child.setAttribute ('class', 'midori_access_key_fc04de');"
|
||
" child.appendChild (document.createTextNode (document.links[i].accessKey));"
|
||
" } else {"
|
||
" child.setAttribute ('class', 'midoriHKD87346');"
|
||
" child.appendChild (document.createTextNode (label_count));"
|
||
" label_count++;"
|
||
" }"
|
||
" document.links[i].insertBefore (child); } }",
|
||
NULL);
|
||
view->find_links = 0;
|
||
}
|
||
else if (digit != -1 && event->keyval != GDK_Return && event->keyval != GDK_Escape)
|
||
{
|
||
if (view->find_links > -1)
|
||
view->find_links *= 10;
|
||
view->find_links += digit;
|
||
}
|
||
else if (event->keyval == GDK_Escape)
|
||
{
|
||
view->find_links = 0;
|
||
}
|
||
else if (event->keyval == GDK_Return)
|
||
{
|
||
gchar* script;
|
||
script = g_strdup_printf (
|
||
"var links = document.getElementsByClassName ('midoriHKD87346');"
|
||
"var i = %d; var return_key = %d;"
|
||
"if (return_key) {"
|
||
" if (typeof links[i] != 'undefined')"
|
||
" links[i].parentNode.href; }",
|
||
view->find_links, event->keyval == GDK_Return);
|
||
result = sokoke_js_script_eval (js_context, script, NULL);
|
||
if (result && strstr (result, "://"))
|
||
{
|
||
if (MIDORI_MOD_NEW_TAB (event->state))
|
||
{
|
||
gboolean background = view->open_tabs_in_the_background;
|
||
if (MIDORI_MOD_BACKGROUND (event->state))
|
||
background = !background;
|
||
g_signal_emit (view, signals[NEW_TAB], 0, result, background);
|
||
}
|
||
else
|
||
midori_view_set_uri (view, result);
|
||
}
|
||
g_free (script);
|
||
g_free (result);
|
||
view->find_links = 0;
|
||
}
|
||
else
|
||
{
|
||
result = sokoke_js_script_eval (js_context,
|
||
"var links = document.getElementsByClassName ('midoriHKD87346');"
|
||
"for (var i = links.length - 1; i >= 0; i--) {"
|
||
" var parent = links[i].parentNode;"
|
||
" parent.removeChild(links[i]); }",
|
||
NULL);
|
||
g_free (result);
|
||
result = sokoke_js_script_eval (js_context,
|
||
"var links = document.getElementsByClassName ('midori_access_key_fc04de');"
|
||
"if (links != undefined && links.length > 0) {"
|
||
" for (var i = links.length - 1; i >= 0; i--) {"
|
||
" var parent = links[i].parentNode;"
|
||
" parent.removeChild(links[i]); } }",
|
||
NULL);
|
||
g_free (result);
|
||
view->find_links = -1;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
/* Find inline */
|
||
if (event->keyval == ',' || event->keyval == '/' || event->keyval == GDK_KP_Divide)
|
||
character = '\0';
|
||
else
|
||
return FALSE;
|
||
|
||
/* Skip control characters */
|
||
if (character == (event->keyval | 0x01000000))
|
||
return FALSE;
|
||
|
||
if (!webkit_web_view_can_cut_clipboard (web_view)
|
||
&& !webkit_web_view_can_paste_clipboard (web_view))
|
||
{
|
||
gchar* text = character ? g_strdup_printf ("%c", character) : g_strdup ("");
|
||
g_signal_emit (view, signals[SEARCH_TEXT], 0, TRUE, text);
|
||
g_free (text);
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
static gboolean
|
||
gtk_widget_scroll_event_cb (WebKitWebView* web_view,
|
||
GdkEventScroll* event,
|
||
MidoriView* view)
|
||
{
|
||
event->state = event->state & MIDORI_KEYS_MODIFIER_MASK;
|
||
|
||
if (MIDORI_MOD_SCROLL (event->state))
|
||
{
|
||
if (event->direction == GDK_SCROLL_DOWN)
|
||
midori_view_set_zoom_level (view,
|
||
midori_view_get_zoom_level (view) - 0.25f);
|
||
else if(event->direction == GDK_SCROLL_UP)
|
||
midori_view_set_zoom_level (view,
|
||
midori_view_get_zoom_level (view) + 0.25f);
|
||
return TRUE;
|
||
}
|
||
else
|
||
return FALSE;
|
||
}
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 15)
|
||
static void
|
||
midori_web_view_menu_new_window_activate_cb (GtkWidget* widget,
|
||
MidoriView* view)
|
||
{
|
||
g_signal_emit (view, signals[NEW_WINDOW], 0, view->link_uri);
|
||
}
|
||
|
||
static void
|
||
midori_web_view_menu_web_app_activate_cb (GtkWidget* widget,
|
||
MidoriView* view)
|
||
{
|
||
sokoke_spawn_app (view->link_uri, FALSE);
|
||
}
|
||
|
||
static void
|
||
midori_web_view_menu_link_copy_activate_cb (GtkWidget* widget,
|
||
MidoriView* view)
|
||
{
|
||
if (g_str_has_prefix (view->link_uri, "mailto:"))
|
||
sokoke_widget_copy_clipboard (widget, view->link_uri + 7);
|
||
else
|
||
sokoke_widget_copy_clipboard (widget, view->link_uri);
|
||
}
|
||
|
||
static void
|
||
midori_web_view_menu_save_activate_cb (GtkWidget* widget,
|
||
MidoriView* view)
|
||
{
|
||
WebKitNetworkRequest* request = webkit_network_request_new (view->link_uri);
|
||
WebKitDownload* download = webkit_download_new (request);
|
||
gboolean handled;
|
||
g_object_unref (request);
|
||
g_object_set_data (G_OBJECT (download), "save-as-download", (void*)0xdeadbeef);
|
||
g_signal_emit (view, signals[DOWNLOAD_REQUESTED], 0, download, &handled);
|
||
}
|
||
|
||
static void
|
||
midori_web_view_menu_image_new_tab_activate_cb (GtkWidget* widget,
|
||
MidoriView* view)
|
||
{
|
||
gchar* uri = katze_object_get_string (view->hit_test, "image-uri");
|
||
g_signal_emit (view, signals[NEW_TAB], 0, uri,
|
||
view->open_tabs_in_the_background);
|
||
g_free (uri);
|
||
}
|
||
|
||
static void
|
||
midori_web_view_menu_image_copy_activate_cb (GtkWidget* widget,
|
||
MidoriView* view)
|
||
{
|
||
gchar* uri = katze_object_get_string (view->hit_test, "image-uri");
|
||
sokoke_widget_copy_clipboard (widget, uri);
|
||
g_free (uri);
|
||
}
|
||
|
||
static void
|
||
midori_web_view_menu_image_save_activate_cb (GtkWidget* widget,
|
||
MidoriView* view)
|
||
{
|
||
gchar* uri = katze_object_get_string (view->hit_test, "image-uri");
|
||
WebKitNetworkRequest* request = webkit_network_request_new (uri);
|
||
WebKitDownload* download = webkit_download_new (request);
|
||
gboolean handled;
|
||
g_object_unref (request);
|
||
g_object_set_data (G_OBJECT (download), "save-as-download", (void*)0xdeadbeef);
|
||
g_signal_emit (view, signals[DOWNLOAD_REQUESTED], 0, download, &handled);
|
||
g_free (uri);
|
||
}
|
||
|
||
static void
|
||
midori_web_view_menu_video_copy_activate_cb (GtkWidget* widget,
|
||
MidoriView* view)
|
||
{
|
||
gchar* uri = katze_object_get_string (view->hit_test, "media-uri");
|
||
sokoke_widget_copy_clipboard (widget, uri);
|
||
g_free (uri);
|
||
}
|
||
|
||
static void
|
||
midori_web_view_menu_video_save_activate_cb (GtkWidget* widget,
|
||
MidoriView* view)
|
||
{
|
||
gchar* uri = katze_object_get_string (view->hit_test, "media-uri");
|
||
WebKitNetworkRequest* request = webkit_network_request_new (uri);
|
||
WebKitDownload* download = webkit_download_new (request);
|
||
gboolean handled;
|
||
g_object_unref (request);
|
||
g_object_set_data (G_OBJECT (download), "save-as-download", (void*)0xdeadbeef);
|
||
g_signal_emit (view, signals[DOWNLOAD_REQUESTED], 0, download, &handled);
|
||
g_free (uri);
|
||
}
|
||
#endif
|
||
|
||
static void
|
||
midori_web_view_menu_new_tab_activate_cb (GtkWidget* widget,
|
||
MidoriView* view)
|
||
{
|
||
if (view->link_uri)
|
||
g_signal_emit (view, signals[NEW_TAB], 0, view->link_uri,
|
||
view->open_tabs_in_the_background);
|
||
else
|
||
{
|
||
gchar* data = (gchar*)g_object_get_data (G_OBJECT (widget), "uri");
|
||
if (strchr (data, '@'))
|
||
{
|
||
gchar* uri = g_strconcat ("mailto:", data, NULL);
|
||
sokoke_show_uri (gtk_widget_get_screen (widget),
|
||
uri, GDK_CURRENT_TIME, NULL);
|
||
g_free (uri);
|
||
}
|
||
else
|
||
{
|
||
gchar* uri = sokoke_magic_uri (data);
|
||
if (!uri)
|
||
uri = g_strdup (data);
|
||
g_signal_emit (view, signals[NEW_TAB], 0, uri,
|
||
view->open_tabs_in_the_background);
|
||
g_free (uri);
|
||
}
|
||
}
|
||
}
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 15)
|
||
static void
|
||
midori_web_view_menu_background_tab_activate_cb (GtkWidget* widget,
|
||
MidoriView* view)
|
||
{
|
||
g_signal_emit (view, signals[NEW_TAB], 0, view->link_uri,
|
||
!view->open_tabs_in_the_background);
|
||
}
|
||
#endif
|
||
|
||
static void
|
||
midori_web_view_menu_search_web_activate_cb (GtkWidget* widget,
|
||
MidoriView* view)
|
||
{
|
||
gchar* search;
|
||
gchar* uri;
|
||
|
||
if ((search = g_object_get_data (G_OBJECT (widget), "search")))
|
||
search = g_strdup (search);
|
||
else
|
||
g_object_get (view->settings, "location-entry-search",
|
||
&search, NULL);
|
||
uri = sokoke_search_uri (search, view->selected_text);
|
||
g_free (search);
|
||
|
||
g_signal_emit (view, signals[NEW_TAB], 0, uri,
|
||
view->open_tabs_in_the_background);
|
||
|
||
g_free (uri);
|
||
}
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 15)
|
||
static void
|
||
midori_web_view_menu_copy_activate_cb (GtkWidget* widget,
|
||
MidoriView* view)
|
||
{
|
||
sokoke_widget_copy_clipboard (widget, view->selected_text);
|
||
}
|
||
#endif
|
||
|
||
#if !WEBKIT_CHECK_VERSION (1, 1, 3)
|
||
static void
|
||
midori_web_view_menu_save_as_activate_cb (GtkWidget* widget,
|
||
MidoriView* view)
|
||
{
|
||
g_signal_emit (view, signals[SAVE_AS], 0, view->link_uri);
|
||
}
|
||
#endif
|
||
|
||
static void
|
||
midori_view_tab_label_menu_window_new_cb (GtkWidget* menuitem,
|
||
GtkWidget* view)
|
||
{
|
||
g_signal_emit (view, signals[NEW_WINDOW], 0,
|
||
midori_view_get_display_uri (MIDORI_VIEW (view)));
|
||
}
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 17)
|
||
static void
|
||
midori_web_view_menu_inspect_element_activate_cb (GtkWidget* widget,
|
||
MidoriView* view)
|
||
{
|
||
WebKitWebInspector* inspector;
|
||
gint x, y;
|
||
|
||
inspector = webkit_web_view_get_inspector (WEBKIT_WEB_VIEW (view->web_view));
|
||
x = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "x"));
|
||
y = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "y"));
|
||
webkit_web_inspector_inspect_coordinates (inspector, x, y);
|
||
webkit_web_inspector_show (inspector);
|
||
}
|
||
#endif
|
||
|
||
static GtkWidget*
|
||
midori_view_insert_menu_item (GtkMenuShell* menu,
|
||
gint position,
|
||
const gchar* label,
|
||
const gchar* stock_id,
|
||
GCallback callback,
|
||
GtkWidget* widget)
|
||
{
|
||
GtkWidget* menuitem;
|
||
|
||
if (label)
|
||
{
|
||
menuitem = gtk_image_menu_item_new_with_mnemonic (label);
|
||
if (stock_id)
|
||
{
|
||
GdkScreen* screen = gtk_widget_get_screen (widget);
|
||
GtkIconTheme* icon_theme = gtk_icon_theme_get_for_screen (screen);
|
||
if (gtk_icon_theme_has_icon (icon_theme, stock_id))
|
||
{
|
||
GtkWidget* icon = gtk_image_new_from_stock (stock_id,
|
||
GTK_ICON_SIZE_MENU);
|
||
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem),
|
||
icon);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
menuitem = gtk_image_menu_item_new_from_stock (stock_id, NULL);
|
||
gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, position);
|
||
if (callback)
|
||
g_signal_connect (menuitem, "activate", callback, widget);
|
||
else
|
||
gtk_widget_set_sensitive (menuitem, FALSE);
|
||
return menuitem;
|
||
}
|
||
|
||
/**
|
||
* midori_view_populate_popup:
|
||
* @view: a #MidoriView
|
||
* @menu: a #GtkMenu
|
||
* @manual: %TRUE if this a manually created popup
|
||
*
|
||
* Populates the given @menu with context menu items
|
||
* according to the position of the mouse pointer. This
|
||
* can be used in situations where a custom hotkey
|
||
* opens the context menu or the default behaviour
|
||
* needs to be intercepted.
|
||
*
|
||
* @manual should usually be %TRUE, except for the
|
||
* case where @menu was created by the #WebKitWebView.
|
||
*
|
||
* Since: 0.2.5
|
||
*/
|
||
void
|
||
midori_view_populate_popup (MidoriView* view,
|
||
GtkWidget* menu,
|
||
gboolean manual)
|
||
{
|
||
WebKitWebView* web_view = WEBKIT_WEB_VIEW (view->web_view);
|
||
GtkWidget* widget = GTK_WIDGET (view);
|
||
MidoriBrowser* browser = midori_browser_get_for_widget (widget);
|
||
GtkActionGroup* actions = midori_browser_get_action_group (browser);
|
||
GtkMenuShell* menu_shell = GTK_MENU_SHELL (menu);
|
||
GtkWidget* menuitem;
|
||
GtkWidget* icon;
|
||
gchar* stock_id;
|
||
GList* items;
|
||
gboolean has_selection;
|
||
gboolean is_editable;
|
||
gboolean is_document;
|
||
GtkWidget* label;
|
||
guint i;
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 15)
|
||
gint x, y;
|
||
WebKitHitTestResultContext context;
|
||
gboolean is_image;
|
||
gboolean is_media;
|
||
|
||
midori_view_ensure_link_uri (view, &x, &y, NULL);
|
||
context = katze_object_get_int (view->hit_test, "context");
|
||
has_selection = context & WEBKIT_HIT_TEST_RESULT_CONTEXT_SELECTION;
|
||
/* Ensure view->selected_text */
|
||
midori_view_has_selection (view);
|
||
is_editable = context & WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE;
|
||
is_image = context & WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE;
|
||
is_media = context & WEBKIT_HIT_TEST_RESULT_CONTEXT_MEDIA;
|
||
is_document = !view->link_uri && !has_selection && !is_image && !is_media;
|
||
#else
|
||
/* There is no guarantee view->link_uri is correct in case
|
||
gtk-touchscreen-mode is enabled, nothing we can do. */
|
||
has_selection = midori_view_has_selection (view);
|
||
is_document = !view->link_uri && !has_selection;
|
||
|
||
/* Unfortunately inspecting the menu is the only way to
|
||
determine that the mouse is over a text area or selection. */
|
||
items = gtk_container_get_children (GTK_CONTAINER (menu));
|
||
menuitem = (GtkWidget*)g_list_nth_data (items, 0);
|
||
if (GTK_IS_IMAGE_MENU_ITEM (menuitem))
|
||
{
|
||
icon = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (menuitem));
|
||
gtk_image_get_stock (GTK_IMAGE (icon), &stock_id, NULL);
|
||
if (!strcmp (stock_id, GTK_STOCK_FIND))
|
||
{
|
||
gtk_widget_hide (menuitem);
|
||
gtk_widget_set_no_show_all (menuitem, TRUE);
|
||
menuitem = (GtkWidget*)g_list_nth_data (items, 1);
|
||
gtk_widget_hide (menuitem);
|
||
menuitem = (GtkWidget*)g_list_nth_data (items, 2);
|
||
icon = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (menuitem));
|
||
gtk_image_get_stock (GTK_IMAGE (icon), &stock_id, NULL);
|
||
}
|
||
is_editable = !strcmp (stock_id, GTK_STOCK_CUT);
|
||
if (is_document && !strcmp (stock_id, GTK_STOCK_OPEN))
|
||
is_document = FALSE;
|
||
}
|
||
else
|
||
is_editable = FALSE;
|
||
g_list_free (items);
|
||
#endif
|
||
|
||
if (is_editable)
|
||
{
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 14)
|
||
menuitem = gtk_separator_menu_item_new ();
|
||
gtk_menu_shell_prepend (menu_shell, menuitem);
|
||
gtk_widget_show (menuitem);
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "Redo"));
|
||
gtk_widget_set_sensitive (menuitem,
|
||
webkit_web_view_can_redo (web_view));
|
||
gtk_menu_shell_prepend (menu_shell, menuitem);
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "Undo"));
|
||
gtk_widget_set_sensitive (menuitem,
|
||
webkit_web_view_can_undo (web_view));
|
||
gtk_menu_shell_prepend (menu_shell, menuitem);
|
||
#endif
|
||
if (manual)
|
||
{
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "Cut"));
|
||
gtk_widget_set_sensitive (menuitem,
|
||
webkit_web_view_can_cut_clipboard (web_view));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "Copy"));
|
||
gtk_widget_set_sensitive (menuitem,
|
||
webkit_web_view_can_copy_clipboard (web_view));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "Paste"));
|
||
gtk_widget_set_sensitive (menuitem,
|
||
webkit_web_view_can_paste_clipboard (web_view));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "Delete"));
|
||
gtk_widget_set_sensitive (menuitem,
|
||
webkit_web_view_can_cut_clipboard (web_view));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
menuitem = gtk_separator_menu_item_new ();
|
||
gtk_widget_show (menuitem);
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "SelectAll"));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
/* FIXME: We are missing Font, Input Methods and Insert Character */
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 17)
|
||
if (katze_object_get_boolean (view->settings, "enable-developer-extras"))
|
||
{
|
||
menuitem = gtk_separator_menu_item_new ();
|
||
gtk_widget_show (menuitem);
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
menuitem = midori_view_insert_menu_item (menu_shell, -1,
|
||
_("Inspect _Element"), NULL,
|
||
G_CALLBACK (midori_web_view_menu_inspect_element_activate_cb),
|
||
widget);
|
||
gtk_widget_show (menuitem);
|
||
g_object_set_data (G_OBJECT (menuitem), "x", GINT_TO_POINTER (x));
|
||
g_object_set_data (G_OBJECT (menuitem), "y", GINT_TO_POINTER (y));
|
||
}
|
||
#endif
|
||
}
|
||
return;
|
||
}
|
||
|
||
items = gtk_container_get_children (GTK_CONTAINER (menu));
|
||
menuitem = (GtkWidget*)g_list_nth_data (items, 0);
|
||
/* Form control: no items */
|
||
if (!manual && !menuitem)
|
||
{
|
||
g_list_free (items);
|
||
return;
|
||
}
|
||
/* Form control: separator and Inspect element */
|
||
if (!manual && GTK_IS_SEPARATOR_MENU_ITEM (menuitem) && g_list_length (items) == 2)
|
||
{
|
||
gtk_widget_destroy (menuitem);
|
||
g_list_free (items);
|
||
return;
|
||
}
|
||
g_list_free (items);
|
||
/* Link and/ or image, but falsely reported as document */
|
||
if (is_document)
|
||
{
|
||
if (GTK_IS_IMAGE_MENU_ITEM (menuitem))
|
||
{
|
||
icon = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (menuitem));
|
||
gtk_image_get_stock (GTK_IMAGE (icon), &stock_id, NULL);
|
||
if (stock_id && !strcmp (stock_id, GTK_STOCK_OPEN))
|
||
return;
|
||
}
|
||
}
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 15)
|
||
if (!is_document)
|
||
{
|
||
items = gtk_container_get_children (GTK_CONTAINER (menu));
|
||
i = 0;
|
||
while ((menuitem = g_list_nth_data (items, i++)))
|
||
gtk_widget_destroy (menuitem);
|
||
g_list_free (items);
|
||
}
|
||
if (view->link_uri)
|
||
{
|
||
midori_view_insert_menu_item (menu_shell, -1,
|
||
_("Open Link in New _Tab"), STOCK_TAB_NEW,
|
||
G_CALLBACK (midori_web_view_menu_new_tab_activate_cb), widget);
|
||
midori_view_insert_menu_item (menu_shell, -1,
|
||
view->open_tabs_in_the_background
|
||
? _("Open Link in _Foreground Tab")
|
||
: _("Open Link in _Background Tab"), NULL,
|
||
G_CALLBACK (midori_web_view_menu_background_tab_activate_cb), widget);
|
||
midori_view_insert_menu_item (menu_shell, -1,
|
||
_("Open Link in New _Window"), STOCK_WINDOW_NEW,
|
||
G_CALLBACK (midori_web_view_menu_new_window_activate_cb), widget);
|
||
midori_view_insert_menu_item (menu_shell, -1,
|
||
_("Open Link as Web A_pplication"), NULL,
|
||
G_CALLBACK (midori_web_view_menu_web_app_activate_cb), widget);
|
||
midori_view_insert_menu_item (menu_shell, -1,
|
||
_("Copy Link de_stination"), NULL,
|
||
G_CALLBACK (midori_web_view_menu_link_copy_activate_cb), widget);
|
||
midori_view_insert_menu_item (menu_shell, -1,
|
||
NULL, GTK_STOCK_SAVE_AS,
|
||
G_CALLBACK (midori_web_view_menu_save_activate_cb), widget);
|
||
}
|
||
|
||
if (is_image)
|
||
{
|
||
if (view->link_uri)
|
||
gtk_menu_shell_append (menu_shell, gtk_separator_menu_item_new ());
|
||
midori_view_insert_menu_item (menu_shell, -1,
|
||
_("Open _Image in New Tab"), STOCK_TAB_NEW,
|
||
G_CALLBACK (midori_web_view_menu_image_new_tab_activate_cb), widget);
|
||
midori_view_insert_menu_item (menu_shell, -1,
|
||
_("Copy Image _Address"), NULL,
|
||
G_CALLBACK (midori_web_view_menu_image_copy_activate_cb), widget);
|
||
midori_view_insert_menu_item (menu_shell, -1,
|
||
_("Save I_mage"), GTK_STOCK_SAVE,
|
||
G_CALLBACK (midori_web_view_menu_image_save_activate_cb), widget);
|
||
}
|
||
|
||
if (is_media)
|
||
{
|
||
midori_view_insert_menu_item (menu_shell, -1,
|
||
_("Copy Video _Address"), NULL,
|
||
G_CALLBACK (midori_web_view_menu_video_copy_activate_cb), widget);
|
||
midori_view_insert_menu_item (menu_shell, -1,
|
||
FALSE ? _("Save _Video") : _("Download _Video"), GTK_STOCK_SAVE,
|
||
G_CALLBACK (midori_web_view_menu_video_save_activate_cb), widget);
|
||
}
|
||
|
||
if (has_selection)
|
||
{
|
||
gtk_menu_shell_append (menu_shell, gtk_separator_menu_item_new ());
|
||
midori_view_insert_menu_item (menu_shell, -1, NULL, GTK_STOCK_COPY,
|
||
G_CALLBACK (midori_web_view_menu_copy_activate_cb), widget);
|
||
}
|
||
#else
|
||
if (view->link_uri)
|
||
{
|
||
items = gtk_container_get_children (GTK_CONTAINER (menu));
|
||
menuitem = (GtkWidget*)g_list_nth_data (items, 0);
|
||
/* hack to hide menu item */
|
||
gtk_widget_hide (menuitem);
|
||
midori_view_insert_menu_item (menu_shell, 1,
|
||
_("Open Link in New _Tab"), STOCK_TAB_NEW,
|
||
G_CALLBACK (midori_web_view_menu_new_tab_activate_cb), widget);
|
||
g_list_free (items);
|
||
items = gtk_container_get_children (GTK_CONTAINER (menu));
|
||
menuitem = (GtkWidget*)g_list_nth_data (items, 2);
|
||
/* hack to localize menu item */
|
||
label = gtk_bin_get_child (GTK_BIN (menuitem));
|
||
gtk_label_set_label (GTK_LABEL (label), _("Open Link in New _Window"));
|
||
menuitem = (GtkWidget*)g_list_nth_data (items, 3);
|
||
g_list_free (items);
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 3)
|
||
/* hack to localize menu item */
|
||
label = gtk_bin_get_child (GTK_BIN (menuitem));
|
||
GtkStockItem stock_item;
|
||
if (gtk_stock_lookup (GTK_STOCK_SAVE_AS, &stock_item))
|
||
gtk_label_set_label (GTK_LABEL (label), stock_item.label);
|
||
#else
|
||
/* hack to disable non-functional Download File */
|
||
gtk_widget_hide (menuitem);
|
||
gtk_widget_set_no_show_all (menuitem, TRUE);
|
||
midori_view_insert_menu_item (menu_shell, 3,
|
||
NULL, GTK_STOCK_SAVE_AS,
|
||
G_CALLBACK (midori_web_view_menu_save_as_activate_cb), widget);
|
||
#endif
|
||
}
|
||
#endif
|
||
|
||
if (!view->link_uri && has_selection)
|
||
{
|
||
GtkWidget* window;
|
||
KatzeArray* search_engines = NULL;
|
||
|
||
window = gtk_widget_get_toplevel (GTK_WIDGET (web_view));
|
||
i = 0;
|
||
if (katze_object_has_property (window, "search-engines"))
|
||
search_engines = katze_object_get_object (window, "search-engines");
|
||
|
||
if (search_engines != NULL)
|
||
{
|
||
KatzeItem* item;
|
||
GtkWidget* sub_menu = gtk_menu_new ();
|
||
|
||
menuitem = gtk_image_menu_item_new_with_mnemonic (_("Search _with"));
|
||
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), sub_menu);
|
||
gtk_menu_shell_insert (menu_shell, menuitem, 1);
|
||
|
||
KATZE_ARRAY_FOREACH_ITEM (item, search_engines)
|
||
{
|
||
GdkPixbuf* pixbuf;
|
||
const gchar* icon_name;
|
||
|
||
menuitem = gtk_image_menu_item_new_with_mnemonic (katze_item_get_name (item));
|
||
pixbuf = midori_search_action_get_icon (item,
|
||
GTK_WIDGET (web_view), &icon_name);
|
||
if (pixbuf)
|
||
{
|
||
icon = gtk_image_new_from_pixbuf (pixbuf);
|
||
g_object_unref (pixbuf);
|
||
}
|
||
else
|
||
icon = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
|
||
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon);
|
||
#if GTK_CHECK_VERSION (2, 16, 0)
|
||
gtk_image_menu_item_set_always_show_image (
|
||
GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
|
||
#endif
|
||
gtk_menu_shell_insert (GTK_MENU_SHELL (sub_menu), menuitem, i);
|
||
g_object_set_data (G_OBJECT (menuitem), "search",
|
||
(gchar*)katze_item_get_uri (item));
|
||
g_signal_connect (menuitem, "activate",
|
||
G_CALLBACK (midori_web_view_menu_search_web_activate_cb), view);
|
||
i++;
|
||
}
|
||
g_object_unref (search_engines);
|
||
}
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 15)
|
||
midori_view_insert_menu_item (menu_shell, 0,
|
||
_("_Search the Web"), GTK_STOCK_FIND,
|
||
G_CALLBACK (midori_web_view_menu_search_web_activate_cb), widget);
|
||
#else
|
||
items = gtk_container_get_children (GTK_CONTAINER (menu));
|
||
menuitem = (GtkWidget*)g_list_nth_data (items, 0);
|
||
/* hack to localize menu item */
|
||
label = gtk_bin_get_child (GTK_BIN (menuitem));
|
||
gtk_label_set_label (GTK_LABEL (label), _("_Search the Web"));
|
||
/* hack to implement Search the Web */
|
||
g_signal_connect (menuitem, "activate",
|
||
G_CALLBACK (midori_web_view_menu_search_web_activate_cb), view);
|
||
g_list_free (items);
|
||
#endif
|
||
|
||
g_strstrip (view->selected_text);
|
||
if (view->selected_text && !strchr (view->selected_text, ' ')
|
||
&& (strchr (view->selected_text, '.') || g_strstr_len (view->selected_text, 9, "://")))
|
||
{
|
||
if (strchr (view->selected_text, '@'))
|
||
{
|
||
gchar* text = g_strdup_printf (_("Send a message to %s"), view->selected_text);
|
||
menuitem = midori_view_insert_menu_item (menu_shell, -1,
|
||
text, GTK_STOCK_JUMP_TO,
|
||
G_CALLBACK (midori_web_view_menu_new_tab_activate_cb), widget);
|
||
g_free (text);
|
||
}
|
||
else
|
||
menuitem = midori_view_insert_menu_item (menu_shell, -1,
|
||
_("Open Address in New _Tab"), GTK_STOCK_JUMP_TO,
|
||
G_CALLBACK (midori_web_view_menu_new_tab_activate_cb), widget);
|
||
g_object_set_data (G_OBJECT (menuitem), "uri", view->selected_text);
|
||
}
|
||
}
|
||
|
||
if (is_document)
|
||
{
|
||
if (manual)
|
||
{
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "Back"));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "Forward"));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "Stop"));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "Reload"));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
}
|
||
else
|
||
{
|
||
items = gtk_container_get_children (GTK_CONTAINER (menu));
|
||
#if HAVE_HILDON
|
||
gtk_widget_hide (g_list_nth_data (items, 2));
|
||
gtk_widget_set_no_show_all (g_list_nth_data (items, 2), TRUE);
|
||
gtk_widget_hide (g_list_nth_data (items, 3));
|
||
gtk_widget_set_no_show_all (g_list_nth_data (items, 3), TRUE);
|
||
#endif
|
||
menuitem = (GtkWidget*)g_list_nth_data (items, 3);
|
||
/* hack to localize menu item */
|
||
if (GTK_IS_BIN (menuitem))
|
||
{
|
||
GtkStockItem stock_item;
|
||
if (gtk_stock_lookup (GTK_STOCK_REFRESH, &stock_item))
|
||
{
|
||
label = gtk_bin_get_child (GTK_BIN (menuitem));
|
||
gtk_label_set_label (GTK_LABEL (label), stock_item.label);
|
||
}
|
||
}
|
||
g_list_free (items);
|
||
}
|
||
|
||
gtk_menu_shell_append (menu_shell, gtk_separator_menu_item_new ());
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "UndoTabClose"));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
menuitem = gtk_image_menu_item_new_from_stock (STOCK_WINDOW_NEW, NULL);
|
||
gtk_menu_item_set_label (GTK_MENU_ITEM (menuitem), _("Open in New _Window"));
|
||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||
g_signal_connect (menuitem, "activate",
|
||
G_CALLBACK (midori_view_tab_label_menu_window_new_cb), view);
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 15)
|
||
/* if (webkit_web_view_get_main_frame (web_view) != frame_under_mouse)
|
||
{
|
||
midori_view_insert_menu_item (menu_shell, -1,
|
||
_("Open _Frame in New Tab"), NULL,
|
||
G_CALLBACK (midori_web_view_menu_frame_new_tab_activate_cb), widget);
|
||
midori_view_insert_menu_item (menu_shell, -1,
|
||
_("Open _Frame in New Window"), NULL,
|
||
G_CALLBACK (midori_web_view_menu_frame_new_window_activate_cb), widget);
|
||
} */
|
||
#endif
|
||
|
||
#if !HAVE_HILDON
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "ZoomIn"));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "ZoomOut"));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
#endif
|
||
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "Encoding"));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
if (gtk_widget_get_sensitive (menuitem))
|
||
{
|
||
GtkWidget* sub_menu;
|
||
static const GtkActionEntry encodings[] = {
|
||
{ "EncodingAutomatic" },
|
||
{ "EncodingChinese" },
|
||
{ "EncodingJapanese" },
|
||
{ "EncodingKorean" },
|
||
{ "EncodingRussian" },
|
||
{ "EncodingUnicode" },
|
||
{ "EncodingWestern" },
|
||
{ "EncodingCustom" },
|
||
};
|
||
|
||
sub_menu = gtk_menu_new ();
|
||
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), sub_menu);
|
||
|
||
for (i = 0; i < G_N_ELEMENTS (encodings); i++)
|
||
{
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, encodings[i].name));
|
||
gtk_menu_shell_append (GTK_MENU_SHELL (sub_menu), menuitem);
|
||
}
|
||
}
|
||
|
||
#if HAVE_HILDON
|
||
gtk_menu_shell_append (menu_shell, gtk_separator_menu_item_new ());
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "CompactAdd"));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "Fullscreen"));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "PrivateBrowsing"));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
#else
|
||
gtk_menu_shell_append (menu_shell, gtk_separator_menu_item_new ());
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "BookmarkAdd"));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
|
||
if (!midori_view_is_blank (view)
|
||
&& strcmp ("/", sokoke_set_config_dir (NULL)))
|
||
{
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "AddSpeedDial"));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
}
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "AddDesktopShortcut"));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
#endif
|
||
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "SaveAs"));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
/* Currently views that don't support source, don't support
|
||
saving either. If that changes, we need to think of something. */
|
||
if (!midori_view_can_view_source (view))
|
||
gtk_widget_set_sensitive (menuitem, FALSE);
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "SourceView"));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
|
||
if (!g_object_get_data (G_OBJECT (browser), "midori-toolbars-visible"))
|
||
{
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "Navigationbar"));
|
||
gtk_menu_shell_append (menu_shell, menuitem);
|
||
}
|
||
}
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 17)
|
||
if ((!is_document || manual)
|
||
&& katze_object_get_boolean (view->settings, "enable-developer-extras"))
|
||
{
|
||
gtk_menu_shell_append (menu_shell, gtk_separator_menu_item_new ());
|
||
menuitem = midori_view_insert_menu_item (menu_shell, -1,
|
||
_("Inspect _Element"), NULL,
|
||
G_CALLBACK (midori_web_view_menu_inspect_element_activate_cb), widget);
|
||
g_object_set_data (G_OBJECT (menuitem), "x", GINT_TO_POINTER (x));
|
||
g_object_set_data (G_OBJECT (menuitem), "y", GINT_TO_POINTER (y));
|
||
}
|
||
#endif
|
||
|
||
gtk_widget_show_all (menu);
|
||
}
|
||
|
||
static void
|
||
webkit_web_view_populate_popup_cb (WebKitWebView* web_view,
|
||
GtkWidget* menu,
|
||
MidoriView* view)
|
||
{
|
||
midori_view_populate_popup (view, menu, FALSE);
|
||
}
|
||
|
||
#if HAVE_HILDON
|
||
static void
|
||
midori_view_web_view_tap_and_hold_cb (GtkWidget* web_view,
|
||
gpointer data)
|
||
{
|
||
gint x, y;
|
||
GdkEvent event;
|
||
gboolean result;
|
||
|
||
/* Emulate a pointer motion above the tap position
|
||
and a right click at the according position. */
|
||
event.any.window = gtk_widget_get_window (web_view);
|
||
gdk_window_get_pointer (event.any.window, &x, &y, NULL);
|
||
event.any.type = GDK_MOTION_NOTIFY;
|
||
event.motion.x = x;
|
||
event.motion.y = y;
|
||
g_signal_emit_by_name (web_view, "motion-notify-event", &event, &result);
|
||
|
||
event.any.type = GDK_BUTTON_PRESS;
|
||
event.button.axes = NULL;
|
||
event.button.x = x;
|
||
event.button.y = y;
|
||
event.button.button = 3;
|
||
g_signal_emit_by_name (web_view, "button-press-event", &event, &result);
|
||
}
|
||
#endif
|
||
|
||
static gboolean
|
||
webkit_web_view_web_view_ready_cb (GtkWidget* web_view,
|
||
MidoriView* view)
|
||
{
|
||
GtkWidget* new_view = gtk_widget_get_parent (gtk_widget_get_parent (web_view));
|
||
MidoriNewView where = MIDORI_NEW_VIEW_TAB;
|
||
|
||
/* FIXME: Open windows opened by scripts in tabs if they otherwise
|
||
would be replacing the page the user opened. */
|
||
if (view->open_new_pages_in == MIDORI_NEW_PAGE_CURRENT)
|
||
return TRUE;
|
||
|
||
if (view->open_new_pages_in == MIDORI_NEW_PAGE_TAB)
|
||
{
|
||
if (view->open_tabs_in_the_background)
|
||
where = MIDORI_NEW_VIEW_BACKGROUND;
|
||
}
|
||
else if (view->open_new_pages_in == MIDORI_NEW_PAGE_WINDOW)
|
||
where = MIDORI_NEW_VIEW_WINDOW;
|
||
|
||
gtk_widget_show (new_view);
|
||
g_signal_emit (view, signals[NEW_VIEW], 0, new_view, where);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static GtkWidget*
|
||
webkit_web_view_create_web_view_cb (GtkWidget* web_view,
|
||
WebKitWebFrame* web_frame,
|
||
MidoriView* view)
|
||
{
|
||
MidoriView* new_view;
|
||
|
||
if (view->open_new_pages_in == MIDORI_NEW_PAGE_CURRENT)
|
||
new_view = view;
|
||
else
|
||
{
|
||
new_view = (MidoriView*)midori_view_new_with_title (NULL,
|
||
view->settings, FALSE);
|
||
g_signal_connect (new_view->web_view, "web-view-ready",
|
||
G_CALLBACK (webkit_web_view_web_view_ready_cb), view);
|
||
}
|
||
return new_view->web_view;
|
||
}
|
||
|
||
static gboolean
|
||
webkit_web_view_mime_type_decision_cb (GtkWidget* web_view,
|
||
WebKitWebFrame* web_frame,
|
||
WebKitNetworkRequest* request,
|
||
const gchar* mime_type,
|
||
WebKitWebPolicyDecision* decision,
|
||
MidoriView* view)
|
||
{
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 3)
|
||
GtkWidget* dialog;
|
||
gchar* content_type;
|
||
gchar* description;
|
||
gchar* file_type;
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 14)
|
||
WebKitWebDataSource* datasource;
|
||
WebKitNetworkRequest* original_request;
|
||
#endif
|
||
const gchar* original_uri;
|
||
gchar** fingerprint;
|
||
#if GTK_CHECK_VERSION (2, 14, 0)
|
||
GIcon* icon;
|
||
GtkWidget* image;
|
||
#endif
|
||
gchar* title;
|
||
GdkScreen* screen;
|
||
GtkIconTheme* icon_theme;
|
||
gint response;
|
||
#else
|
||
gchar* uri;
|
||
#endif
|
||
|
||
if (web_frame != webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (web_view)))
|
||
return FALSE;
|
||
|
||
if (webkit_web_view_can_show_mime_type (WEBKIT_WEB_VIEW (web_view), mime_type))
|
||
{
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 14)
|
||
gboolean view_source = FALSE;
|
||
/* Dedicated source code views are always pseudo-blank pages */
|
||
if (midori_view_is_blank (view))
|
||
view_source = webkit_web_view_get_view_source_mode (WEBKIT_WEB_VIEW (web_view));
|
||
|
||
/* Render raw XML, including news feeds, as source */
|
||
if (!view_source && (!strcmp (mime_type, "application/xml")
|
||
|| !strcmp (mime_type, "text/xml")))
|
||
view_source = TRUE;
|
||
webkit_web_view_set_view_source_mode (WEBKIT_WEB_VIEW (web_view), view_source);
|
||
#endif
|
||
|
||
katze_assign (view->mime_type, g_strdup (mime_type));
|
||
midori_view_update_icon (view, NULL);
|
||
g_object_notify (G_OBJECT (view), "mime-type");
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 3)
|
||
dialog = gtk_message_dialog_new (
|
||
NULL, 0, GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE,
|
||
_("Open or download file"));
|
||
content_type = g_content_type_from_mime_type (mime_type);
|
||
if (!content_type)
|
||
#ifdef G_OS_WIN32
|
||
content_type = g_content_type_get_mime_type ("*");
|
||
#else
|
||
content_type = g_strdup ("application/octet-stream");
|
||
#endif
|
||
description = g_content_type_get_description (content_type);
|
||
#if GTK_CHECK_VERSION (2, 14, 0)
|
||
icon = g_content_type_get_icon (content_type);
|
||
g_themed_icon_append_name (G_THEMED_ICON (icon), "document-x-generic");
|
||
image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_DIALOG);
|
||
g_object_unref (icon);
|
||
gtk_widget_show (image);
|
||
gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), image);
|
||
#endif
|
||
g_free (content_type);
|
||
if (g_strrstr (description, mime_type))
|
||
file_type = g_strdup_printf (_("File Type: '%s'"), mime_type);
|
||
else
|
||
file_type = g_strdup_printf (_("File Type: %s ('%s')"), description, mime_type);
|
||
g_free (description);
|
||
|
||
/* Link Fingerprint */
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 14)
|
||
/* We look at the original URI because redirection would lose the fragment */
|
||
datasource = webkit_web_frame_get_provisional_data_source (web_frame);
|
||
original_request = webkit_web_data_source_get_initial_request (datasource);
|
||
original_uri = webkit_network_request_get_uri (original_request);
|
||
#else
|
||
original_uri = webkit_network_request_get_uri (request);
|
||
#endif
|
||
fingerprint = g_strsplit (original_uri, "#!md5!", 2);
|
||
if (fingerprint && fingerprint[0] && fingerprint[1])
|
||
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
|
||
"%s\n%s %s", file_type, _("MD5-Checksum:"), fingerprint[1]);
|
||
else
|
||
{
|
||
g_strfreev (fingerprint);
|
||
fingerprint = g_strsplit (original_uri, "#!sha1!", 2);
|
||
if (fingerprint && fingerprint[0] && fingerprint[1])
|
||
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
|
||
"%s\n%s %s", file_type, _("SHA1-Checksum:"), fingerprint[1]);
|
||
else
|
||
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
|
||
"%s", file_type);
|
||
}
|
||
g_strfreev (fingerprint);
|
||
g_free (file_type);
|
||
|
||
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), FALSE);
|
||
/* i18n: A file open dialog title, ie. "Open http://fila.com/manual.tgz" */
|
||
title = g_strdup_printf (_("Open %s"),
|
||
webkit_network_request_get_uri (request));
|
||
gtk_window_set_title (GTK_WINDOW (dialog), title);
|
||
g_free (title);
|
||
screen = gtk_widget_get_screen (dialog);
|
||
if (screen)
|
||
{
|
||
icon_theme = gtk_icon_theme_get_for_screen (screen);
|
||
if (gtk_icon_theme_has_icon (icon_theme, STOCK_TRANSFER))
|
||
gtk_window_set_icon_name (GTK_WINDOW (dialog), STOCK_TRANSFER);
|
||
else
|
||
gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_OPEN);
|
||
}
|
||
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
|
||
GTK_STOCK_SAVE, 1,
|
||
GTK_STOCK_SAVE_AS, 4,
|
||
GTK_STOCK_CANCEL, 2,
|
||
GTK_STOCK_OPEN, 3,
|
||
NULL);
|
||
response = gtk_dialog_run (GTK_DIALOG (dialog));
|
||
gtk_widget_destroy (dialog);
|
||
g_object_set_data (G_OBJECT (view), "open-download", (gpointer)0);
|
||
switch (response)
|
||
{
|
||
case 4:
|
||
g_object_set_data (G_OBJECT (view), "save-as-download", (gpointer)1);
|
||
webkit_web_policy_decision_download (decision);
|
||
webkit_web_view_stop_loading (WEBKIT_WEB_VIEW (view->web_view));
|
||
return TRUE;
|
||
case 3:
|
||
g_object_set_data (G_OBJECT (view), "open-download", (gpointer)1);
|
||
case 1:
|
||
webkit_web_policy_decision_download (decision);
|
||
/* Apparently WebKit will continue loading which ends in an error.
|
||
It's unclear whether it's a bug or we are doing something wrong. */
|
||
webkit_web_view_stop_loading (WEBKIT_WEB_VIEW (view->web_view));
|
||
return TRUE;
|
||
case 2:
|
||
default:
|
||
/* Apparently WebKit will continue loading which ends in an error.
|
||
It's unclear whether it's a bug or we are doing something wrong. */
|
||
webkit_web_view_stop_loading (WEBKIT_WEB_VIEW (view->web_view));
|
||
return FALSE;
|
||
}
|
||
#else
|
||
katze_assign (view->mime_type, NULL);
|
||
midori_view_update_icon (view, NULL);
|
||
g_object_notify (G_OBJECT (view), "mime-type");
|
||
|
||
uri = g_strdup_printf ("error:nodisplay %s",
|
||
webkit_network_request_get_uri (request));
|
||
midori_view_set_uri (view, uri);
|
||
g_free (uri);
|
||
|
||
return TRUE;
|
||
#endif
|
||
}
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 3)
|
||
static gboolean
|
||
webkit_web_view_download_requested_cb (GtkWidget* web_view,
|
||
WebKitDownload* download,
|
||
MidoriView* view)
|
||
{
|
||
gboolean handled;
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 14)
|
||
/* Propagate original URI to make it available when the download finishes */
|
||
WebKitWebFrame* web_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (web_view));
|
||
WebKitWebDataSource* datasource = webkit_web_frame_get_provisional_data_source (web_frame);
|
||
WebKitNetworkRequest* original_request = webkit_web_data_source_get_initial_request (datasource);
|
||
const gchar* original_uri = webkit_network_request_get_uri (original_request);
|
||
WebKitNetworkRequest* request = webkit_download_get_network_request (download);
|
||
g_object_set_data_full (G_OBJECT (request), "midori-original-uri",
|
||
g_strdup (original_uri), g_free);
|
||
#endif
|
||
g_object_set_data (G_OBJECT (download), "open-download",
|
||
g_object_get_data (G_OBJECT (view), "open-download"));
|
||
g_object_set_data (G_OBJECT (download), "save-as-download",
|
||
g_object_get_data (G_OBJECT (view), "save-as-download"));
|
||
g_object_set_data (G_OBJECT (view), "open-download", (gpointer)0);
|
||
g_object_set_data (G_OBJECT (view), "save-as-download", (gpointer)0);
|
||
g_signal_emit (view, signals[DOWNLOAD_REQUESTED], 0, download, &handled);
|
||
return handled;
|
||
}
|
||
#endif
|
||
|
||
static gboolean
|
||
webkit_web_view_console_message_cb (GtkWidget* web_view,
|
||
const gchar* message,
|
||
guint line,
|
||
const gchar* source_id,
|
||
MidoriView* view)
|
||
{
|
||
if (!strncmp (message, "speed_dial-save", 13))
|
||
midori_view_speed_dial_save (view, message);
|
||
else
|
||
g_signal_emit (view, signals[CONSOLE_MESSAGE], 0, message, line, source_id);
|
||
return TRUE;
|
||
}
|
||
|
||
static void
|
||
midori_view_script_response_cb (GtkWidget* infobar,
|
||
gint response,
|
||
MidoriView* view)
|
||
{
|
||
view->alerts--;
|
||
}
|
||
|
||
static gboolean
|
||
midori_view_web_view_script_alert_cb (GtkWidget* web_view,
|
||
WebKitWebFrame* web_frame,
|
||
const gchar* message,
|
||
MidoriView* view)
|
||
{
|
||
gchar* text;
|
||
|
||
/* Allow a maximum of 5 alerts */
|
||
if (view->alerts > 4)
|
||
return TRUE;
|
||
|
||
view->alerts++;
|
||
/* i18n: The text of an infobar for JavaScript alert messages */
|
||
text = g_strdup_printf ("JavaScript: %s", message);
|
||
midori_view_add_info_bar (view, GTK_MESSAGE_WARNING, text,
|
||
G_CALLBACK (midori_view_script_response_cb), view,
|
||
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);
|
||
g_free (text);
|
||
return TRUE;
|
||
}
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 5)
|
||
static gboolean
|
||
midori_view_web_view_print_requested_cb (GtkWidget* web_view,
|
||
WebKitWebFrame* web_frame,
|
||
MidoriView* view)
|
||
{
|
||
midori_view_print (view);
|
||
return TRUE;
|
||
}
|
||
#endif
|
||
|
||
static void
|
||
webkit_web_view_window_object_cleared_cb (GtkWidget* web_view,
|
||
WebKitWebFrame* web_frame,
|
||
JSContextRef js_context,
|
||
JSObjectRef js_window,
|
||
MidoriView* view)
|
||
{
|
||
g_signal_emit (view, signals[CONTEXT_READY], 0, js_context);
|
||
}
|
||
|
||
static void
|
||
midori_view_hadjustment_notify_value_cb (GtkAdjustment* hadjustment,
|
||
GParamSpec* pspec,
|
||
MidoriView* view)
|
||
{
|
||
gint value = (gint)gtk_adjustment_get_value (hadjustment);
|
||
katze_item_set_meta_integer (view->item, "scrollh", value);
|
||
}
|
||
|
||
static void
|
||
midori_view_notify_hadjustment_cb (MidoriView* view,
|
||
GParamSpec* pspec,
|
||
gpointer data)
|
||
{
|
||
GtkScrolledWindow* scrolled = GTK_SCROLLED_WINDOW (view->scrolled_window);
|
||
GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment (scrolled);
|
||
g_signal_connect (hadjustment, "notify::value",
|
||
G_CALLBACK (midori_view_hadjustment_notify_value_cb), view);
|
||
}
|
||
|
||
static void
|
||
midori_view_vadjustment_notify_value_cb (GtkAdjustment* vadjustment,
|
||
GParamSpec* pspec,
|
||
MidoriView* view)
|
||
{
|
||
gint value = (gint)gtk_adjustment_get_value (vadjustment);
|
||
katze_item_set_meta_integer (view->item, "scrollv", value);
|
||
}
|
||
|
||
static void
|
||
midori_view_notify_vadjustment_cb (MidoriView* view,
|
||
GParamSpec* pspec,
|
||
gpointer data)
|
||
{
|
||
GtkScrolledWindow* scrolled = GTK_SCROLLED_WINDOW (view->scrolled_window);
|
||
GtkAdjustment* vadjustment = gtk_scrolled_window_get_vadjustment (scrolled);
|
||
g_signal_connect (vadjustment, "notify::value",
|
||
G_CALLBACK (midori_view_vadjustment_notify_value_cb), view);
|
||
}
|
||
|
||
static void
|
||
katze_net_object_maybe_unref (gpointer object)
|
||
{
|
||
if (object)
|
||
g_object_unref (object);
|
||
}
|
||
|
||
static GHashTable* midori_view_get_memory (void)
|
||
{
|
||
static GHashTable* memory = NULL;
|
||
if (!memory)
|
||
memory = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||
g_free, katze_net_object_maybe_unref);
|
||
return g_hash_table_ref (memory);
|
||
|
||
}
|
||
|
||
static void
|
||
midori_view_init (MidoriView* view)
|
||
{
|
||
view->uri = NULL;
|
||
view->title = NULL;
|
||
view->security = MIDORI_SECURITY_NONE;
|
||
view->mime_type = g_strdup ("");
|
||
view->icon = NULL;
|
||
view->icon_uri = NULL;
|
||
view->memory = midori_view_get_memory ();
|
||
view->progress = 0.0;
|
||
view->load_status = MIDORI_LOAD_FINISHED;
|
||
view->minimized = FALSE;
|
||
view->statusbar_text = NULL;
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 15)
|
||
view->hit_test = NULL;
|
||
#endif
|
||
view->link_uri = NULL;
|
||
view->selected_text = NULL;
|
||
view->news_feeds = katze_array_new (KATZE_TYPE_ITEM);
|
||
view->find_links = -1;
|
||
view->alerts = 0;
|
||
|
||
view->item = katze_item_new ();
|
||
|
||
view->scrollh = view->scrollv = -2;
|
||
view->back_forward_set = FALSE;
|
||
|
||
view->news_aggregator = NULL;
|
||
view->web_view = NULL;
|
||
/* Adjustments are not created initially, but overwritten later */
|
||
view->scrolled_window = katze_scrolled_new (NULL, NULL);
|
||
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (view->scrolled_window),
|
||
GTK_SHADOW_NONE);
|
||
gtk_container_add (GTK_CONTAINER (view), view->scrolled_window);
|
||
|
||
g_signal_connect (view->item, "meta-data-changed",
|
||
G_CALLBACK (midori_view_item_meta_data_changed), view);
|
||
g_signal_connect (view->scrolled_window, "notify::hadjustment",
|
||
G_CALLBACK (midori_view_notify_hadjustment_cb), view);
|
||
g_signal_connect (view->scrolled_window, "notify::vadjustment",
|
||
G_CALLBACK (midori_view_notify_vadjustment_cb), view);
|
||
|
||
midori_view_construct_web_view (view);
|
||
}
|
||
|
||
static void
|
||
midori_view_finalize (GObject* object)
|
||
{
|
||
MidoriView* view;
|
||
|
||
view = MIDORI_VIEW (object);
|
||
|
||
if (view->settings)
|
||
g_signal_handlers_disconnect_by_func (view->settings,
|
||
midori_view_settings_notify_cb, view);
|
||
g_signal_handlers_disconnect_by_func (view->item,
|
||
midori_view_item_meta_data_changed, view);
|
||
|
||
if (view->thumb_view)
|
||
{
|
||
gtk_widget_destroy (view->thumb_view);
|
||
view->thumb_view = NULL;
|
||
}
|
||
|
||
katze_assign (view->uri, NULL);
|
||
katze_assign (view->title, NULL);
|
||
katze_object_assign (view->icon, NULL);
|
||
katze_assign (view->icon_uri, NULL);
|
||
|
||
if (view->memory)
|
||
{
|
||
g_hash_table_unref (view->memory);
|
||
view->memory = NULL;
|
||
}
|
||
|
||
katze_assign (view->statusbar_text, NULL);
|
||
katze_assign (view->link_uri, NULL);
|
||
katze_assign (view->selected_text, NULL);
|
||
katze_object_assign (view->news_feeds, NULL);
|
||
|
||
katze_object_assign (view->settings, NULL);
|
||
katze_object_assign (view->item, NULL);
|
||
|
||
katze_assign (view->news_aggregator, NULL);
|
||
|
||
G_OBJECT_CLASS (midori_view_parent_class)->finalize (object);
|
||
}
|
||
|
||
static void
|
||
midori_view_set_property (GObject* object,
|
||
guint prop_id,
|
||
const GValue* value,
|
||
GParamSpec* pspec)
|
||
{
|
||
MidoriView* view;
|
||
|
||
view = MIDORI_VIEW (object);
|
||
|
||
switch (prop_id)
|
||
{
|
||
case PROP_TITLE:
|
||
midori_view_set_title (view, g_value_get_string (value));
|
||
break;
|
||
case PROP_MINIMIZED:
|
||
view->minimized = g_value_get_boolean (value);
|
||
g_signal_handlers_block_by_func (view->item,
|
||
midori_view_item_meta_data_changed, view);
|
||
katze_item_set_meta_integer (view->item, "minimized",
|
||
view->minimized ? 1 : -1);
|
||
g_signal_handlers_unblock_by_func (view->item,
|
||
midori_view_item_meta_data_changed, view);
|
||
if (view->tab_label)
|
||
sokoke_widget_set_visible (view->tab_title, !view->minimized);
|
||
break;
|
||
case PROP_ZOOM_LEVEL:
|
||
midori_view_set_zoom_level (view, g_value_get_float (value));
|
||
break;
|
||
case PROP_STATUSBAR_TEXT:
|
||
katze_assign (view->statusbar_text, g_value_dup_string (value));
|
||
break;
|
||
case PROP_SETTINGS:
|
||
_midori_view_set_settings (view, g_value_get_object (value));
|
||
break;
|
||
default:
|
||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||
break;
|
||
}
|
||
}
|
||
|
||
static void
|
||
midori_view_get_property (GObject* object,
|
||
guint prop_id,
|
||
GValue* value,
|
||
GParamSpec* pspec)
|
||
{
|
||
MidoriView* view = MIDORI_VIEW (object);
|
||
|
||
switch (prop_id)
|
||
{
|
||
case PROP_URI:
|
||
g_value_set_string (value, view->uri);
|
||
break;
|
||
case PROP_TITLE:
|
||
g_value_set_string (value, view->title);
|
||
break;
|
||
case PROP_SECURITY:
|
||
g_value_set_enum (value, view->security);
|
||
break;
|
||
case PROP_MIME_TYPE:
|
||
g_value_set_string (value, view->mime_type);
|
||
break;
|
||
case PROP_ICON:
|
||
g_value_set_object (value, view->icon);
|
||
break;
|
||
case PROP_PROGRESS:
|
||
g_value_set_double (value, midori_view_get_progress (view));
|
||
break;
|
||
case PROP_LOAD_STATUS:
|
||
g_value_set_enum (value, midori_view_get_load_status (view));
|
||
break;
|
||
case PROP_MINIMIZED:
|
||
g_value_set_boolean (value, view->minimized);
|
||
break;
|
||
case PROP_ZOOM_LEVEL:
|
||
g_value_set_float (value, midori_view_get_zoom_level (view));
|
||
break;
|
||
case PROP_NEWS_FEEDS:
|
||
g_value_set_object (value, view->news_feeds);
|
||
break;
|
||
case PROP_STATUSBAR_TEXT:
|
||
g_value_set_string (value, view->statusbar_text);
|
||
break;
|
||
case PROP_SETTINGS:
|
||
g_value_set_object (value, view->settings);
|
||
break;
|
||
default:
|
||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||
break;
|
||
}
|
||
}
|
||
|
||
static gboolean
|
||
midori_view_focus_in_event (GtkWidget* widget,
|
||
GdkEventFocus* event)
|
||
{
|
||
/* Always propagate focus to the child web view */
|
||
gtk_widget_grab_focus (midori_view_get_web_view (MIDORI_VIEW (widget)));
|
||
return TRUE;
|
||
}
|
||
|
||
/**
|
||
* midori_view_new:
|
||
* @net: %NULL
|
||
*
|
||
* Creates a new view.
|
||
*
|
||
* Return value: a new #MidoriView
|
||
*
|
||
* Deprecated: 0.2.8: Use midori_view_new_with_title() instead.
|
||
**/
|
||
GtkWidget*
|
||
midori_view_new (KatzeNet* net)
|
||
{
|
||
return g_object_new (MIDORI_TYPE_VIEW, NULL);
|
||
}
|
||
|
||
static void
|
||
_midori_view_set_settings (MidoriView* view,
|
||
MidoriWebSettings* settings)
|
||
{
|
||
gboolean zoom_text_and_images, kinetic_scrolling;
|
||
|
||
if (view->settings)
|
||
g_signal_handlers_disconnect_by_func (view->settings,
|
||
midori_view_settings_notify_cb, view);
|
||
|
||
katze_object_assign (view->settings, settings);
|
||
if (!settings)
|
||
return;
|
||
|
||
g_object_ref (settings);
|
||
g_signal_connect (settings, "notify",
|
||
G_CALLBACK (midori_view_settings_notify_cb), view);
|
||
|
||
g_object_set (view->web_view, "settings", settings, NULL);
|
||
|
||
g_free (view->news_aggregator);
|
||
|
||
g_object_get (view->settings,
|
||
"news-aggregator", &view->news_aggregator,
|
||
"zoom-text-and-images", &zoom_text_and_images,
|
||
"kinetic-scrolling", &kinetic_scrolling,
|
||
"close-buttons-on-tabs", &view->close_buttons_on_tabs,
|
||
"open-new-pages-in", &view->open_new_pages_in,
|
||
"middle-click-opens-selection", &view->middle_click_opens_selection,
|
||
"open-tabs-in-the-background", &view->open_tabs_in_the_background,
|
||
NULL);
|
||
|
||
if (view->web_view)
|
||
g_object_set (view->web_view,
|
||
"full-content-zoom", zoom_text_and_images, NULL);
|
||
g_object_set (view->scrolled_window, "kinetic-scrolling", kinetic_scrolling, NULL);
|
||
}
|
||
|
||
/**
|
||
* midori_view_new_with_title:
|
||
* @uri: an URI string, or %NULL
|
||
* @title: a title, or %NULL
|
||
* @settings: a #MidoriWebSettings, or %NULL
|
||
* @append: if %TRUE, the view should be appended
|
||
*
|
||
* Creates a new view with the specified parameters that
|
||
* is visible by default.
|
||
*
|
||
* Return value: a new #MidoriView
|
||
*
|
||
* Since: 0.3.0
|
||
**/
|
||
GtkWidget*
|
||
midori_view_new_with_title (const gchar* title,
|
||
MidoriWebSettings* settings,
|
||
gboolean append)
|
||
{
|
||
MidoriView* view = g_object_new (MIDORI_TYPE_VIEW, "title", title, NULL);
|
||
if (settings)
|
||
_midori_view_set_settings (view, settings);
|
||
if (append)
|
||
g_object_set_data (G_OBJECT (view), "midori-view-append", (void*)1);
|
||
gtk_widget_show ((GtkWidget*)view);
|
||
return (GtkWidget*)view;
|
||
}
|
||
|
||
static void
|
||
midori_view_settings_notify_cb (MidoriWebSettings* settings,
|
||
GParamSpec* pspec,
|
||
MidoriView* view)
|
||
{
|
||
const gchar* name;
|
||
GValue value = { 0, };
|
||
|
||
name = g_intern_string (g_param_spec_get_name (pspec));
|
||
g_value_init (&value, pspec->value_type);
|
||
g_object_get_property (G_OBJECT (view->settings), name, &value);
|
||
|
||
if (name == g_intern_string ("news-aggregator"))
|
||
katze_assign (view->news_aggregator, g_value_dup_string (&value));
|
||
else if (name == g_intern_string ("zoom-text-and-images"))
|
||
{
|
||
if (view->web_view)
|
||
g_object_set (view->web_view, "full-content-zoom",
|
||
g_value_get_boolean (&value), NULL);
|
||
}
|
||
else if (name == g_intern_string ("kinetic-scrolling"))
|
||
{
|
||
g_object_set (view, "kinetic-scrolling",
|
||
g_value_get_boolean (&value), NULL);
|
||
}
|
||
else if (name == g_intern_string ("close-buttons-on-tabs"))
|
||
{
|
||
view->close_buttons_on_tabs = g_value_get_boolean (&value);
|
||
sokoke_widget_set_visible (view->tab_close,
|
||
view->close_buttons_on_tabs);
|
||
}
|
||
else if (name == g_intern_string ("open-new-pages-in"))
|
||
view->open_new_pages_in = g_value_get_enum (&value);
|
||
else if (name == g_intern_string ("middle-click-opens-selection"))
|
||
view->middle_click_opens_selection = g_value_get_boolean (&value);
|
||
else if (name == g_intern_string ("open-tabs-in-the-background"))
|
||
view->open_tabs_in_the_background = g_value_get_boolean (&value);
|
||
|
||
g_value_unset (&value);
|
||
}
|
||
|
||
/**
|
||
* midori_view_set_settings:
|
||
* @view: a #MidoriView
|
||
* @settings: a #MidoriWebSettings
|
||
*
|
||
* Assigns a settings instance to the view.
|
||
**/
|
||
void
|
||
midori_view_set_settings (MidoriView* view,
|
||
MidoriWebSettings* settings)
|
||
{
|
||
g_return_if_fail (MIDORI_IS_VIEW (view));
|
||
g_return_if_fail (MIDORI_IS_WEB_SETTINGS (settings));
|
||
|
||
if (view->settings == settings)
|
||
return;
|
||
|
||
_midori_view_set_settings (view, settings);
|
||
g_object_notify (G_OBJECT (view), "settings");
|
||
}
|
||
|
||
/**
|
||
* midori_view_load_status:
|
||
* @web_view: a #MidoriView
|
||
*
|
||
* Determines the current loading status of a view.
|
||
*
|
||
* Return value: the current #MidoriLoadStatus
|
||
**/
|
||
MidoriLoadStatus
|
||
midori_view_get_load_status (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), MIDORI_LOAD_FINISHED);
|
||
|
||
return view->load_status;
|
||
}
|
||
|
||
/**
|
||
* midori_view_get_progress:
|
||
* @view: a #MidoriView
|
||
*
|
||
* Retrieves the current loading progress as
|
||
* a fraction between 0.0 and 1.0.
|
||
*
|
||
* Return value: the current loading progress
|
||
**/
|
||
gdouble
|
||
midori_view_get_progress (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), 0.0);
|
||
|
||
return view->progress;
|
||
}
|
||
|
||
static void
|
||
midori_view_web_inspector_construct_window (gpointer inspector,
|
||
WebKitWebView* web_view,
|
||
GtkWidget* inspector_view,
|
||
MidoriView* view)
|
||
{
|
||
gchar* title;
|
||
gchar* label;
|
||
GtkWidget* window;
|
||
GtkWidget* toplevel;
|
||
GdkScreen* screen;
|
||
gint width, height;
|
||
GtkIconTheme* icon_theme;
|
||
GdkPixbuf* icon;
|
||
GdkPixbuf* gray_icon;
|
||
|
||
label = g_strdup (midori_view_get_display_title (view));
|
||
title = g_strdup_printf (_("Inspect page - %s"), label);
|
||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||
gtk_window_set_title (GTK_WINDOW (window), title);
|
||
g_free (title);
|
||
g_free (label);
|
||
|
||
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (view));
|
||
if (gtk_widget_is_toplevel (toplevel))
|
||
{
|
||
screen = gtk_window_get_screen (GTK_WINDOW (toplevel));
|
||
width = gdk_screen_get_width (screen) / 1.7;
|
||
height = gdk_screen_get_height (screen) / 1.7;
|
||
gtk_window_set_default_size (GTK_WINDOW (window), width, height);
|
||
}
|
||
|
||
/* Attempt to make a gray version of the icon on the fly */
|
||
icon_theme = gtk_icon_theme_get_for_screen (
|
||
gtk_widget_get_screen (GTK_WIDGET (view)));
|
||
icon = gtk_icon_theme_load_icon (icon_theme, "midori", 32,
|
||
GTK_ICON_LOOKUP_USE_BUILTIN, NULL);
|
||
if (icon)
|
||
{
|
||
gray_icon = gdk_pixbuf_copy (icon);
|
||
if (gray_icon)
|
||
{
|
||
gdk_pixbuf_saturate_and_pixelate (gray_icon, gray_icon, 0.1f, FALSE);
|
||
gtk_window_set_icon (GTK_WINDOW (window), gray_icon);
|
||
g_object_unref (gray_icon);
|
||
}
|
||
g_object_unref (icon);
|
||
}
|
||
else
|
||
gtk_window_set_icon_name (GTK_WINDOW (window), "midori");
|
||
gtk_container_add (GTK_CONTAINER (window), inspector_view);
|
||
gtk_widget_show_all (window);
|
||
|
||
/* FIXME: Update window title with URI */
|
||
}
|
||
|
||
static WebKitWebView*
|
||
midori_view_web_inspector_inspect_web_view_cb (gpointer inspector,
|
||
WebKitWebView* web_view,
|
||
MidoriView* view)
|
||
{
|
||
GtkWidget* inspector_view = webkit_web_view_new ();
|
||
#if HAVE_HILDON
|
||
gtk_widget_tap_and_hold_setup (view->web_view, NULL, NULL, 0);
|
||
g_signal_connect (view->web_view, "tap-and-hold",
|
||
G_CALLBACK (midori_view_web_view_tap_and_hold_cb), NULL);
|
||
#endif
|
||
midori_view_web_inspector_construct_window (inspector,
|
||
web_view, inspector_view, view);
|
||
return WEBKIT_WEB_VIEW (inspector_view);
|
||
}
|
||
|
||
static gboolean
|
||
midori_view_web_inspector_show_window_cb (WebKitWebInspector* inspector,
|
||
MidoriView* view)
|
||
{
|
||
WebKitWebView* inspector_view = webkit_web_inspector_get_web_view (inspector);
|
||
GtkWidget* window = gtk_widget_get_toplevel (GTK_WIDGET (inspector_view));
|
||
if (!window)
|
||
return FALSE;
|
||
gtk_window_present (GTK_WINDOW (window));
|
||
return TRUE;
|
||
}
|
||
|
||
static gboolean
|
||
midori_view_web_inspector_attach_window_cb (gpointer inspector,
|
||
MidoriView* view)
|
||
{
|
||
WebKitWebView* inspector_view = webkit_web_inspector_get_web_view (inspector);
|
||
g_signal_emit (view, signals[ATTACH_INSPECTOR], 0, inspector_view);
|
||
return TRUE;
|
||
}
|
||
|
||
static gboolean
|
||
midori_view_web_inspector_detach_window_cb (gpointer inspector,
|
||
MidoriView* view)
|
||
{
|
||
WebKitWebView* inspector_view = webkit_web_inspector_get_web_view (inspector);
|
||
GtkWidget* parent = gtk_widget_get_parent (GTK_WIDGET (inspector_view));
|
||
if (GTK_IS_WINDOW (parent))
|
||
return FALSE;
|
||
|
||
gtk_widget_hide (parent);
|
||
g_signal_emit (view, signals[DETACH_INSPECTOR], 0, inspector_view);
|
||
midori_view_web_inspector_construct_window (inspector,
|
||
WEBKIT_WEB_VIEW (view->web_view), GTK_WIDGET (inspector_view), view);
|
||
return TRUE;
|
||
}
|
||
|
||
static gboolean
|
||
midori_view_web_inspector_close_window_cb (gpointer inspector,
|
||
MidoriView* view)
|
||
{
|
||
WebKitWebView* inspector_view = webkit_web_inspector_get_web_view (inspector);
|
||
GtkWidget* scrolled = gtk_widget_get_parent (GTK_WIDGET (inspector_view));
|
||
if (!scrolled)
|
||
return FALSE;
|
||
gtk_widget_destroy (gtk_widget_get_parent (scrolled));
|
||
return TRUE;
|
||
}
|
||
|
||
static void
|
||
midori_view_construct_web_view (MidoriView* view)
|
||
{
|
||
WebKitWebFrame* web_frame;
|
||
gpointer inspector;
|
||
|
||
g_return_if_fail (!view->web_view);
|
||
|
||
view->web_view = webkit_web_view_new ();
|
||
|
||
/* Load something to avoid a bug where WebKit might not set a main frame */
|
||
webkit_web_view_open (WEBKIT_WEB_VIEW (view->web_view), "");
|
||
web_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (view->web_view));
|
||
|
||
#if HAVE_HILDON
|
||
gtk_widget_tap_and_hold_setup (view->web_view, NULL, NULL, 0);
|
||
g_signal_connect (view->web_view, "tap-and-hold",
|
||
G_CALLBACK (midori_view_web_view_tap_and_hold_cb), NULL);
|
||
#endif
|
||
|
||
g_object_connect (view->web_view,
|
||
"signal::navigation-policy-decision-requested",
|
||
midori_view_web_view_navigation_decision_cb, view,
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 14)
|
||
"signal::resource-request-starting",
|
||
midori_view_web_view_resource_request_cb, view,
|
||
#endif
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 14)
|
||
"signal::database-quota-exceeded",
|
||
midori_view_web_view_database_quota_exceeded_cb, view,
|
||
#endif
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 23)
|
||
"signal::geolocation-policy-decision-requested",
|
||
midori_view_web_view_geolocation_decision_cb, view,
|
||
#endif
|
||
"signal::load-started",
|
||
webkit_web_view_load_started_cb, view,
|
||
"signal::load-committed",
|
||
webkit_web_view_load_committed_cb, view,
|
||
"signal::load-progress-changed",
|
||
webkit_web_view_progress_changed_cb, view,
|
||
"signal::load-finished",
|
||
webkit_web_view_load_finished_cb, view,
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 18)
|
||
"signal::notify::icon-uri",
|
||
midori_web_view_notify_icon_uri_cb, view,
|
||
#endif
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 4)
|
||
"signal::notify::uri",
|
||
webkit_web_view_notify_uri_cb, view,
|
||
"signal::notify::title",
|
||
webkit_web_view_notify_title_cb, view,
|
||
#else
|
||
"signal::title-changed",
|
||
webkit_web_view_title_changed_cb, view,
|
||
#endif
|
||
"signal::status-bar-text-changed",
|
||
webkit_web_view_statusbar_text_changed_cb, view,
|
||
"signal::leave-notify-event",
|
||
midori_view_web_view_leave_notify_event_cb, view,
|
||
"signal::hovering-over-link",
|
||
webkit_web_view_hovering_over_link_cb, view,
|
||
"signal::button-press-event",
|
||
gtk_widget_button_press_event_cb, view,
|
||
"signal-after::key-press-event",
|
||
gtk_widget_key_press_event_cb, view,
|
||
"signal::scroll-event",
|
||
gtk_widget_scroll_event_cb, view,
|
||
"signal::populate-popup",
|
||
webkit_web_view_populate_popup_cb, view,
|
||
"signal::console-message",
|
||
webkit_web_view_console_message_cb, view,
|
||
"signal::script-alert",
|
||
midori_view_web_view_script_alert_cb, view,
|
||
"signal::window-object-cleared",
|
||
webkit_web_view_window_object_cleared_cb, view,
|
||
"signal::create-web-view",
|
||
webkit_web_view_create_web_view_cb, view,
|
||
"signal-after::mime-type-policy-decision-requested",
|
||
webkit_web_view_mime_type_decision_cb, view,
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 3)
|
||
"signal::download-requested",
|
||
webkit_web_view_download_requested_cb, view,
|
||
#endif
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 5)
|
||
"signal::print-requested",
|
||
midori_view_web_view_print_requested_cb, view,
|
||
#endif
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 6)
|
||
"signal-after::load-error",
|
||
webkit_web_view_load_error_cb, view,
|
||
#endif
|
||
NULL);
|
||
|
||
#if !WEBKIT_CHECK_VERSION (1, 1, 6)
|
||
g_object_connect (web_frame,
|
||
"signal::load-done",
|
||
webkit_web_frame_load_done_cb, view,
|
||
NULL);
|
||
#endif
|
||
|
||
if (view->settings)
|
||
{
|
||
g_object_set (view->web_view, "settings", view->settings,
|
||
"full-content-zoom", katze_object_get_boolean (view->settings,
|
||
"zoom-text-and-images"), NULL);
|
||
}
|
||
|
||
gtk_container_add (GTK_CONTAINER (view->scrolled_window), view->web_view);
|
||
gtk_widget_show_all (view->scrolled_window);
|
||
|
||
inspector = webkit_web_view_get_inspector ((WebKitWebView*)view->web_view);
|
||
g_object_connect (inspector,
|
||
"signal::inspect-web-view",
|
||
midori_view_web_inspector_inspect_web_view_cb, view,
|
||
"signal::show-window",
|
||
midori_view_web_inspector_show_window_cb, view,
|
||
"signal::attach-window",
|
||
midori_view_web_inspector_attach_window_cb, view,
|
||
"signal::detach-window",
|
||
midori_view_web_inspector_detach_window_cb, view,
|
||
"signal::close-window",
|
||
midori_view_web_inspector_close_window_cb, view,
|
||
NULL);
|
||
}
|
||
|
||
static gchar* list_netscape_plugins ()
|
||
{
|
||
GtkWidget* web_view = webkit_web_view_new ();
|
||
WebKitWebFrame* web_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (web_view));
|
||
JSContextRef js_context = webkit_web_frame_get_global_context (web_frame);
|
||
/* This snippet joins the available plugins into a string like this:
|
||
URI1|title1,URI2|title2 */
|
||
gchar* value = sokoke_js_script_eval (js_context,
|
||
"function plugins (l) { var f = new Array (); for (i in l) "
|
||
"{ var p = l[i].name + '|' + l[i].filename; "
|
||
"if (f.indexOf (p) == -1) f.push (p); } return f; }"
|
||
"plugins (navigator.plugins)", NULL);
|
||
gchar** items = g_strsplit (value, ",", 0);
|
||
guint i = 0;
|
||
GString* ns_plugins = g_string_new (NULL);
|
||
if (items != NULL)
|
||
while (items[i] != NULL)
|
||
{
|
||
gchar** parts = g_strsplit (items[i], "|", 2);
|
||
if (parts && *parts && !g_str_equal (parts[1], "undefined"))
|
||
{
|
||
g_string_append (ns_plugins, "<tr><td>");
|
||
g_string_append (ns_plugins, parts[1]);
|
||
g_string_append (ns_plugins, "</td><td>");
|
||
g_string_append (ns_plugins, parts[0]);
|
||
g_string_append (ns_plugins, "</tr>");
|
||
}
|
||
g_strfreev (parts);
|
||
i++;
|
||
}
|
||
if (g_str_has_prefix (value, "undefined"))
|
||
g_string_append (ns_plugins, "<tr><td>No plugins found</td></tr>");
|
||
g_strfreev (items);
|
||
g_free (value);
|
||
return g_string_free (ns_plugins, FALSE);
|
||
}
|
||
|
||
static gchar*
|
||
prepare_speed_dial_html (MidoriView* view)
|
||
{
|
||
MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (view));
|
||
GKeyFile* key_file;
|
||
GString* markup = g_string_new (NULL);
|
||
guint rows, cols, slot = 1;
|
||
gchar* thumb_size_type;
|
||
guint thumb_size = 160;
|
||
|
||
g_object_get (browser, "speed-dial", &key_file, NULL);
|
||
if (!key_file)
|
||
return g_string_free (markup, FALSE);
|
||
rows = g_key_file_get_integer (key_file, "settings", "rows", NULL);
|
||
cols = g_key_file_get_integer (key_file, "settings", "columns", NULL);
|
||
thumb_size_type = g_key_file_get_string (key_file, "settings", "size", NULL);
|
||
if (thumb_size_type == NULL)
|
||
thumb_size_type = g_strdup ("MEDIUM");
|
||
|
||
if (g_str_equal (thumb_size_type, "SMALL"))
|
||
thumb_size = 80;
|
||
else if (g_str_equal (thumb_size_type, "MEDIUM"))
|
||
thumb_size = 160;
|
||
else if (g_str_equal (thumb_size_type, "BIG"))
|
||
thumb_size = 240;
|
||
|
||
g_free (thumb_size_type);
|
||
|
||
g_string_append_printf (markup,
|
||
"<script>var columns = %d; var rows = %d;"
|
||
"setThumbSize(%d);</script>\n",
|
||
cols, rows, thumb_size);
|
||
|
||
while (slot <= rows * cols)
|
||
{
|
||
gchar* position;
|
||
gchar* dial_entry = g_strdup_printf ("Dial %d", slot);
|
||
if (slot < cols)
|
||
position = g_strdup (" top");
|
||
else if (slot == cols)
|
||
position = g_strdup (" top right");
|
||
else if (slot > cols && slot % cols == 0)
|
||
position = g_strdup (" right");
|
||
else
|
||
position = g_strdup ("");
|
||
|
||
if (g_key_file_has_group (key_file, dial_entry))
|
||
{
|
||
gchar* slot_id = g_strdup_printf ("s%d", slot);
|
||
gchar* uri = g_key_file_get_string (key_file, dial_entry, "uri", NULL);
|
||
gchar* title = g_key_file_get_string (key_file, dial_entry, "title", NULL);
|
||
gchar* thumb_file = sokoke_build_thumbnail_path (uri);
|
||
gchar* encoded;
|
||
|
||
if (g_access (thumb_file, F_OK) == 0)
|
||
{
|
||
gsize sz;
|
||
gchar* thumb_content;
|
||
g_file_get_contents (thumb_file, &thumb_content, &sz, NULL);
|
||
encoded = g_base64_encode ((guchar*)thumb_content, sz);
|
||
g_free (thumb_content);
|
||
}
|
||
else
|
||
{
|
||
encoded = g_strdup ("");
|
||
}
|
||
g_free (slot_id);
|
||
g_free (thumb_file);
|
||
|
||
g_string_append_printf (markup,
|
||
"<div class=\"shortcut%s activated\" id=\"s%d\">\n"
|
||
"<div onclick='javascript:clearShortcut(\"s%d\");' "
|
||
"class='cross'></div>\n<a href=\"%s\">"
|
||
"<img src=\"data:image/png;base64,%s\"></a>\n"
|
||
"<p onclick='javascript:renameShortcut(\"s%d\");'>"
|
||
"%s</p></div>\n",
|
||
position, slot, slot, uri, encoded, slot, title);
|
||
|
||
g_free (uri);
|
||
g_free (title);
|
||
g_free (encoded);
|
||
}
|
||
else
|
||
{
|
||
g_string_append_printf (markup,
|
||
"<div class=\"shortcut%s\" id=\"s%d\">"
|
||
"\n<a href=\"#\" onclick='javascript:return"
|
||
" getAction(\"s%d\");'>"
|
||
"<h1>%d</h1>\n<h4><span></span></h4>"
|
||
"</a>\n<p></p></div>\n",
|
||
position, slot, slot, slot);
|
||
}
|
||
|
||
slot++;
|
||
g_free (position);
|
||
g_free (dial_entry);
|
||
}
|
||
g_string_append_printf (markup,
|
||
"</div>\n</div>\n</body>\n</html>\n");
|
||
|
||
return g_string_free (markup, FALSE);
|
||
}
|
||
|
||
|
||
/**
|
||
* midori_view_set_uri:
|
||
* @view: a #MidoriView
|
||
*
|
||
* Opens the specified URI in the view.
|
||
*
|
||
* Since 0.3.0 a warning is shown if the view is not yet
|
||
* contained in a browser. This is because extensions
|
||
* can't monitor page loading if that happens.
|
||
**/
|
||
void
|
||
midori_view_set_uri (MidoriView* view,
|
||
const gchar* uri)
|
||
{
|
||
gchar* data;
|
||
|
||
g_return_if_fail (MIDORI_IS_VIEW (view));
|
||
|
||
if (!gtk_widget_get_parent (GTK_WIDGET (view)))
|
||
g_warning ("Calling %s() before adding the view to a browser. This "
|
||
"breaks extensions that monitor page loading.", G_STRFUNC);
|
||
|
||
/* Treat "about:blank" and "" equally, see midori_view_is_blank(). */
|
||
if (!uri || !strcmp (uri, "about:blank")) uri = "";
|
||
|
||
if (g_getenv ("MIDORI_UNARMED") == NULL)
|
||
{
|
||
if (!strcmp (uri, ""))
|
||
{
|
||
#if !WEBKIT_CHECK_VERSION (1, 1, 14)
|
||
SoupServer* res_server;
|
||
guint port;
|
||
#endif
|
||
gchar* res_root;
|
||
gchar* speed_dial_head;
|
||
gchar* speed_dial_body;
|
||
gchar* speed_dial_markup;
|
||
gchar* stock_root;
|
||
gchar* filepath;
|
||
#ifdef G_ENABLE_DEBUG
|
||
GTimer* timer = NULL;
|
||
|
||
if (g_getenv ("MIDORI_STARTTIME") != NULL)
|
||
timer = g_timer_new ();
|
||
#endif
|
||
|
||
katze_assign (view->uri, g_strdup (""));
|
||
katze_item_set_uri (view->item, "");
|
||
|
||
filepath = sokoke_find_data_filename ("midori/res/speeddial-head.html");
|
||
g_file_get_contents (filepath, &speed_dial_head, NULL, NULL);
|
||
g_free (filepath);
|
||
if (G_UNLIKELY (!speed_dial_head))
|
||
speed_dial_head = g_strdup ("");
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 14)
|
||
res_root = g_strdup ("res:/");
|
||
stock_root = g_strdup ("stock:/");
|
||
#else
|
||
res_server = sokoke_get_res_server ();
|
||
port = soup_server_get_port (res_server);
|
||
res_root = g_strdup_printf ("http://localhost:%d/res", port);
|
||
stock_root = g_strdup_printf ("http://localhost:%d/stock", port);
|
||
#endif
|
||
|
||
data = sokoke_replace_variables (speed_dial_head,
|
||
"{res}", res_root,
|
||
"{stock}", stock_root,
|
||
"{title}", _("Speed Dial"),
|
||
"{click_to_add}", _("Click to add a shortcut"),
|
||
"{enter_shortcut_address}", _("Enter shortcut address"),
|
||
"{enter_shortcut_name}", _("Enter shortcut title"),
|
||
"{are_you_sure}", _("Are you sure you want to delete this shortcut?"),
|
||
"{set_dial_size}", _("Set number of columns and rows"),
|
||
"{enter_dial_size}", _("Enter number of columns and rows:"),
|
||
"{invalid_dial_size}", _("Invalid input for the size of the speed dial"),
|
||
"{set_thumb_size}", _("Thumb size:"),
|
||
"{set_thumb_small}", _("Small"),
|
||
"{set_thumb_normal}", _("Medium"),
|
||
"{set_thumb_big}", _("Big"), NULL);
|
||
|
||
#ifdef G_ENABLE_DEBUG
|
||
if (g_getenv ("MIDORI_STARTTIME") != NULL)
|
||
{
|
||
g_debug ("Speed Dial: \t%fs", g_timer_elapsed (timer, NULL));
|
||
g_timer_destroy (timer);
|
||
}
|
||
#endif
|
||
|
||
speed_dial_body = prepare_speed_dial_html (view);
|
||
speed_dial_markup = g_strdup_printf ("%s\n%s", data, speed_dial_body);
|
||
|
||
midori_view_load_alternate_string (view,
|
||
speed_dial_markup, res_root, "about:blank", NULL);
|
||
|
||
g_free (res_root);
|
||
g_free (stock_root);
|
||
g_free (data);
|
||
g_free (speed_dial_head);
|
||
g_free (speed_dial_body);
|
||
g_free (speed_dial_markup);
|
||
}
|
||
/* This is not prefectly elegant, but creating
|
||
special pages inline is the simplest solution. */
|
||
else if (g_str_has_prefix (uri, "error:") || g_str_has_prefix (uri, "about:"))
|
||
{
|
||
data = NULL;
|
||
#if !WEBKIT_CHECK_VERSION (1, 1, 3)
|
||
if (!strncmp (uri, "error:nodisplay ", 16))
|
||
{
|
||
gchar* title;
|
||
gchar* logo_path;
|
||
gchar* logo_uri;
|
||
|
||
katze_assign (view->uri, g_strdup (&uri[16]));
|
||
title = g_strdup_printf (_("Document cannot be displayed"));
|
||
logo_path = sokoke_find_data_filename ("midori/logo-shade.png");
|
||
logo_uri = g_filename_to_uri (logo_path, NULL, NULL);
|
||
g_free (logo_path);
|
||
data = g_strdup_printf (
|
||
"<html><head><title>%s</title></head>"
|
||
"<body><h1>%s</h1>"
|
||
"<img src=\"%s\" "
|
||
"style=\"position: absolute; right: 15px; bottom: 15px; z-index: -9;\">"
|
||
"<p />The document %s of type '%s' cannot be displayed."
|
||
"</body></html>",
|
||
title, title, logo_uri, view->uri, view->mime_type);
|
||
g_free (title);
|
||
g_free (logo_uri);
|
||
}
|
||
#endif
|
||
if (!strncmp (uri, "error:nodocs ", 13))
|
||
{
|
||
gchar* title;
|
||
gchar* logo_path;
|
||
gchar* logo_uri;
|
||
|
||
katze_assign (view->uri, g_strdup (&uri[13]));
|
||
title = g_strdup_printf (_("No documentation installed"));
|
||
logo_path = sokoke_find_data_filename ("midori/logo-shade.png");
|
||
logo_uri = g_filename_to_uri (logo_path, NULL, NULL);
|
||
g_free (logo_path);
|
||
data = g_strdup_printf (
|
||
"<html><head><title>%s</title></head>"
|
||
"<body><h1>%s</h1>"
|
||
"<img src=\"%s\" "
|
||
"style=\"position: absolute; right: 15px; bottom: 15px; z-index: -9;\">"
|
||
"<p />There is no documentation installed at %s."
|
||
"You may want to ask your distribution or "
|
||
"package maintainer for it or if this a custom build "
|
||
"verify that the build is setup properly."
|
||
"</body></html>",
|
||
title, title, logo_uri, view->uri);
|
||
g_free (title);
|
||
g_free (logo_uri);
|
||
}
|
||
else if (!strcmp (uri, "about:") || !strcmp (uri, "about:version"))
|
||
{
|
||
gchar** argument_vector = sokoke_get_argv (NULL);
|
||
gchar* command_line = g_strjoinv (" ", argument_vector);
|
||
gchar* ident = katze_object_get_string (view->settings, "user-agent");
|
||
gchar* netscape_plugins = list_netscape_plugins ();
|
||
#if defined (G_OS_WIN32)
|
||
gchar* sys_name = g_strdup ("Windows");
|
||
#else
|
||
gchar* sys_name;
|
||
struct utsname name;
|
||
if (uname (&name) != -1)
|
||
sys_name = g_strdup_printf ("%s %s", name.sysname, name.machine);
|
||
else
|
||
sys_name = g_strdup ("Unix");
|
||
#endif
|
||
|
||
katze_assign (view->uri, g_strdup (uri));
|
||
#ifndef WEBKIT_USER_AGENT_MAJOR_VERSION
|
||
#define WEBKIT_USER_AGENT_MAJOR_VERSION 532
|
||
#define WEBKIT_USER_AGENT_MINOR_VERSION 1
|
||
#endif
|
||
#if defined (HAVE_LIBSOUP_2_29_3)
|
||
#define LIBSOUP_VERSION "2.29.3"
|
||
#elif defined (HAVE_LIBSOUP_2_27_90)
|
||
#define LIBSOUP_VERSION "2.27.90"
|
||
#else
|
||
#define LIBSOUP_VERSION "2.25.2"
|
||
#endif
|
||
#ifdef G_ENABLE_DEBUG
|
||
#define DEBUGGING " (Debug)"
|
||
#else
|
||
#define DEBUGGING ""
|
||
#endif
|
||
data = g_strdup_printf (
|
||
"<html><head><title>about:version</title></head>"
|
||
"<body><h1>about:version</h1>"
|
||
"<p>%s</p>"
|
||
"<img src=\"res://logo-shade.png\" "
|
||
"style=\"position: absolute; right: 15px; bottom: 15px; z-index: -9;\">"
|
||
"<table>"
|
||
"<tr><td>Command line</td><td>%s</td></tr>"
|
||
"<tr><td>Midori</td><td>" PACKAGE_VERSION "%s</td></tr>"
|
||
"<tr><td>WebKitGTK+</td><td>%d.%d.%d (%d.%d.%d)</td></tr>"
|
||
"<tr><td>GTK+</td><td>%d.%d.%d (%d.%d.%d)</td></tr>"
|
||
"<tr><td>Glib</td><td>%d.%d.%d (%d.%d.%d)</td></tr>"
|
||
"<tr><td>libsoup</td><td>%s</td></tr>"
|
||
"<tr><td>libnotify</td><td>%s</td></tr>"
|
||
"<tr><td>libidn</td><td>%s</td></tr>"
|
||
"<tr><td>libunique</td><td>%s</td></tr>"
|
||
"<tr><td>libhildon</td><td>%s</td></tr>"
|
||
"<tr><td>Platform</td><td>%s</td></tr>"
|
||
"<tr><td>Identification</td><td>%s</td></tr>"
|
||
"</table>"
|
||
"<h2>Netscape Plugins:</h2><table>%s</table>"
|
||
"</body></html>",
|
||
_("Version numbers in brackets show the version used at runtime."),
|
||
command_line,
|
||
DEBUGGING,
|
||
WEBKIT_MAJOR_VERSION,
|
||
WEBKIT_MINOR_VERSION,
|
||
WEBKIT_MICRO_VERSION,
|
||
webkit_major_version (),
|
||
webkit_minor_version (),
|
||
webkit_micro_version (),
|
||
GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION,
|
||
gtk_major_version, gtk_minor_version, gtk_micro_version,
|
||
GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION,
|
||
glib_major_version, glib_minor_version, glib_micro_version,
|
||
LIBSOUP_VERSION,
|
||
HAVE_LIBNOTIFY ? "Yes" : "No",
|
||
HAVE_LIBIDN ? "Yes" : "No",
|
||
HAVE_UNIQUE ? "Yes" : "No",
|
||
HAVE_HILDON ? "Yes" : "No",
|
||
sys_name, ident,
|
||
netscape_plugins);
|
||
g_free (command_line);
|
||
g_free (ident);
|
||
g_free (sys_name);
|
||
g_free (netscape_plugins);
|
||
}
|
||
else
|
||
{
|
||
katze_assign (view->uri, g_strdup (uri));
|
||
data = g_strdup_printf (
|
||
"<html><head><title>%s</title></head><body><h1>%s</h1>"
|
||
"<img src=\"file://" MDATADIR "/midori/logo-shade.png\" "
|
||
"style=\"position: absolute; right: 15px; bottom: 15px; z-index: -9;\">"
|
||
"</body></html>", view->uri, view->uri);
|
||
}
|
||
|
||
webkit_web_view_load_html_string (
|
||
WEBKIT_WEB_VIEW (view->web_view), data, view->uri);
|
||
g_free (data);
|
||
katze_item_set_uri (view->item, uri);
|
||
g_object_notify (G_OBJECT (view), "uri");
|
||
return;
|
||
}
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 6)
|
||
else if (g_str_has_prefix (uri, "pause:"))
|
||
{
|
||
katze_assign (view->uri, g_strdup (&uri[6]));
|
||
midori_view_display_error (
|
||
view, view->uri, view->title,
|
||
_("Page loading delayed"),
|
||
_("Loading delayed either due to a recent crash or startup preferences."),
|
||
_("Load Page"),
|
||
NULL);
|
||
katze_item_set_uri (view->item, uri);
|
||
g_object_notify (G_OBJECT (view), "uri");
|
||
}
|
||
#endif
|
||
else if (g_str_has_prefix (uri, "javascript:"))
|
||
{
|
||
gboolean result;
|
||
gchar* exception;
|
||
|
||
result = midori_view_execute_script (view, &uri[11], &exception);
|
||
if (!result)
|
||
{
|
||
sokoke_message_dialog (GTK_MESSAGE_ERROR, "javascript:",
|
||
exception, FALSE);
|
||
g_free (exception);
|
||
}
|
||
}
|
||
else if (g_str_has_prefix (uri, "mailto:") || sokoke_external_uri (uri))
|
||
{
|
||
sokoke_show_uri (NULL, uri, GDK_CURRENT_TIME, NULL);
|
||
}
|
||
else
|
||
{
|
||
katze_assign (view->uri, sokoke_format_uri_for_display (uri));
|
||
katze_item_set_uri (view->item, uri);
|
||
katze_item_set_meta_integer (view->item, "delay", -1);
|
||
g_object_notify (G_OBJECT (view), "uri");
|
||
webkit_web_view_open (WEBKIT_WEB_VIEW (view->web_view), uri);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* midori_view_is_blank:
|
||
* @view: a #MidoriView
|
||
*
|
||
* Determines whether the view is currently empty.
|
||
**/
|
||
gboolean
|
||
midori_view_is_blank (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), TRUE);
|
||
|
||
return midori_view_get_display_uri (view)[0] == '\0';
|
||
}
|
||
|
||
/**
|
||
* midori_view_get_icon:
|
||
* @view: a #MidoriView
|
||
*
|
||
* Retrieves the icon of the view, or a default icon. See
|
||
* midori_view_get_icon_uri() if you need to distinguish
|
||
* the origin of an icon.
|
||
*
|
||
* The returned icon is owned by the @view and must not be modified.
|
||
*
|
||
* Return value: a #GdkPixbuf, or %NULL
|
||
**/
|
||
GdkPixbuf*
|
||
midori_view_get_icon (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL);
|
||
|
||
return view->icon;
|
||
}
|
||
|
||
/**
|
||
* midori_view_get_icon_uri:
|
||
* @view: a #MidoriView
|
||
*
|
||
* Retrieves the address of the icon of the view
|
||
* if the loaded website has an icon, otherwise
|
||
* %NULL.
|
||
* Note that if there is no icon uri, midori_view_get_icon()
|
||
* will still return a default icon.
|
||
*
|
||
* The returned string is owned by the @view and must not be freed.
|
||
*
|
||
* Return value: a string, or %NULL
|
||
*
|
||
* Since: 0.2.5
|
||
**/
|
||
const gchar*
|
||
midori_view_get_icon_uri (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL);
|
||
|
||
return view->icon_uri;
|
||
}
|
||
|
||
/**
|
||
* midori_view_get_display_uri:
|
||
* @view: a #MidoriView
|
||
*
|
||
* Retrieves a string that is suitable for displaying.
|
||
*
|
||
* Note that "about:blank" is represented as "".
|
||
*
|
||
* You can assume that the string is not %NULL.
|
||
*
|
||
* Return value: an URI string
|
||
**/
|
||
const gchar*
|
||
midori_view_get_display_uri (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), "");
|
||
|
||
/* Something in the stack tends to turn "" into "about:blank".
|
||
Yet for practical purposes we prefer "". */
|
||
if (view->uri && !strcmp (view->uri, "about:blank"))
|
||
return "";
|
||
|
||
if (view->uri && *view->uri)
|
||
return view->uri;
|
||
return "";
|
||
}
|
||
|
||
/**
|
||
* midori_view_get_display_title:
|
||
* @view: a #MidoriView
|
||
*
|
||
* Retrieves a string that is suitable for displaying
|
||
* as a title. Most of the time this will be the title
|
||
* or the current URI.
|
||
*
|
||
* An empty page is represented as "about:blank".
|
||
*
|
||
* You can assume that the string is not %NULL.
|
||
*
|
||
* Return value: a title string
|
||
**/
|
||
const gchar*
|
||
midori_view_get_display_title (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), "about:blank");
|
||
|
||
if (view->title && *view->title)
|
||
return view->title;
|
||
if (midori_view_is_blank (view))
|
||
return _("Blank page");
|
||
return midori_view_get_display_uri (view);
|
||
}
|
||
|
||
/**
|
||
* midori_view_get_link_uri:
|
||
* @view: a #MidoriView
|
||
*
|
||
* Retrieves the uri of the currently focused link,
|
||
* particularly while the mouse hovers a link or a
|
||
* context menu is being opened.
|
||
*
|
||
* Return value: an URI string, or %NULL if there is no link focussed
|
||
**/
|
||
const gchar*
|
||
midori_view_get_link_uri (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL);
|
||
|
||
return view->link_uri;
|
||
}
|
||
|
||
/**
|
||
* midori_view_has_selection:
|
||
* @view: a #MidoriView
|
||
*
|
||
* Determines whether something in the view is selected.
|
||
*
|
||
* This function returns %FALSE if there is a selection
|
||
* that effectively only consists of whitespace.
|
||
*
|
||
* Return value: %TRUE if effectively there is a selection
|
||
**/
|
||
gboolean
|
||
midori_view_has_selection (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), FALSE);
|
||
|
||
katze_assign (view->selected_text, webkit_web_view_get_selected_text (
|
||
WEBKIT_WEB_VIEW (view->web_view)));
|
||
if (view->selected_text && *view->selected_text)
|
||
return TRUE;
|
||
else
|
||
return FALSE;
|
||
}
|
||
|
||
/**
|
||
* midori_view_get_selected_text:
|
||
* @view: a #MidoriView
|
||
*
|
||
* Retrieves the currently selected text.
|
||
*
|
||
* Return value: the selected text, or %NULL
|
||
**/
|
||
const gchar*
|
||
midori_view_get_selected_text (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL);
|
||
|
||
if (midori_view_has_selection (view))
|
||
return view->selected_text;
|
||
return NULL;
|
||
}
|
||
|
||
/**
|
||
* midori_view_can_cut_clipboard:
|
||
* @view: a #MidoriView
|
||
*
|
||
* Determines whether a selection can be cut.
|
||
*
|
||
* Return value: %TRUE if a selection can be cut
|
||
**/
|
||
gboolean
|
||
midori_view_can_cut_clipboard (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), FALSE);
|
||
|
||
if (view->web_view)
|
||
return webkit_web_view_can_cut_clipboard (
|
||
WEBKIT_WEB_VIEW (view->web_view));
|
||
else
|
||
return FALSE;
|
||
}
|
||
|
||
/**
|
||
* midori_view_can_copy_clipboard:
|
||
* @view: a #MidoriView
|
||
*
|
||
* Determines whether a selection can be copied.
|
||
*
|
||
* Return value: %TRUE if a selection can be copied
|
||
**/
|
||
gboolean
|
||
midori_view_can_copy_clipboard (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), FALSE);
|
||
|
||
if (view->web_view)
|
||
return webkit_web_view_can_copy_clipboard (
|
||
WEBKIT_WEB_VIEW (view->web_view));
|
||
else
|
||
return FALSE;
|
||
}
|
||
|
||
/**
|
||
* midori_view_can_paste_clipboard:
|
||
* @view: a #MidoriView
|
||
*
|
||
* Determines whether a selection can be pasted.
|
||
*
|
||
* Return value: %TRUE if a selection can be pasted
|
||
**/
|
||
gboolean
|
||
midori_view_can_paste_clipboard (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), FALSE);
|
||
|
||
if (view->web_view)
|
||
return webkit_web_view_can_paste_clipboard (
|
||
WEBKIT_WEB_VIEW (view->web_view));
|
||
else
|
||
return FALSE;
|
||
}
|
||
|
||
/**
|
||
* midori_view_get_proxy_menu_item:
|
||
* @view: a #MidoriView
|
||
*
|
||
* Retrieves a proxy menu item that is typically added to a Window menu
|
||
* and which on activation switches to the right window/ tab.
|
||
*
|
||
* The item is created on the first call and will be updated to reflect
|
||
* changes to the icon and title automatically.
|
||
*
|
||
* The menu item is valid until it is removed from its container.
|
||
*
|
||
* Return value: the proxy #GtkMenuItem
|
||
**/
|
||
GtkWidget*
|
||
midori_view_get_proxy_menu_item (MidoriView* view)
|
||
{
|
||
const gchar* title;
|
||
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL);
|
||
|
||
if (!view->menu_item)
|
||
{
|
||
title = midori_view_get_display_title (view);
|
||
view->menu_item = katze_image_menu_item_new_ellipsized (title);
|
||
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (view->menu_item),
|
||
gtk_image_new_from_pixbuf (view->icon));
|
||
|
||
g_signal_connect (view->menu_item, "destroy",
|
||
G_CALLBACK (gtk_widget_destroyed),
|
||
&view->menu_item);
|
||
}
|
||
return view->menu_item;
|
||
}
|
||
|
||
static void
|
||
midori_view_tab_label_menu_open_cb (GtkWidget* menuitem,
|
||
GtkWidget* view)
|
||
{
|
||
MidoriBrowser* browser = midori_browser_get_for_widget (view);
|
||
midori_browser_set_current_tab (browser, view);
|
||
}
|
||
|
||
static void
|
||
midori_view_tab_label_menu_duplicate_tab_cb (GtkWidget* menuitem,
|
||
MidoriView* view)
|
||
{
|
||
MidoriNewView where = MIDORI_NEW_VIEW_TAB;
|
||
GtkWidget* new_view = midori_view_new_with_title (
|
||
NULL, view->settings, FALSE);
|
||
const gchar* uri = midori_view_get_display_uri (MIDORI_VIEW (view));
|
||
g_signal_emit (view, signals[NEW_VIEW], 0, new_view, where);
|
||
midori_view_set_uri (MIDORI_VIEW (new_view), uri);
|
||
}
|
||
|
||
static void
|
||
midori_view_browser_close_tabs_cb (GtkWidget* view,
|
||
gpointer data)
|
||
{
|
||
GtkWidget* remaining_view = data;
|
||
if (view != remaining_view)
|
||
gtk_widget_destroy (view);
|
||
}
|
||
|
||
static void
|
||
midori_view_tab_label_menu_close_other_tabs_cb (GtkWidget* menuitem,
|
||
GtkWidget* view)
|
||
{
|
||
MidoriBrowser* browser = midori_browser_get_for_widget (view);
|
||
midori_browser_foreach (browser, midori_view_browser_close_tabs_cb, view);
|
||
}
|
||
|
||
static void
|
||
midori_view_tab_label_menu_minimize_tab_cb (GtkWidget* menuitem,
|
||
MidoriView* view)
|
||
{
|
||
g_object_set (view, "minimized", !view->minimized, NULL);
|
||
}
|
||
|
||
static void
|
||
midori_view_tab_label_menu_close_cb (GtkWidget* menuitem,
|
||
GtkWidget* view)
|
||
{
|
||
gtk_widget_destroy (view);
|
||
}
|
||
|
||
/**
|
||
* midori_view_get_tab_menu:
|
||
* @view: a #MidoriView
|
||
*
|
||
* Retrieves a menu that is typically shown when right-clicking
|
||
* a tab label or equivalent representation.
|
||
*
|
||
* Return value: a #GtkMenu
|
||
*
|
||
* Since: 0.1.8
|
||
**/
|
||
GtkWidget*
|
||
midori_view_get_tab_menu (MidoriView* view)
|
||
{
|
||
MidoriBrowser* browser;
|
||
GtkActionGroup* actions;
|
||
GtkWidget* menu;
|
||
GtkWidget* menuitem;
|
||
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL);
|
||
|
||
browser = midori_browser_get_for_widget (GTK_WIDGET (view));
|
||
actions = midori_browser_get_action_group (browser);
|
||
|
||
menu = gtk_menu_new ();
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "TabNew"));
|
||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||
menuitem = sokoke_action_create_popup_menu_item (
|
||
gtk_action_group_get_action (actions, "UndoTabClose"));
|
||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||
menuitem = gtk_separator_menu_item_new ();
|
||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||
menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_OPEN, NULL);
|
||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||
g_signal_connect (menuitem, "activate",
|
||
G_CALLBACK (midori_view_tab_label_menu_open_cb), view);
|
||
menuitem = gtk_image_menu_item_new_from_stock (STOCK_WINDOW_NEW, NULL);
|
||
gtk_menu_item_set_label (GTK_MENU_ITEM (menuitem), _("Open in New _Window"));
|
||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||
g_signal_connect (menuitem, "activate",
|
||
G_CALLBACK (midori_view_tab_label_menu_window_new_cb), view);
|
||
menuitem = gtk_menu_item_new_with_mnemonic (_("_Duplicate Tab"));
|
||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||
g_signal_connect (menuitem, "activate",
|
||
G_CALLBACK (midori_view_tab_label_menu_duplicate_tab_cb), view);
|
||
menuitem = gtk_menu_item_new_with_mnemonic (
|
||
view->minimized ? _("Show Tab _Label") : _("Show Tab _Icon Only"));
|
||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||
g_signal_connect (menuitem, "activate",
|
||
G_CALLBACK (midori_view_tab_label_menu_minimize_tab_cb), view);
|
||
menuitem = gtk_separator_menu_item_new ();
|
||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||
menuitem = gtk_menu_item_new_with_mnemonic (_("Close ot_her Tabs"));
|
||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||
g_signal_connect (menuitem, "activate",
|
||
G_CALLBACK (midori_view_tab_label_menu_close_other_tabs_cb), view);
|
||
menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_CLOSE, NULL);
|
||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||
g_signal_connect (menuitem, "activate",
|
||
G_CALLBACK (midori_view_tab_label_menu_close_cb), view);
|
||
gtk_widget_show_all (menu);
|
||
|
||
return menu;
|
||
}
|
||
|
||
static gboolean
|
||
midori_view_tab_label_button_press_event (GtkWidget* tab_label,
|
||
GdkEventButton* event,
|
||
GtkWidget* widget)
|
||
{
|
||
if (event->button == 2)
|
||
{
|
||
/* Close the widget on middle click */
|
||
gtk_widget_destroy (widget);
|
||
return TRUE;
|
||
}
|
||
else if (event->button == 3)
|
||
{
|
||
/* Show a context menu on right click */
|
||
GtkWidget* menu = midori_view_get_tab_menu (MIDORI_VIEW (widget));
|
||
|
||
katze_widget_popup (widget, GTK_MENU (menu),
|
||
event, KATZE_MENU_POSITION_CURSOR);
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
static void
|
||
midori_view_tab_close_clicked (GtkWidget* tab_close,
|
||
GtkWidget* widget)
|
||
{
|
||
gtk_widget_destroy (widget);
|
||
}
|
||
|
||
static void
|
||
midori_view_tab_icon_style_set_cb (GtkWidget* tab_close,
|
||
GtkStyle* previous_style)
|
||
{
|
||
GtkRequisition size;
|
||
gtk_widget_size_request (gtk_bin_get_child (GTK_BIN (tab_close)), &size);
|
||
gtk_widget_set_size_request (tab_close, size.width, size.height);
|
||
}
|
||
|
||
static void
|
||
midori_view_update_tab_title (GtkWidget* label,
|
||
gint size,
|
||
gdouble angle)
|
||
{
|
||
if (angle == 0.0 || angle == 360.0)
|
||
{
|
||
if (gtk_label_get_ellipsize (GTK_LABEL (label)) != PANGO_ELLIPSIZE_START)
|
||
gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
|
||
}
|
||
else
|
||
{
|
||
gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_NONE);
|
||
}
|
||
gtk_label_set_angle (GTK_LABEL (label), angle);
|
||
}
|
||
|
||
static void
|
||
gtk_box_repack (GtkBox* box,
|
||
GtkWidget* child)
|
||
{
|
||
GtkWidget* old_box;
|
||
gboolean expand, fill;
|
||
guint padding;
|
||
GtkPackType pack_type;
|
||
|
||
old_box = gtk_widget_get_parent (child);
|
||
g_return_if_fail (GTK_IS_BOX (old_box));
|
||
|
||
gtk_box_query_child_packing (GTK_BOX (old_box), child,
|
||
&expand, &fill, &padding, &pack_type);
|
||
|
||
g_object_ref (child);
|
||
gtk_container_remove (GTK_CONTAINER (old_box), child);
|
||
if (pack_type == GTK_PACK_START)
|
||
gtk_box_pack_start (box, child, expand, fill, padding);
|
||
else
|
||
gtk_box_pack_end (box, child, expand, fill, padding);
|
||
g_object_unref (child);
|
||
}
|
||
|
||
static void
|
||
midori_view_tab_label_parent_set (GtkWidget* tab_label,
|
||
GtkObject* old_parent,
|
||
MidoriView* view)
|
||
{
|
||
GtkWidget* parent;
|
||
|
||
/* FIXME: Disconnect orientation notification
|
||
if (old_parent)
|
||
; */
|
||
|
||
if (!(parent = gtk_widget_get_parent (tab_label)))
|
||
return;
|
||
|
||
if (GTK_IS_NOTEBOOK (parent))
|
||
{
|
||
GtkPositionType pos;
|
||
gdouble old_angle, angle;
|
||
GtkWidget* box;
|
||
|
||
pos = gtk_notebook_get_tab_pos (GTK_NOTEBOOK (parent));
|
||
old_angle = gtk_label_get_angle (GTK_LABEL (view->tab_title));
|
||
switch (pos)
|
||
{
|
||
case GTK_POS_LEFT:
|
||
angle = 90.0;
|
||
break;
|
||
case GTK_POS_RIGHT:
|
||
angle = 270.0;
|
||
break;
|
||
default:
|
||
angle = 0.0;
|
||
}
|
||
|
||
if (old_angle != angle)
|
||
{
|
||
if (angle == 0.0)
|
||
box = gtk_hbox_new (FALSE, 1);
|
||
else
|
||
box = gtk_vbox_new (FALSE, 1);
|
||
gtk_box_repack (GTK_BOX (box), view->tab_icon);
|
||
gtk_box_repack (GTK_BOX (box), view->tab_title);
|
||
gtk_box_repack (GTK_BOX (box), view->tab_close);
|
||
|
||
gtk_container_remove (GTK_CONTAINER (tab_label),
|
||
gtk_bin_get_child (GTK_BIN (tab_label)));
|
||
gtk_container_add (GTK_CONTAINER (tab_label), GTK_WIDGET (box));
|
||
gtk_widget_show (box);
|
||
}
|
||
|
||
midori_view_update_tab_title (view->tab_title, 10, angle);
|
||
|
||
/* FIXME: Connect orientation notification */
|
||
}
|
||
}
|
||
|
||
/**
|
||
* midori_view_get_label_ellipsize:
|
||
* @view: a #MidoriView
|
||
*
|
||
* Determines how labels representing the view should be
|
||
* ellipsized, which is helpful for alternative labels.
|
||
*
|
||
* Return value: how to ellipsize the label
|
||
*
|
||
* Since: 0.1.9
|
||
**/
|
||
PangoEllipsizeMode
|
||
midori_view_get_label_ellipsize (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), PANGO_ELLIPSIZE_END);
|
||
|
||
if (view->tab_label)
|
||
return gtk_label_get_ellipsize (GTK_LABEL (view->tab_title));
|
||
return PANGO_ELLIPSIZE_END;
|
||
}
|
||
|
||
static void midori_view_tab_label_data_received (GtkWidget* widget,
|
||
GdkDragContext* context,
|
||
gint x,
|
||
gint y,
|
||
GtkSelectionData* data,
|
||
guint ttype,
|
||
guint timestamp,
|
||
MidoriView* view)
|
||
{
|
||
gchar **uri;
|
||
gchar* text;
|
||
|
||
uri = gtk_selection_data_get_uris (data);
|
||
if (uri != NULL)
|
||
{
|
||
midori_view_set_uri (view, uri[0]);
|
||
g_strfreev (uri);
|
||
}
|
||
else
|
||
{
|
||
text = gtk_selection_data_get_text (data);
|
||
midori_view_set_uri (view, text);
|
||
g_free (text);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* midori_view_get_proxy_tab_label:
|
||
* @view: a #MidoriView
|
||
*
|
||
* Retrieves a proxy tab label that is typically used when
|
||
* adding the view to a notebook.
|
||
*
|
||
* Note that the label actually adjusts its orientation
|
||
* to the according tab position when used in a notebook.
|
||
*
|
||
* The label is created on the first call and will be updated to reflect
|
||
* changes of the loading progress and title.
|
||
*
|
||
* The label is valid until it is removed from its container.
|
||
*
|
||
* Return value: the proxy #GtkEventBox
|
||
**/
|
||
GtkWidget*
|
||
midori_view_get_proxy_tab_label (MidoriView* view)
|
||
{
|
||
GtkWidget* event_box;
|
||
GtkWidget* hbox;
|
||
GtkRcStyle* rcstyle;
|
||
GtkWidget* image;
|
||
GtkWidget* align;
|
||
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL);
|
||
|
||
if (!view->tab_label)
|
||
{
|
||
view->tab_icon = katze_throbber_new ();
|
||
katze_throbber_set_static_pixbuf (KATZE_THROBBER (view->tab_icon),
|
||
midori_view_get_icon (view));
|
||
|
||
view->tab_title = gtk_label_new (midori_view_get_display_title (view));
|
||
gtk_misc_set_alignment (GTK_MISC (view->tab_title), 0.0, 0.5);
|
||
|
||
event_box = gtk_event_box_new ();
|
||
gtk_event_box_set_visible_window (GTK_EVENT_BOX (event_box), FALSE);
|
||
hbox = gtk_hbox_new (FALSE, 1);
|
||
gtk_container_add (GTK_CONTAINER (event_box), GTK_WIDGET (hbox));
|
||
midori_view_update_tab_title (view->tab_title, 10, 0.0);
|
||
|
||
view->tab_close = gtk_button_new ();
|
||
gtk_button_set_relief (GTK_BUTTON (view->tab_close), GTK_RELIEF_NONE);
|
||
gtk_button_set_focus_on_click (GTK_BUTTON (view->tab_close), FALSE);
|
||
rcstyle = gtk_rc_style_new ();
|
||
rcstyle->xthickness = rcstyle->ythickness = 0;
|
||
gtk_widget_modify_style (view->tab_close, rcstyle);
|
||
g_object_unref (rcstyle);
|
||
image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
|
||
gtk_container_add (GTK_CONTAINER (view->tab_close), image);
|
||
align = gtk_alignment_new (1.0, 0.0, 0.0, 0.0);
|
||
gtk_container_add (GTK_CONTAINER (align), view->tab_close);
|
||
|
||
if (katze_object_get_boolean (view->settings, "close-buttons-left"))
|
||
{
|
||
gtk_box_pack_end (GTK_BOX (hbox), view->tab_icon, FALSE, FALSE, 0);
|
||
gtk_box_pack_end (GTK_BOX (hbox), view->tab_title, TRUE, TRUE, 0);
|
||
gtk_box_pack_start (GTK_BOX (hbox), align, FALSE, FALSE, 0);
|
||
}
|
||
else
|
||
{
|
||
gtk_box_pack_start (GTK_BOX (hbox), view->tab_icon, FALSE, FALSE, 0);
|
||
gtk_box_pack_start (GTK_BOX (hbox), view->tab_title, TRUE, TRUE, 0);
|
||
gtk_box_pack_end (GTK_BOX (hbox), align, FALSE, FALSE, 0);
|
||
}
|
||
gtk_widget_show_all (GTK_WIDGET (event_box));
|
||
|
||
if (view->minimized)
|
||
gtk_widget_hide (view->tab_title);
|
||
if (!view->close_buttons_on_tabs)
|
||
gtk_widget_hide (view->tab_close);
|
||
|
||
g_signal_connect (event_box, "button-press-event",
|
||
G_CALLBACK (midori_view_tab_label_button_press_event), view);
|
||
g_signal_connect (view->tab_close, "style-set",
|
||
G_CALLBACK (midori_view_tab_icon_style_set_cb), NULL);
|
||
g_signal_connect (view->tab_close, "clicked",
|
||
G_CALLBACK (midori_view_tab_close_clicked), view);
|
||
|
||
view->tab_label = event_box;
|
||
g_signal_connect (view->tab_icon, "destroy",
|
||
G_CALLBACK (gtk_widget_destroyed),
|
||
&view->tab_icon);
|
||
g_signal_connect (view->tab_label, "destroy",
|
||
G_CALLBACK (gtk_widget_destroyed),
|
||
&view->tab_label);
|
||
|
||
g_signal_connect (view->tab_label, "parent-set",
|
||
G_CALLBACK (midori_view_tab_label_parent_set),
|
||
view);
|
||
gtk_drag_dest_set (view->tab_label, GTK_DEST_DEFAULT_ALL, NULL,
|
||
0, GDK_ACTION_COPY);
|
||
gtk_drag_dest_add_text_targets (view->tab_label);
|
||
gtk_drag_dest_add_uri_targets (view->tab_label);
|
||
g_signal_connect (view->tab_label, "drag-data-received",
|
||
G_CALLBACK (midori_view_tab_label_data_received),
|
||
view);
|
||
}
|
||
return view->tab_label;
|
||
}
|
||
|
||
static void
|
||
midori_view_item_meta_data_changed (KatzeItem* item,
|
||
const gchar* key,
|
||
MidoriView* view)
|
||
{
|
||
if (g_str_equal (key, "minimized"))
|
||
g_object_set (view, "minimized",
|
||
katze_item_get_meta_string (item, key) != NULL, NULL);
|
||
else if (g_str_has_prefix (key, "scroll"))
|
||
{
|
||
gint value = katze_item_get_meta_integer (item, key);
|
||
if (view->scrollh == -2 && key[6] == 'h')
|
||
view->scrollh = value > -1 ? value : 0;
|
||
else if (view->scrollv == -2 && key[6] == 'v')
|
||
view->scrollv = value > -1 ? value : 0;
|
||
else
|
||
return;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* midori_view_get_proxy_item:
|
||
* @view: a #MidoriView
|
||
*
|
||
* Retrieves a proxy item that can be used for bookmark storage as
|
||
* well as session management.
|
||
*
|
||
* The item reflects changes to the title and uri automatically.
|
||
*
|
||
* Return value: the proxy #KatzeItem
|
||
**/
|
||
KatzeItem*
|
||
midori_view_get_proxy_item (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL);
|
||
|
||
return view->item;
|
||
}
|
||
|
||
/**
|
||
* midori_view_get_zoom_level:
|
||
* @view: a #MidoriView
|
||
*
|
||
* Determines the current zoom level of the view.
|
||
*
|
||
* Return value: the current zoom level
|
||
**/
|
||
gfloat
|
||
midori_view_get_zoom_level (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), 1.0f);
|
||
|
||
if (view->web_view != NULL)
|
||
return webkit_web_view_get_zoom_level (WEBKIT_WEB_VIEW (view->web_view));
|
||
return 1.0f;
|
||
}
|
||
|
||
/**
|
||
* midori_view_set_zoom_level:
|
||
* @view: a #MidoriView
|
||
* @zoom_level: the new zoom level
|
||
*
|
||
* Sets the current zoom level of the view.
|
||
**/
|
||
void
|
||
midori_view_set_zoom_level (MidoriView* view,
|
||
gfloat zoom_level)
|
||
{
|
||
g_return_if_fail (MIDORI_IS_VIEW (view));
|
||
|
||
webkit_web_view_set_zoom_level (
|
||
WEBKIT_WEB_VIEW (view->web_view), zoom_level);
|
||
g_object_notify (G_OBJECT (view), "zoom-level");
|
||
}
|
||
|
||
gboolean
|
||
midori_view_can_zoom_in (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), FALSE);
|
||
|
||
return view->web_view != NULL
|
||
&& (katze_object_get_boolean (view->settings, "zoom-text-and-images")
|
||
|| !g_str_has_prefix (view->mime_type, "image/"));
|
||
}
|
||
|
||
gboolean
|
||
midori_view_can_zoom_out (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), FALSE);
|
||
|
||
return view->web_view != NULL
|
||
&& (katze_object_get_boolean (view->settings, "zoom-text-and-images")
|
||
|| !g_str_has_prefix (view->mime_type, "image/"));
|
||
}
|
||
|
||
gboolean
|
||
midori_view_can_view_source (MidoriView* view)
|
||
{
|
||
gchar* content_type;
|
||
gchar* text_type;
|
||
gboolean is_text;
|
||
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), FALSE);
|
||
|
||
if (midori_view_is_blank (view))
|
||
return FALSE;
|
||
|
||
content_type = g_content_type_from_mime_type (view->mime_type);
|
||
text_type = g_content_type_from_mime_type ("text/plain");
|
||
is_text = g_content_type_is_a (content_type, text_type);
|
||
g_free (content_type);
|
||
g_free (text_type);
|
||
return is_text;
|
||
}
|
||
|
||
#define can_do(what) \
|
||
gboolean \
|
||
midori_view_can_##what (MidoriView* view) \
|
||
{ \
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), FALSE); \
|
||
\
|
||
return view->web_view != NULL; \
|
||
}
|
||
|
||
can_do (reload)
|
||
can_do (print)
|
||
can_do (find)
|
||
|
||
/**
|
||
* midori_view_reload:
|
||
* @view: a #MidoriView
|
||
* @from_cache: whether to allow caching
|
||
*
|
||
* Reloads the view.
|
||
**/
|
||
void
|
||
midori_view_reload (MidoriView* view,
|
||
gboolean from_cache)
|
||
{
|
||
gchar* title;
|
||
|
||
g_return_if_fail (MIDORI_IS_VIEW (view));
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 14)
|
||
title = NULL;
|
||
#elif WEBKIT_CHECK_VERSION (1, 1, 6)
|
||
/* WebKit 1.1.6 doesn't handle "alternate content" flawlessly,
|
||
so reloading via Javascript works but not via API calls. */
|
||
title = g_strdup_printf (_("Error - %s"), view->uri);
|
||
#else
|
||
/* Error pages are special, we want to try loading the destination
|
||
again, not the error page which isn't even a proper page */
|
||
title = g_strdup_printf (_("Error - %s"), view->uri);
|
||
#endif
|
||
if (view->title && title && strstr (title, view->title))
|
||
webkit_web_view_open (WEBKIT_WEB_VIEW (view->web_view), view->uri);
|
||
else if (!(view->uri && *view->uri && strncmp (view->uri, "about:", 6)))
|
||
{
|
||
gchar* uri = g_strdup (view->uri);
|
||
midori_view_set_uri (view, uri);
|
||
g_free (uri);
|
||
}
|
||
else if (from_cache)
|
||
webkit_web_view_reload (WEBKIT_WEB_VIEW (view->web_view));
|
||
else
|
||
webkit_web_view_reload_bypass_cache (WEBKIT_WEB_VIEW (view->web_view));
|
||
katze_item_set_meta_integer (view->item, "delay", -1);
|
||
|
||
g_free (title);
|
||
}
|
||
|
||
/**
|
||
* midori_view_stop_loading
|
||
* @view: a #MidoriView
|
||
*
|
||
* Stops loading the view if it is currently loading.
|
||
**/
|
||
void
|
||
midori_view_stop_loading (MidoriView* view)
|
||
{
|
||
g_return_if_fail (MIDORI_IS_VIEW (view));
|
||
|
||
webkit_web_view_stop_loading (WEBKIT_WEB_VIEW (view->web_view));
|
||
}
|
||
|
||
/**
|
||
* midori_view_can_go_back
|
||
* @view: a #MidoriView
|
||
*
|
||
* Determines whether the view can go back.
|
||
**/
|
||
gboolean
|
||
midori_view_can_go_back (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), FALSE);
|
||
|
||
if (view->web_view)
|
||
return webkit_web_view_can_go_back (WEBKIT_WEB_VIEW (view->web_view));
|
||
else
|
||
return FALSE;
|
||
}
|
||
|
||
/**
|
||
* midori_view_go_back
|
||
* @view: a #MidoriView
|
||
*
|
||
* Goes back one page in the view.
|
||
**/
|
||
void
|
||
midori_view_go_back (MidoriView* view)
|
||
{
|
||
g_return_if_fail (MIDORI_IS_VIEW (view));
|
||
|
||
webkit_web_view_go_back (WEBKIT_WEB_VIEW (view->web_view));
|
||
}
|
||
|
||
/**
|
||
* midori_view_can_go_forward
|
||
* @view: a #MidoriView
|
||
*
|
||
* Determines whether the view can go forward.
|
||
**/
|
||
gboolean
|
||
midori_view_can_go_forward (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), FALSE);
|
||
|
||
if (view->web_view)
|
||
return webkit_web_view_can_go_forward (WEBKIT_WEB_VIEW (view->web_view));
|
||
else
|
||
return FALSE;
|
||
}
|
||
|
||
/**
|
||
* midori_view_go_forward
|
||
* @view: a #MidoriView
|
||
*
|
||
* Goes forward one page in the view.
|
||
**/
|
||
void
|
||
midori_view_go_forward (MidoriView* view)
|
||
{
|
||
g_return_if_fail (MIDORI_IS_VIEW (view));
|
||
|
||
webkit_web_view_go_forward (WEBKIT_WEB_VIEW (view->web_view));
|
||
}
|
||
|
||
/**
|
||
* midori_view_get_previous_page
|
||
* @view: a #MidoriView
|
||
*
|
||
* Determines the previous sub-page in the view.
|
||
*
|
||
* Return value: an URI, or %NULL
|
||
*
|
||
* Since: 0.2.3
|
||
**/
|
||
const gchar*
|
||
midori_view_get_previous_page (MidoriView* view)
|
||
{
|
||
static gchar* uri = NULL;
|
||
WebKitWebFrame* web_frame;
|
||
JSContextRef js_context;
|
||
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL);
|
||
|
||
if (!view->web_view)
|
||
return NULL;
|
||
|
||
web_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (view->web_view));
|
||
js_context = webkit_web_frame_get_global_context (web_frame);
|
||
katze_assign (uri, sokoke_js_script_eval (js_context,
|
||
"(function (tags) {"
|
||
"for (var tag in tags) {"
|
||
"var l = document.getElementsByTagName (tag);"
|
||
"for (var i in l) { "
|
||
"if ((l[i].rel && l[i].rel.toLowerCase () == 'prev') "
|
||
" || (l[i].innerHTML"
|
||
" && l[i].innerHTML.toLowerCase ().indexOf ('prev') != -1)) "
|
||
"{ return l[i].href; } } } return 0; })("
|
||
"{ link:'link', a:'a' });", NULL));
|
||
return uri && uri[0] != '0' ? uri : NULL;
|
||
}
|
||
|
||
/**
|
||
* midori_view_get_next_page
|
||
* @view: a #MidoriView
|
||
*
|
||
* Determines the next sub-page in the view.
|
||
*
|
||
* Return value: an URI, or %NULL
|
||
*
|
||
* Since: 0.2.3
|
||
**/
|
||
const gchar*
|
||
midori_view_get_next_page (MidoriView* view)
|
||
{
|
||
static gchar* uri = NULL;
|
||
WebKitWebFrame* web_frame;
|
||
JSContextRef js_context;
|
||
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL);
|
||
|
||
if (!view->web_view)
|
||
return NULL;
|
||
|
||
web_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (view->web_view));
|
||
js_context = webkit_web_frame_get_global_context (web_frame);
|
||
katze_assign (uri, sokoke_js_script_eval (js_context,
|
||
"(function (tags) {"
|
||
"for (var tag in tags) {"
|
||
"var l = document.getElementsByTagName (tag);"
|
||
"for (var i in l) { "
|
||
"if ((l[i].rel && l[i].rel.toLowerCase () == 'next') "
|
||
" || (l[i].innerHTML"
|
||
" && l[i].innerHTML.toLowerCase ().indexOf ('next') != -1)) "
|
||
"{ return l[i].href; } } } return 0; })("
|
||
"{ link:'link', a:'a' });", NULL));
|
||
return uri && uri[0] != '0' ? uri : NULL;
|
||
}
|
||
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 5)
|
||
static GtkWidget*
|
||
midori_view_print_create_custom_widget_cb (GtkPrintOperation* operation,
|
||
MidoriView* view)
|
||
{
|
||
GtkWidget* box;
|
||
GtkWidget* button;
|
||
|
||
box = gtk_vbox_new (FALSE, 0);
|
||
gtk_container_set_border_width (GTK_CONTAINER (box), 4);
|
||
button = katze_property_proxy (view->settings, "print-backgrounds", NULL);
|
||
gtk_button_set_label (GTK_BUTTON (button), _("Print background images"));
|
||
gtk_widget_set_tooltip_text (button, _("Whether background images should be printed"));
|
||
gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
|
||
gtk_widget_show_all (box);
|
||
|
||
return box;
|
||
}
|
||
#endif
|
||
|
||
static void
|
||
midori_view_print_response_cb (GtkWidget* dialog,
|
||
gint response,
|
||
gpointer data)
|
||
{
|
||
gtk_widget_destroy (dialog);
|
||
}
|
||
|
||
/**
|
||
* midori_view_print
|
||
* @view: a #MidoriView
|
||
*
|
||
* Prints the contents of the view.
|
||
**/
|
||
void
|
||
midori_view_print (MidoriView* view)
|
||
{
|
||
WebKitWebFrame* frame;
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 5)
|
||
GtkPrintOperation* operation;
|
||
GError* error;
|
||
#endif
|
||
|
||
g_return_if_fail (MIDORI_IS_VIEW (view));
|
||
|
||
frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (view->web_view));
|
||
#if WEBKIT_CHECK_VERSION (1, 1, 5)
|
||
operation = gtk_print_operation_new ();
|
||
gtk_print_operation_set_custom_tab_label (operation, _("Features"));
|
||
#if GTK_CHECK_VERSION (2, 18, 0)
|
||
gtk_print_operation_set_embed_page_setup (operation, TRUE);
|
||
#endif
|
||
g_signal_connect (operation, "create-custom-widget",
|
||
G_CALLBACK (midori_view_print_create_custom_widget_cb), view);
|
||
error = NULL;
|
||
webkit_web_frame_print_full (frame, operation,
|
||
GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, &error);
|
||
g_object_unref (operation);
|
||
|
||
if (error)
|
||
{
|
||
GtkWidget* window = gtk_widget_get_toplevel (GTK_WIDGET (view));
|
||
GtkWidget* dialog = gtk_message_dialog_new (
|
||
gtk_widget_is_toplevel (window) ? GTK_WINDOW (window) : NULL,
|
||
GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR,
|
||
GTK_BUTTONS_CLOSE, "%s", error->message);
|
||
g_error_free (error);
|
||
|
||
g_signal_connect (dialog, "response",
|
||
G_CALLBACK (midori_view_print_response_cb), NULL);
|
||
gtk_widget_show (dialog);
|
||
}
|
||
#else
|
||
webkit_web_frame_print (frame);
|
||
#endif
|
||
}
|
||
|
||
/**
|
||
* midori_view_unmark_text_matches
|
||
* @view: a #MidoriView
|
||
*
|
||
* Unmarks the text matches in the view.
|
||
**/
|
||
void
|
||
midori_view_unmark_text_matches (MidoriView* view)
|
||
{
|
||
g_return_if_fail (MIDORI_IS_VIEW (view));
|
||
|
||
webkit_web_view_unmark_text_matches (WEBKIT_WEB_VIEW (view->web_view));
|
||
}
|
||
|
||
/**
|
||
* midori_view_search_text
|
||
* @view: a #MidoriView
|
||
* @text: a string
|
||
* @case_sensitive: case sensitivity
|
||
* @forward: whether to search forward
|
||
*
|
||
* Searches a text within the view.
|
||
**/
|
||
void
|
||
midori_view_search_text (MidoriView* view,
|
||
const gchar* text,
|
||
gboolean case_sensitive,
|
||
gboolean forward)
|
||
{
|
||
g_return_if_fail (MIDORI_IS_VIEW (view));
|
||
|
||
g_signal_emit (view, signals[SEARCH_TEXT], 0,
|
||
webkit_web_view_search_text (WEBKIT_WEB_VIEW (view->web_view),
|
||
text, case_sensitive, forward, TRUE), NULL);
|
||
}
|
||
|
||
/**
|
||
* midori_view_mark_text_matches
|
||
* @view: a #MidoriView
|
||
* @text: a string
|
||
* @case_sensitive: case sensitivity
|
||
*
|
||
* Marks all text matches within the view.
|
||
**/
|
||
void
|
||
midori_view_mark_text_matches (MidoriView* view,
|
||
const gchar* text,
|
||
gboolean case_sensitive)
|
||
{
|
||
g_return_if_fail (MIDORI_IS_VIEW (view));
|
||
|
||
webkit_web_view_mark_text_matches (WEBKIT_WEB_VIEW (view->web_view),
|
||
text, case_sensitive, 0);
|
||
}
|
||
|
||
/**
|
||
* midori_view_set_highlight_text_matches
|
||
* @view: a #MidoriView
|
||
* @highlight: whether to highlight matches
|
||
*
|
||
* Whether to highlight all matches within the view.
|
||
**/
|
||
void
|
||
midori_view_set_highlight_text_matches (MidoriView* view,
|
||
gboolean highlight)
|
||
{
|
||
g_return_if_fail (MIDORI_IS_VIEW (view));
|
||
|
||
webkit_web_view_set_highlight_text_matches (
|
||
WEBKIT_WEB_VIEW (view->web_view), highlight);
|
||
}
|
||
|
||
/**
|
||
* midori_view_execute_script
|
||
* @view: a #MidoriView
|
||
* @script: script code
|
||
* @exception: location to store an exception message
|
||
*
|
||
* Execute a script on the view.
|
||
*
|
||
* Returns: %TRUE if the script was executed successfully
|
||
**/
|
||
gboolean
|
||
midori_view_execute_script (MidoriView* view,
|
||
const gchar* script,
|
||
gchar** exception)
|
||
{
|
||
WebKitWebFrame* web_frame;
|
||
JSContextRef js_context;
|
||
gchar* script_decoded;
|
||
gchar* result;
|
||
gboolean success;
|
||
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), FALSE);
|
||
g_return_val_if_fail (script != NULL, FALSE);
|
||
|
||
web_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (view->web_view));
|
||
js_context = webkit_web_frame_get_global_context (web_frame);
|
||
if ((script_decoded = soup_uri_decode (script)))
|
||
{
|
||
result = sokoke_js_script_eval (js_context, script_decoded, exception);
|
||
g_free (script_decoded);
|
||
}
|
||
else
|
||
result = sokoke_js_script_eval (js_context, script, exception);
|
||
success = result != NULL;
|
||
g_free (result);
|
||
return success;
|
||
}
|
||
|
||
/**
|
||
* midori_view_get_snapshot
|
||
* @view: a #MidoriView
|
||
* @width: the desired width
|
||
* @height: the desired height
|
||
*
|
||
* Take a snapshot of the view at the given dimensions. The
|
||
* view has to be mapped on the screen.
|
||
*
|
||
* If width and height are negative, the resulting
|
||
* image is going to be optimized for speed.
|
||
*
|
||
* Returns: a newly allocated #GdkPixbuf
|
||
*
|
||
* Since: 0.2.1
|
||
**/
|
||
GdkPixbuf*
|
||
midori_view_get_snapshot (MidoriView* view,
|
||
gint width,
|
||
gint height)
|
||
{
|
||
GtkWidget* web_view;
|
||
GdkWindow* window;
|
||
GtkAllocation allocation;
|
||
gboolean fast;
|
||
gint x, y, w, h;
|
||
GdkRectangle rect;
|
||
GdkPixmap* pixmap;
|
||
GdkEvent event;
|
||
gboolean result;
|
||
GdkColormap* colormap;
|
||
GdkPixbuf* pixbuf;
|
||
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL);
|
||
web_view = view->web_view;
|
||
window = gtk_widget_get_window (web_view);
|
||
g_return_val_if_fail (window != NULL, NULL);
|
||
|
||
gtk_widget_get_allocation (web_view, &allocation);
|
||
x = allocation.x;
|
||
y = allocation.y;
|
||
w = allocation.width;
|
||
h = allocation.height;
|
||
|
||
/* If width and height are both negative, we try to render faster at
|
||
the cost of correctness or beauty. Only a part of the page is
|
||
rendered which makes it a lot faster and scaling isn't as nice. */
|
||
fast = FALSE;
|
||
if (width < 0 && height < 0)
|
||
{
|
||
width *= -1;
|
||
height *= -1;
|
||
w = w > 320 ? 320 : w;
|
||
h = h > 240 ? 240 : h;
|
||
fast = TRUE;
|
||
}
|
||
|
||
rect.x = x;
|
||
rect.y = y;
|
||
rect.width = w;
|
||
rect.height = h;
|
||
|
||
pixmap = gdk_pixmap_new (window, w, h, gdk_drawable_get_depth (window));
|
||
event.expose.type = GDK_EXPOSE;
|
||
event.expose.window = pixmap;
|
||
event.expose.send_event = FALSE;
|
||
event.expose.count = 0;
|
||
event.expose.area.x = 0;
|
||
event.expose.area.y = 0;
|
||
gdk_drawable_get_size (GDK_DRAWABLE (window),
|
||
&event.expose.area.width, &event.expose.area.height);
|
||
event.expose.region = gdk_region_rectangle (&event.expose.area);
|
||
|
||
g_signal_emit_by_name (web_view, "expose-event", &event, &result);
|
||
|
||
colormap = gdk_drawable_get_colormap (pixmap);
|
||
pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, colormap, 0, 0,
|
||
0, 0, rect.width, rect.height);
|
||
g_object_unref (pixmap);
|
||
|
||
if (width || height)
|
||
{
|
||
GdkPixbuf* scaled;
|
||
if (!width)
|
||
width = rect.width;
|
||
if (!height)
|
||
height = rect.height;
|
||
|
||
scaled = gdk_pixbuf_scale_simple (pixbuf, width, height,
|
||
fast ? GDK_INTERP_NEAREST : GDK_INTERP_TILES);
|
||
g_object_unref (pixbuf);
|
||
return scaled;
|
||
}
|
||
|
||
return pixbuf;
|
||
}
|
||
|
||
/**
|
||
* midori_view_get_web_view
|
||
* @view: a #MidoriView
|
||
*
|
||
* Returns: The #WebKitWebView for this view
|
||
*
|
||
* Since: 0.2.5
|
||
**/
|
||
GtkWidget*
|
||
midori_view_get_web_view (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL);
|
||
|
||
return view->web_view;
|
||
}
|
||
|
||
/**
|
||
* midori_view_get_security
|
||
* @view: a #MidoriView
|
||
*
|
||
* Returns: The #MidoriSecurity for this view
|
||
*
|
||
* Since: 0.2.5
|
||
**/
|
||
MidoriSecurity
|
||
midori_view_get_security (MidoriView* view)
|
||
{
|
||
g_return_val_if_fail (MIDORI_IS_VIEW (view), MIDORI_SECURITY_NONE);
|
||
|
||
return view->security;
|
||
}
|
||
|
||
static void
|
||
thumb_view_load_status_cb (MidoriView* thumb_view,
|
||
GParamSpec* pspec,
|
||
MidoriView* view)
|
||
{
|
||
GdkPixbuf* img;
|
||
gchar* file_path;
|
||
gchar* thumb_dir;
|
||
gchar* thumb_uri;
|
||
MidoriBrowser* browser;
|
||
gint i;
|
||
GtkWidget* tab;
|
||
|
||
if (midori_view_get_load_status (thumb_view) != MIDORI_LOAD_FINISHED)
|
||
return;
|
||
|
||
gtk_widget_realize (midori_view_get_web_view (MIDORI_VIEW (thumb_view)));
|
||
img = midori_view_get_snapshot (MIDORI_VIEW (thumb_view), 240, 160);
|
||
thumb_uri = g_object_get_data (G_OBJECT (thumb_view), "thumb-uri");
|
||
file_path = sokoke_build_thumbnail_path (thumb_uri);
|
||
thumb_dir = g_build_path (G_DIR_SEPARATOR_S, g_get_user_cache_dir (),
|
||
PACKAGE_NAME, "thumbnails", NULL);
|
||
|
||
if (!g_file_test (thumb_dir, G_FILE_TEST_EXISTS))
|
||
katze_mkdir_with_parents (thumb_dir, 0700);
|
||
|
||
gdk_pixbuf_save (img, file_path, "png", NULL, "compression", "7", NULL);
|
||
|
||
g_object_unref (img);
|
||
|
||
g_free (thumb_uri);
|
||
g_free (file_path);
|
||
g_free (thumb_dir);
|
||
|
||
g_signal_handlers_disconnect_by_func (
|
||
thumb_view, thumb_view_load_status_cb, view);
|
||
|
||
/* Destroying the view here may trigger a WebKitGTK+ 1.1.14 bug */
|
||
#if !WEBKIT_CHECK_VERSION (1, 1, 14) || WEBKIT_CHECK_VERSION (1, 1, 15)
|
||
gtk_widget_destroy (GTK_WIDGET (thumb_view));
|
||
view->thumb_view = NULL;
|
||
#endif
|
||
|
||
browser = midori_browser_get_for_widget (GTK_WIDGET (view));
|
||
i = 0;
|
||
while ((tab = midori_browser_get_nth_tab (browser, i++)))
|
||
if (midori_view_is_blank (MIDORI_VIEW (tab)))
|
||
midori_view_reload (MIDORI_VIEW (tab), FALSE);
|
||
}
|
||
|
||
/**
|
||
* midori_view_speed_dial_get_thumb
|
||
* @view: a #MidoriView
|
||
* @dom_id: Id of the shortcut on speed_dial page in wich to inject content
|
||
* @url: url of the shortcut
|
||
*/
|
||
static void
|
||
midori_view_speed_dial_get_thumb (MidoriView* view,
|
||
gchar* dom_id,
|
||
gchar* url)
|
||
{
|
||
GtkWidget* thumb_view;
|
||
MidoriWebSettings* settings;
|
||
GtkWidget* browser;
|
||
GtkWidget* notebook;
|
||
GtkWidget* label;
|
||
|
||
browser = gtk_widget_get_toplevel (GTK_WIDGET (view));
|
||
if (!GTK_IS_WINDOW (browser))
|
||
return;
|
||
|
||
/* What we are doing here is a bit of a hack. In order to render a
|
||
thumbnail we need a new view and load the url in it. But it has
|
||
to be visible and packed in a container. So we secretly pack it
|
||
into the notebook of the parent browser. */
|
||
notebook = katze_object_get_object (browser, "notebook");
|
||
if (!notebook)
|
||
return;
|
||
|
||
if (!view->thumb_view)
|
||
{
|
||
view->thumb_view = midori_view_new_with_title (NULL, NULL, FALSE);
|
||
gtk_container_add (GTK_CONTAINER (notebook), view->thumb_view);
|
||
/* We use an empty label. It's not invisible but at least hard to spot. */
|
||
label = gtk_event_box_new ();
|
||
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), view->thumb_view, label);
|
||
gtk_widget_show (view->thumb_view);
|
||
}
|
||
g_object_unref (notebook);
|
||
thumb_view = view->thumb_view;
|
||
settings = g_object_new (MIDORI_TYPE_WEB_SETTINGS, "enable-scripts", FALSE,
|
||
"enable-plugins", FALSE, "auto-load-images", TRUE, NULL);
|
||
_midori_view_set_settings (MIDORI_VIEW (thumb_view), settings);
|
||
|
||
g_object_set_data (G_OBJECT (thumb_view), "thumb-uri", url);
|
||
g_signal_connect (thumb_view, "notify::load-status",
|
||
G_CALLBACK (thumb_view_load_status_cb), view);
|
||
midori_view_set_uri (MIDORI_VIEW (thumb_view), url);
|
||
}
|
||
|
||
/**
|
||
* midori_view_speed_dial_save
|
||
* @view: a #MidoriView
|
||
* @message: message from JavaScript
|
||
*
|
||
* Save speed_dial settings
|
||
*
|
||
**/
|
||
static void
|
||
midori_view_speed_dial_save (MidoriView* view,
|
||
const gchar* message)
|
||
{
|
||
gchar* action;
|
||
gchar* config_file;
|
||
GKeyFile* key_file;
|
||
MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (view));
|
||
gchar* msg = g_strdup (message + 16);
|
||
gchar** parts = g_strsplit (msg, " ", 4);
|
||
gint i;
|
||
GtkWidget* tab;
|
||
|
||
g_object_get (browser, "speed-dial", &key_file, NULL);
|
||
action = parts[0];
|
||
|
||
if (g_str_equal (action, "size"))
|
||
{
|
||
g_key_file_set_string (key_file, "settings", "rows", parts[2]);
|
||
g_key_file_set_string (key_file, "settings", "columns", parts[1]);
|
||
}
|
||
else if (g_str_equal (action, "thumbsize"))
|
||
{
|
||
gchar* saved_size;
|
||
gchar* thumb_size_type;
|
||
guint size = atoi (parts[1]);
|
||
|
||
if (size == 80)
|
||
thumb_size_type = g_strdup ("SMALL");
|
||
else if (size == 240)
|
||
thumb_size_type = g_strdup ("BIG");
|
||
else /* if (size == 160) */
|
||
thumb_size_type = g_strdup ("MEDIUM");
|
||
|
||
saved_size = g_key_file_get_string (key_file, "settings", "size", NULL);
|
||
if (saved_size != NULL && g_str_equal (saved_size, thumb_size_type))
|
||
{
|
||
g_free (action);
|
||
g_free (msg);
|
||
g_free (thumb_size_type);
|
||
g_free (saved_size);
|
||
return;
|
||
}
|
||
|
||
g_key_file_set_string (key_file, "settings", "size", thumb_size_type);
|
||
g_free (thumb_size_type);
|
||
g_free (saved_size);
|
||
}
|
||
else if (g_str_equal (action, "add") || g_str_equal (action, "rename")
|
||
|| g_str_equal (action, "delete"))
|
||
{
|
||
gchar* tmp = g_strdup (parts[1] + 1);
|
||
guint slot_id = atoi (tmp);
|
||
gchar* dial_id = g_strdup_printf ("Dial %d", slot_id);
|
||
g_free (tmp);
|
||
|
||
|
||
if (g_str_equal (action, "delete"))
|
||
{
|
||
gchar* uri = g_key_file_get_string (key_file, dial_id, "uri", NULL);
|
||
gchar* file_path = sokoke_build_thumbnail_path (uri);
|
||
|
||
g_key_file_remove_group (key_file, dial_id, NULL);
|
||
g_unlink (file_path);
|
||
|
||
g_free (uri);
|
||
g_free (file_path);
|
||
}
|
||
else if (g_str_equal (action, "add"))
|
||
{
|
||
g_key_file_set_string (key_file, dial_id, "uri", parts[2]);
|
||
g_key_file_set_string (key_file, dial_id, "title", parts[3]);
|
||
midori_view_speed_dial_get_thumb (view, parts[1], parts[2]);
|
||
}
|
||
else if (g_str_equal (action, "rename"))
|
||
{
|
||
g_key_file_set_string (key_file, dial_id, "title", parts[2]);
|
||
}
|
||
|
||
g_free (dial_id);
|
||
}
|
||
|
||
config_file = g_build_filename (sokoke_set_config_dir (NULL), "speeddial", NULL);
|
||
sokoke_key_file_save_to_file (key_file, config_file, NULL);
|
||
|
||
i = 0;
|
||
while ((tab = midori_browser_get_nth_tab (browser, i++)))
|
||
if (midori_view_is_blank (MIDORI_VIEW (tab)))
|
||
midori_view_reload (MIDORI_VIEW (tab), FALSE);
|
||
|
||
g_free (msg);
|
||
g_free (action);
|
||
g_free (config_file);
|
||
}
|