95111a054c
Implement font properties, web features, Middle click opens selection, Open tabs in the background and proxy. While we are at it, remove Tab label size.
2859 lines
89 KiB
C
2859 lines
89 KiB
C
/*
|
|
Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
|
|
|
|
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-source.h"
|
|
|
|
#include "midori-stock.h"
|
|
|
|
#include "compat.h"
|
|
#include "sokoke.h"
|
|
#include "gjs.h"
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#if HAVE_GIO
|
|
#include <gio/gio.h>
|
|
#endif
|
|
#include <glib/gi18n.h>
|
|
#include <webkit/webkit.h>
|
|
|
|
/* This is unstable API, so we need to declare it */
|
|
gchar*
|
|
webkit_web_view_get_selected_text (WebKitWebView* web_view);
|
|
|
|
struct _MidoriView
|
|
{
|
|
GtkScrolledWindow parent_instance;
|
|
|
|
gint socket_id;
|
|
GIOChannel* input;
|
|
FILE* output;
|
|
|
|
gchar* command_cache;
|
|
gchar* premature_uri;
|
|
gchar* uri;
|
|
gchar* title;
|
|
GdkPixbuf* icon;
|
|
gdouble progress;
|
|
MidoriLoadStatus load_status;
|
|
gchar* statusbar_text;
|
|
gchar* link_uri;
|
|
gboolean has_selection;
|
|
gchar* selected_text;
|
|
gboolean can_cut_clipboard;
|
|
gboolean can_copy_clipboard;
|
|
gboolean can_paste_clipboard;
|
|
gfloat zoom_level;
|
|
gboolean can_go_back;
|
|
gboolean can_go_forward;
|
|
MidoriWebSettings* settings;
|
|
GtkWidget* web_view;
|
|
gboolean window_object_cleared;
|
|
|
|
gchar* download_manager;
|
|
gchar* default_font_family;
|
|
gint default_font_size;
|
|
gint minimum_font_size;
|
|
gchar* default_encoding;
|
|
gboolean auto_load_images;
|
|
gboolean auto_shrink_images;
|
|
gboolean print_backgrounds;
|
|
gboolean resizable_text_areas;
|
|
gboolean enable_scripts;
|
|
gboolean enable_plugins;
|
|
gboolean middle_click_opens_selection;
|
|
gboolean open_tabs_in_the_background;
|
|
gboolean close_buttons_on_tabs;
|
|
gchar* http_proxy;
|
|
|
|
GtkWidget* menu_item;
|
|
GtkWidget* tab_label;
|
|
GtkWidget* tab_icon;
|
|
GtkWidget* tab_title;
|
|
GtkWidget* tab_close;
|
|
KatzeItem* item;
|
|
};
|
|
|
|
struct _MidoriViewClass
|
|
{
|
|
GtkScrolledWindowClass parent_class;
|
|
};
|
|
|
|
G_DEFINE_TYPE (MidoriView, midori_view, GTK_TYPE_SCROLLED_WINDOW)
|
|
|
|
GType
|
|
midori_load_status_get_type (void)
|
|
{
|
|
static GType type = 0;
|
|
if (type)
|
|
return type;
|
|
static const GEnumValue values[] = {
|
|
{ MIDORI_LOAD_PROVISIONAL, "MIDORI_LOAD_PROVISIONAL", N_("Load Provisional") },
|
|
{ MIDORI_LOAD_COMMITTED, "MIDORI_LOAD_COMMITTED", N_("Load Committed") },
|
|
{ MIDORI_LOAD_FINISHED, "MIDORI_LOAD_FINISHED", N_("Load Finished") },
|
|
{ 0, NULL, NULL }
|
|
};
|
|
type = g_enum_register_static ("MidoriLoadStatus", values);
|
|
return type;
|
|
}
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
|
|
PROP_SOCKET_ID,
|
|
PROP_URI,
|
|
PROP_TITLE,
|
|
PROP_ICON,
|
|
PROP_LOAD_STATUS,
|
|
PROP_PROGRESS,
|
|
PROP_ZOOM_LEVEL,
|
|
PROP_STATUSBAR_TEXT,
|
|
PROP_SETTINGS
|
|
};
|
|
|
|
enum {
|
|
ACTIVATE_ACTION,
|
|
CONSOLE_MESSAGE,
|
|
NEW_TAB,
|
|
NEW_WINDOW,
|
|
SEARCH_TEXT,
|
|
ADD_BOOKMARK,
|
|
|
|
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 void
|
|
midori_cclosure_marshal_VOID__STRING_BOOLEAN (GClosure* closure,
|
|
GValue* return_value,
|
|
guint n_param_values,
|
|
const GValue* param_values,
|
|
gpointer invocation_hint,
|
|
gpointer marshal_data)
|
|
{
|
|
typedef void(*GMarshalFunc_VOID__STRING_BOOLEAN) (gpointer data1,
|
|
gpointer arg_1,
|
|
gboolean arg_2,
|
|
gpointer data2);
|
|
register GMarshalFunc_VOID__STRING_BOOLEAN callback;
|
|
register GCClosure* cc = (GCClosure*) closure;
|
|
register gpointer data1, data2;
|
|
|
|
g_return_if_fail (n_param_values == 3);
|
|
|
|
if (G_CCLOSURE_SWAP_DATA (closure))
|
|
{
|
|
data1 = closure->data;
|
|
data2 = g_value_peek_pointer (param_values + 0);
|
|
}
|
|
else
|
|
{
|
|
data1 = g_value_peek_pointer (param_values + 0);
|
|
data2 = closure->data;
|
|
}
|
|
callback = (GMarshalFunc_VOID__STRING_BOOLEAN) (marshal_data
|
|
? marshal_data : cc->callback);
|
|
callback (data1,
|
|
(gchar*)g_value_get_string (param_values + 1),
|
|
g_value_get_boolean (param_values + 2),
|
|
data2);
|
|
}
|
|
|
|
static void
|
|
midori_cclosure_marshal_VOID__STRING_INT_STRING (GClosure* closure,
|
|
GValue* return_value,
|
|
guint n_param_values,
|
|
const GValue* param_values,
|
|
gpointer invocation_hint,
|
|
gpointer marshal_data)
|
|
{
|
|
typedef void(*GMarshalFunc_VOID__STRING_INT_STRING) (gpointer data1,
|
|
gpointer arg_1,
|
|
gint arg_2,
|
|
gpointer arg_3,
|
|
gpointer data2);
|
|
register GMarshalFunc_VOID__STRING_INT_STRING callback;
|
|
register GCClosure* cc = (GCClosure*) closure;
|
|
register gpointer data1, data2;
|
|
|
|
g_return_if_fail (n_param_values == 4);
|
|
|
|
if (G_CCLOSURE_SWAP_DATA (closure))
|
|
{
|
|
data1 = closure->data;
|
|
data2 = g_value_peek_pointer (param_values + 0);
|
|
}
|
|
else
|
|
{
|
|
data1 = g_value_peek_pointer (param_values + 0);
|
|
data2 = closure->data;
|
|
}
|
|
callback = (GMarshalFunc_VOID__STRING_INT_STRING) (marshal_data
|
|
? marshal_data : cc->callback);
|
|
callback (data1,
|
|
(gchar*)g_value_get_string (param_values + 1),
|
|
g_value_get_int (param_values + 2),
|
|
(gchar*)g_value_get_string (param_values + 3),
|
|
data2);
|
|
}
|
|
|
|
static void
|
|
midori_view_class_init (MidoriViewClass* class)
|
|
{
|
|
GObjectClass* gobject_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[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);
|
|
|
|
signals[SEARCH_TEXT] = g_signal_new (
|
|
"search-text",
|
|
G_TYPE_FROM_CLASS (class),
|
|
(GSignalFlags)(G_SIGNAL_RUN_LAST),
|
|
0,
|
|
0,
|
|
NULL,
|
|
g_cclosure_marshal_VOID__BOOLEAN,
|
|
G_TYPE_NONE, 1,
|
|
G_TYPE_BOOLEAN);
|
|
|
|
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);
|
|
|
|
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;
|
|
|
|
flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT;
|
|
|
|
g_object_class_install_property (gobject_class,
|
|
PROP_SOCKET_ID,
|
|
g_param_spec_uint (
|
|
"socket-id",
|
|
_("Socket ID"),
|
|
_("The ID of a socket"),
|
|
0,
|
|
G_MAXUINT,
|
|
0,
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
|
|
|
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_object_class_install_property (gobject_class,
|
|
PROP_TITLE,
|
|
g_param_spec_string (
|
|
"title",
|
|
_("Title"),
|
|
_("The title of the currently loaded page"),
|
|
NULL,
|
|
G_PARAM_READWRITE));
|
|
|
|
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_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_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_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_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_object_class_install_property (gobject_class,
|
|
PROP_SETTINGS,
|
|
g_param_spec_object (
|
|
"settings",
|
|
_("Settings"),
|
|
_("The associated settings"),
|
|
MIDORI_TYPE_WEB_SETTINGS,
|
|
G_PARAM_READWRITE));
|
|
}
|
|
|
|
#define midori_view_is_socket(view) !view->socket_id
|
|
#define midori_view_is_plug(view) view->socket_id > 0
|
|
|
|
#if 0
|
|
#define midori_debug g_debug
|
|
#else
|
|
#define midori_debug(...) ;
|
|
#endif
|
|
|
|
/**
|
|
* int_to_str
|
|
* @in: an integer
|
|
*
|
|
* Converts an integer to a string.
|
|
*
|
|
* The returned string is valid until
|
|
* the next call to this function.
|
|
*
|
|
* Return value: a string
|
|
**/
|
|
static const gchar*
|
|
int_to_str (gint in)
|
|
{
|
|
static gchar* out = NULL;
|
|
g_free (out);
|
|
out = g_strdup_printf ("%d", in);
|
|
return out;
|
|
}
|
|
|
|
/**
|
|
* float_to_str
|
|
* @in: a float
|
|
*
|
|
* Converts a float to a string.
|
|
*
|
|
* The returned string is valid until
|
|
* the next call to this function.
|
|
*
|
|
* Return value: a string
|
|
**/
|
|
static const gchar*
|
|
float_to_str (gfloat in)
|
|
{
|
|
static gchar* out = NULL;
|
|
g_free (out);
|
|
out = g_strdup_printf ("%f", in);
|
|
return out;
|
|
}
|
|
|
|
static void
|
|
send_command (MidoriView* view,
|
|
const gchar* command,
|
|
const gchar* argument)
|
|
{
|
|
gchar* data;
|
|
gchar* cache;
|
|
|
|
if (argument)
|
|
data = g_strdup_printf ("%s %s", command, argument);
|
|
else
|
|
data = g_strdup (command);
|
|
|
|
if (!view->output)
|
|
{
|
|
/* The output is not ready, so we cache for now */
|
|
cache = g_strdup_printf ("%s\n%s",
|
|
view->command_cache ? view->command_cache : "", data);
|
|
katze_assign (view->command_cache, cache);
|
|
midori_debug ("!view->output, caching command: %s", command);
|
|
return;
|
|
}
|
|
|
|
fwrite (data, strlen (data) + 1, 1, view->output);
|
|
fflush (view->output);
|
|
|
|
g_free (data);
|
|
}
|
|
|
|
static void
|
|
midori_view_notify_uri_cb (MidoriView* view,
|
|
GParamSpec pspec)
|
|
{
|
|
if (midori_view_is_socket (view) && view->item)
|
|
katze_item_set_uri (view->item, view->uri);
|
|
|
|
if (midori_view_is_plug (view))
|
|
/* We must not send a NULL string here */
|
|
send_command (view, "uri", view->uri ? view->uri : "");
|
|
}
|
|
|
|
static void
|
|
midori_view_notify_icon_cb (MidoriView* view,
|
|
GParamSpec pspec)
|
|
{
|
|
if (view->tab_icon)
|
|
katze_throbber_set_static_pixbuf (KATZE_THROBBER (view->tab_icon),
|
|
view->icon);
|
|
if (view->menu_item)
|
|
gtk_image_menu_item_set_image (
|
|
GTK_IMAGE_MENU_ITEM (view->menu_item),
|
|
gtk_image_new_from_pixbuf (view->icon));
|
|
}
|
|
|
|
#if HAVE_GIO
|
|
void
|
|
loadable_icon_finish_cb (GdkPixbuf* icon,
|
|
GAsyncResult* res,
|
|
MidoriView* view)
|
|
{
|
|
GdkPixbuf* pixbuf;
|
|
GInputStream* stream;
|
|
GError* error;
|
|
GdkPixbuf* pixbuf_scaled;
|
|
gint icon_width, icon_height;
|
|
|
|
pixbuf = NULL;
|
|
stream = g_loadable_icon_load_finish (G_LOADABLE_ICON (icon),
|
|
res, NULL, NULL);
|
|
if (stream)
|
|
{
|
|
error = NULL;
|
|
pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, &error);
|
|
if (error)
|
|
midori_debug ("Icon couldn't be loaded: %s", error->message);
|
|
g_object_unref (stream);
|
|
}
|
|
if (!pixbuf)
|
|
pixbuf = gtk_widget_render_icon (GTK_WIDGET (view),
|
|
GTK_STOCK_FILE, GTK_ICON_SIZE_MENU, NULL);
|
|
|
|
gtk_icon_size_lookup (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_object_assign (view->icon, pixbuf_scaled);
|
|
g_object_notify (G_OBJECT (view), "icon");
|
|
}
|
|
|
|
void
|
|
file_info_finish_cb (GFile* icon_file,
|
|
GAsyncResult* res,
|
|
MidoriView* view)
|
|
{
|
|
GFileInfo* info;
|
|
const gchar* content_type;
|
|
GIcon* icon;
|
|
GFile* parent;
|
|
GFile* file;
|
|
GdkPixbuf* pixbuf;
|
|
gint icon_width, icon_height;
|
|
GdkPixbuf* pixbuf_scaled;
|
|
|
|
info = g_file_query_info_finish (G_FILE (icon_file), res, NULL);
|
|
if (info)
|
|
{
|
|
content_type = g_file_info_get_content_type (info);
|
|
if (g_str_has_prefix (content_type, "image/"))
|
|
{
|
|
icon = g_file_icon_new (icon_file);
|
|
g_loadable_icon_load_async (G_LOADABLE_ICON (icon),
|
|
0, NULL, (GAsyncReadyCallback)loadable_icon_finish_cb, view);
|
|
return;
|
|
}
|
|
}
|
|
|
|
file = g_file_get_parent (icon_file);
|
|
parent = g_file_get_parent (file);
|
|
/* We need to check if file equals the parent due to a GIO bug */
|
|
if (parent && !g_file_equal (file, parent))
|
|
{
|
|
icon_file = g_file_get_child (parent, "favicon.ico");
|
|
g_file_query_info_async (icon_file,
|
|
G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
|
|
G_FILE_QUERY_INFO_NONE, 0, NULL,
|
|
(GAsyncReadyCallback)file_info_finish_cb, view);
|
|
return;
|
|
}
|
|
|
|
pixbuf = gtk_widget_render_icon (GTK_WIDGET (view),
|
|
GTK_STOCK_FILE, GTK_ICON_SIZE_MENU, NULL);
|
|
gtk_icon_size_lookup (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);
|
|
|
|
view->icon = pixbuf_scaled;
|
|
g_object_notify (G_OBJECT (view), "icon");
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
_midori_web_view_load_icon (MidoriView* view)
|
|
{
|
|
#if HAVE_GIO
|
|
GFile* file;
|
|
GFile* icon_file;
|
|
#endif
|
|
GdkPixbuf* pixbuf;
|
|
gint icon_width, icon_height;
|
|
GdkPixbuf* pixbuf_scaled;
|
|
|
|
#if HAVE_GIO
|
|
if (view->uri)
|
|
{
|
|
file = g_file_new_for_uri (view->uri);
|
|
icon_file = g_file_get_child (file, "favicon.ico");
|
|
g_file_query_info_async (icon_file,
|
|
G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
|
|
G_FILE_QUERY_INFO_NONE, 0, NULL,
|
|
(GAsyncReadyCallback)file_info_finish_cb, view);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
pixbuf = gtk_widget_render_icon (GTK_WIDGET (view),
|
|
GTK_STOCK_FILE, GTK_ICON_SIZE_MENU, NULL);
|
|
gtk_icon_size_lookup (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);
|
|
|
|
view->icon = pixbuf_scaled;
|
|
g_object_notify (G_OBJECT (view), "icon");
|
|
}
|
|
|
|
static void
|
|
midori_view_notify_load_status_cb (MidoriView* view,
|
|
GParamSpec pspec)
|
|
{
|
|
view->can_go_back = midori_view_can_go_back (view);
|
|
view->can_go_forward = midori_view_can_go_forward (view);
|
|
|
|
if (midori_view_is_socket (view))
|
|
{
|
|
if (view->tab_icon)
|
|
katze_throbber_set_animated (KATZE_THROBBER (view->tab_icon),
|
|
view->load_status != MIDORI_LOAD_FINISHED);
|
|
}
|
|
|
|
if (midori_view_is_plug (view))
|
|
{
|
|
send_command (view, "load-status", int_to_str (view->load_status));
|
|
send_command (view, "can-go-back", int_to_str (view->can_go_back));
|
|
send_command (view, "can-go-forward", int_to_str (view->can_go_forward));
|
|
}
|
|
|
|
if (!midori_view_is_plug (view))
|
|
if (view->load_status == MIDORI_LOAD_COMMITTED)
|
|
_midori_web_view_load_icon (view);
|
|
}
|
|
|
|
static void
|
|
midori_view_notify_progress_cb (MidoriView* view,
|
|
GParamSpec pspec)
|
|
{
|
|
if (midori_view_is_plug (view))
|
|
send_command (view, "progress", float_to_str (view->progress));
|
|
}
|
|
|
|
static void
|
|
midori_view_action_cb (MidoriView* view,
|
|
const gchar* action)
|
|
{
|
|
if (midori_view_is_socket (view))
|
|
return;
|
|
|
|
send_command (view, "activate-action", action);
|
|
}
|
|
|
|
static void
|
|
midori_view_console_message_cb (MidoriView* view,
|
|
const gchar* message,
|
|
gint line,
|
|
const gchar* source_id)
|
|
{
|
|
gchar* argument;
|
|
|
|
if (midori_view_is_socket (view))
|
|
return;
|
|
|
|
argument = g_strdup_printf ("%s %d %s", message, line, source_id);
|
|
send_command (view, "console-message", argument);
|
|
g_free (argument);
|
|
}
|
|
|
|
static void
|
|
midori_view_new_tab_cb (MidoriView* view,
|
|
const gchar* uri,
|
|
gboolean background)
|
|
{
|
|
gchar* argument;
|
|
|
|
if (midori_view_is_socket (view))
|
|
return;
|
|
|
|
/* (uri, background) => (background, uri) */
|
|
argument = g_strdup_printf ("%d %s", background, uri);
|
|
send_command (view, "new-tab", argument);
|
|
g_free (argument);
|
|
}
|
|
|
|
static void
|
|
midori_view_new_window_cb (MidoriView* view,
|
|
const gchar* uri)
|
|
{
|
|
if (midori_view_is_socket (view))
|
|
return;
|
|
|
|
send_command (view, "new-window", uri);
|
|
}
|
|
|
|
static void
|
|
midori_view_search_text_cb (MidoriView* view,
|
|
gboolean found)
|
|
{
|
|
if (!midori_view_is_plug (view))
|
|
return;
|
|
|
|
send_command (view, "search-text", int_to_str (found));
|
|
}
|
|
|
|
static void
|
|
midori_view_add_bookmark_cb (MidoriView* view,
|
|
const gchar* uri)
|
|
{
|
|
if (midori_view_is_socket (view))
|
|
return;
|
|
|
|
send_command (view, "add-bookmark", uri);
|
|
}
|
|
|
|
static void
|
|
receive_status (MidoriView* view,
|
|
const gchar* command)
|
|
{
|
|
if (!strncmp (command, "uri ", 4))
|
|
{
|
|
katze_assign (view->uri, g_strdup (&command[4]));
|
|
g_object_notify (G_OBJECT (view), "uri");
|
|
}
|
|
else if (!strncmp (command, "title ", 6))
|
|
{
|
|
g_object_set (view, "title", &command[6], NULL);
|
|
}
|
|
else if (!strncmp (command, "load-status ", 12))
|
|
{
|
|
view->load_status = (MidoriLoadStatus)atoi (&command[12]);
|
|
g_object_notify (G_OBJECT (view), "load-status");
|
|
}
|
|
else if (!strncmp (command, "progress ", 9))
|
|
{
|
|
view->progress = atof (&command[9]);
|
|
g_object_notify (G_OBJECT (view), "progress");
|
|
}
|
|
else if (!strncmp (command, "zoom-level ", 11))
|
|
{
|
|
view->zoom_level = atof (&command[11]);
|
|
g_object_notify (G_OBJECT (view), "zoom-level");
|
|
}
|
|
else if (!strncmp (command, "can-go-back ", 12))
|
|
{
|
|
view->can_go_back = atoi (&command[12]);
|
|
}
|
|
else if (!strncmp (command, "can-go-forward ", 15))
|
|
{
|
|
view->can_go_forward = atoi (&command[15]);
|
|
}
|
|
else if (!strncmp (command, "statusbar-text ", 15))
|
|
{
|
|
g_object_set (view, "statusbar-text", &command[15], NULL);
|
|
}
|
|
else if (!strncmp (command, "activate-action ", 16))
|
|
{
|
|
g_signal_emit (view, signals[ACTIVATE_ACTION], 0, &command[16]);
|
|
}
|
|
else if (!strncmp (command, "console-message ", 16))
|
|
{
|
|
/* FIXME: Implement */
|
|
}
|
|
else if (!strncmp (command, "new-tab ", 8))
|
|
{
|
|
/* (background, uri) => (uri, background) */
|
|
g_signal_emit (view, signals[NEW_TAB], 0, &command[10], atoi (&command[8]));
|
|
}
|
|
else if (!strncmp (command, "new-window ", 11))
|
|
{
|
|
g_signal_emit (view, signals[NEW_WINDOW], 0, &command[11]);
|
|
}
|
|
else if (!strncmp (command, "search-text ", 12))
|
|
{
|
|
g_signal_emit (view, signals[SEARCH_TEXT], 0, atoi (&command[12]));
|
|
}
|
|
else if (!strncmp (command, "add-bookmark ", 13))
|
|
{
|
|
g_signal_emit (view, signals[ADD_BOOKMARK], 0, &command[13]);
|
|
}
|
|
else if (!strncmp (command, "clipboard ", 10))
|
|
{
|
|
view->can_cut_clipboard = atof (&command[10]);
|
|
view->can_copy_clipboard = atof (&command[12]);
|
|
view->can_paste_clipboard = atof (&command[14]);
|
|
midori_debug ("clipboards: %s => %d, %d, %d",
|
|
&command[10],
|
|
atoi (&command[10]), atoi (&command[12]), atoi (&command[14]));
|
|
}
|
|
else if (g_str_has_prefix (command, "**"))
|
|
{
|
|
g_print ("%s\n", command);
|
|
}
|
|
else
|
|
{
|
|
midori_debug ("receive_status: unknown command '%s'", command);
|
|
}
|
|
}
|
|
|
|
#define UPDATE_SETTING(name, value) \
|
|
g_object_set (webkit_web_view_get_settings ( \
|
|
WEBKIT_WEB_VIEW (view->web_view)), \
|
|
name, value, NULL)
|
|
|
|
static void
|
|
receive_command (MidoriView* view,
|
|
const gchar* command)
|
|
{
|
|
if (!strncmp (command, "set-uri ", 8))
|
|
midori_view_set_uri (view, &command[8]);
|
|
else if (!strncmp (command, "set-zoom-level ", 15))
|
|
midori_view_set_zoom_level (view, atof (&command[15]) / 10);
|
|
else if (!strncmp (command, "reload ", 7))
|
|
midori_view_reload (view, atoi (&command[7]));
|
|
else if (!strncmp (command, "stop-loading", 12))
|
|
midori_view_stop_loading (view);
|
|
else if (!strncmp (command, "go-back", 7))
|
|
midori_view_go_back (view);
|
|
else if (!strncmp (command, "go-forward", 10))
|
|
midori_view_go_forward (view);
|
|
else if (!strncmp (command, "print", 5))
|
|
midori_view_print (view);
|
|
else if (!strncmp (command, "unmark-matches", 14))
|
|
midori_view_unmark_text_matches (view);
|
|
else if (!strncmp (command, "search-text ", 12))
|
|
/* (forward, case_sensitive, text) => (text, case_sensitive, forward) */
|
|
midori_view_search_text (view, &command[16],
|
|
atoi (&command[14]), atoi (&command[12]));
|
|
else if (!strncmp (command, "mark-matches ", 13))
|
|
/* (case_sensitive, text) => (text, case_sensitive) */
|
|
midori_view_mark_text_matches (view, &command[17],
|
|
atoi (&command[15]));
|
|
else if (!strncmp (command, "hl-matches ", 11))
|
|
midori_view_set_highlight_text_matches (view, atoi (&command[11]));
|
|
else if (!strncmp (command, "dlmgr ", 6))
|
|
{
|
|
katze_assign (view->download_manager, g_strdup (&command[6]));
|
|
}
|
|
else if (!strncmp (command, "dffamily ", 9))
|
|
{
|
|
katze_assign (view->default_font_family, g_strdup (&command[9]));
|
|
UPDATE_SETTING ("default-font-family", view->default_font_family);
|
|
}
|
|
else if (!strncmp (command, "dfsize ", 7))
|
|
{
|
|
view->default_font_size = atoi (&command[7]);
|
|
UPDATE_SETTING ("default-font-size", view->default_font_size);
|
|
}
|
|
else if (!strncmp (command, "mfsize ", 7))
|
|
{
|
|
view->minimum_font_size = atoi (&command[7]);
|
|
UPDATE_SETTING ("minimum-font-size", view->minimum_font_size);
|
|
}
|
|
else if (!strncmp (command, "denc ", 5))
|
|
{
|
|
katze_assign (view->default_encoding, g_strdup (&command[5]));
|
|
UPDATE_SETTING ("default-encoding", view->default_encoding);
|
|
}
|
|
else if (!strncmp (command, "alimg ", 6))
|
|
{
|
|
view->auto_load_images = atoi (&command[6]);
|
|
UPDATE_SETTING ("auto-load-images", view->auto_load_images);
|
|
}
|
|
else if (!strncmp (command, "asimg ", 6))
|
|
{
|
|
view->auto_shrink_images = atoi (&command[6]);
|
|
UPDATE_SETTING ("auto-shrink-images", view->auto_shrink_images);
|
|
}
|
|
else if (!strncmp (command, "pbkg ", 5))
|
|
{
|
|
view->print_backgrounds = atoi (&command[5]);
|
|
UPDATE_SETTING ("print-backgrounds", view->print_backgrounds);
|
|
}
|
|
else if (!strncmp (command, "rta ", 4))
|
|
{
|
|
view->print_backgrounds = atoi (&command[4]);
|
|
UPDATE_SETTING ("resizable-text-areas", view->resizable_text_areas);
|
|
}
|
|
else if (!strncmp (command, "escripts ", 9))
|
|
{
|
|
view->enable_scripts = atoi (&command[9]);
|
|
UPDATE_SETTING ("enable-scripts", view->enable_scripts);
|
|
}
|
|
else if (!strncmp (command, "eplugins ", 9))
|
|
{
|
|
view->enable_plugins = atoi (&command[9]);
|
|
UPDATE_SETTING ("enable-plugins", view->enable_plugins);
|
|
}
|
|
else if (!strncmp (command, "mclksel ", 8))
|
|
{
|
|
view->middle_click_opens_selection = atoi (&command[8]);
|
|
}
|
|
else if (!strncmp (command, "tabsbkg ", 8))
|
|
{
|
|
view->open_tabs_in_the_background = atoi (&command[8]);
|
|
}
|
|
else if (!strncmp (command, "proxy ", 6))
|
|
{
|
|
katze_assign (view->http_proxy, g_strdup (&command[6]));
|
|
g_setenv ("http_proxy", view->http_proxy ? view->http_proxy : "", TRUE);
|
|
}
|
|
else if (g_str_has_prefix (command, "**"))
|
|
g_print ("%s\n", command);
|
|
else
|
|
midori_debug ("receive_command: unknown command '%s'", command);
|
|
}
|
|
|
|
static gboolean
|
|
io_input_watch_cb (GIOChannel* source,
|
|
GIOCondition condition,
|
|
MidoriView* view)
|
|
{
|
|
gchar* buffer;
|
|
GError* error;
|
|
|
|
error = NULL;
|
|
switch (condition)
|
|
{
|
|
case G_IO_PRI:
|
|
case G_IO_IN:
|
|
if (g_io_channel_read_line (source,
|
|
&buffer, NULL, NULL, &error) == G_IO_STATUS_NORMAL)
|
|
{
|
|
if (view->socket_id)
|
|
receive_command (view, buffer);
|
|
else
|
|
receive_status (view, buffer);
|
|
g_free (buffer);
|
|
}
|
|
else
|
|
{
|
|
g_warning ("Communication error: %s", error->message);
|
|
g_error_free (error);
|
|
}
|
|
break;
|
|
case G_IO_ERR:
|
|
case G_IO_NVAL:
|
|
g_warning ("Invalid operation");
|
|
return FALSE;
|
|
case G_IO_HUP:
|
|
midori_debug ("Tab closed");
|
|
return FALSE;
|
|
default:
|
|
g_warning ("Unexpected condition");
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
webkit_web_view_load_started_cb (WebKitWebView* web_view,
|
|
WebKitWebFrame* web_frame,
|
|
MidoriView* view)
|
|
{
|
|
view->window_object_cleared = FALSE;
|
|
|
|
view->load_status = MIDORI_LOAD_PROVISIONAL;
|
|
g_object_notify (G_OBJECT (view), "load-status");
|
|
|
|
view->progress = 0.0;
|
|
g_object_notify (G_OBJECT (view), "progress");
|
|
}
|
|
|
|
static void
|
|
webkit_web_view_window_object_cleared_cb (WebKitWebView* web_view,
|
|
WebKitWebFrame* web_frame,
|
|
JSGlobalContextRef js_context,
|
|
JSObjectRef js_window,
|
|
MidoriView* view)
|
|
{
|
|
view->window_object_cleared = TRUE;
|
|
}
|
|
|
|
static void
|
|
webkit_web_view_load_committed_cb (WebKitWebView* web_view,
|
|
WebKitWebFrame* web_frame,
|
|
MidoriView* view)
|
|
{
|
|
const gchar* uri;
|
|
GdkPixbuf* icon;
|
|
|
|
uri = webkit_web_frame_get_uri (web_frame);
|
|
katze_assign (view->uri, g_strdup (uri));
|
|
g_object_notify (G_OBJECT (view), "uri");
|
|
g_object_set (view, "title", NULL, NULL);
|
|
|
|
icon = gtk_widget_render_icon (GTK_WIDGET (view),
|
|
GTK_STOCK_FILE, GTK_ICON_SIZE_MENU, NULL);
|
|
katze_object_assign (view->icon, icon);
|
|
g_object_notify (G_OBJECT (view), "icon");
|
|
|
|
view->load_status = MIDORI_LOAD_COMMITTED;
|
|
g_object_notify (G_OBJECT (view), "load-status");
|
|
}
|
|
|
|
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");
|
|
}
|
|
|
|
/*
|
|
static void
|
|
gjs_value_links_foreach_cb (GjsValue* link,
|
|
MidoriView* view)
|
|
{
|
|
const gchar* type;
|
|
#if HAVE_GIO
|
|
const gchar* rel;
|
|
GFile* icon_file;
|
|
GIcon* icon;
|
|
#endif
|
|
|
|
if (gjs_value_is_object (link) && gjs_value_has_attribute (link, "href"))
|
|
{
|
|
if (gjs_value_has_attribute (link, "type"))
|
|
{
|
|
type = gjs_value_get_attribute_string (link, "type");
|
|
if (!strcmp (type, "application/rss+xml")
|
|
|| !strcmp (type, "application/x.atom+xml")
|
|
|| !strcmp (type, "application/atom+xml"))
|
|
{
|
|
katze_array_add_item (view->news_feeds, link);
|
|
g_signal_emit_by_name (view, "news-feed-ready",
|
|
gjs_value_get_attribute_string (link, "href"), type,
|
|
gjs_value_has_attribute (link, "title")
|
|
? gjs_value_get_attribute_string (link, "title") : NULL);
|
|
}
|
|
}
|
|
#if HAVE_GIO
|
|
if (gjs_value_has_attribute (link, "rel"))
|
|
{
|
|
rel = gjs_value_get_attribute_string (link, "rel");
|
|
if (!strcmp (rel, "icon") || !strcmp (rel, "shortcut icon"))
|
|
{
|
|
icon_file = g_file_new_for_uri (
|
|
gjs_value_get_attribute_string (link, "href"));
|
|
icon = g_file_icon_new (icon_file);
|
|
g_loadable_icon_load_async (G_LOADABLE_ICON (icon),
|
|
0, NULL, (GAsyncReadyCallback)loadable_icon_finish_cb, view);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
*/
|
|
|
|
static void
|
|
webkit_web_frame_load_done_cb (WebKitWebFrame* web_frame,
|
|
gboolean success,
|
|
MidoriView* view)
|
|
{
|
|
gchar* data;
|
|
JSContextRef js_context;
|
|
JSValueRef js_window;
|
|
/* GjsValue* value;
|
|
GjsValue* document;
|
|
GjsValue* links; */
|
|
|
|
if (!success)
|
|
{
|
|
midori_debug ("'%s' not found.", view->uri);
|
|
data = g_strdup_printf ("error:404 %s ", view->uri ? view->uri : "");
|
|
midori_view_set_uri (view, data);
|
|
g_free (data);
|
|
return;
|
|
}
|
|
|
|
/* If WebKit didn't emit the signal due to a bug, we will */
|
|
if (!view->window_object_cleared)
|
|
{
|
|
js_context = webkit_web_frame_get_global_context (web_frame);
|
|
js_window = JSContextGetGlobalObject (js_context);
|
|
g_signal_emit_by_name (view->web_view, "window-object-cleared",
|
|
web_frame, js_context, js_window);
|
|
}
|
|
|
|
/* js_context = webkit_web_frame_get_global_context (web_frame);
|
|
value = gjs_value_new (js_context, NULL);
|
|
document = gjs_value_get_by_name (value, "document");
|
|
links = gjs_value_get_elements_by_tag_name (document, "link");
|
|
katze_array_clear (web_view->news_feeds);
|
|
gjs_value_foreach (links, (GjsCallback)gjs_value_links_foreach_cb, web_view);
|
|
g_object_unref (links);
|
|
g_object_unref (document);
|
|
g_object_unref (value); */
|
|
|
|
view->load_status = MIDORI_LOAD_FINISHED;
|
|
g_object_notify (G_OBJECT (view), "load-status");
|
|
}
|
|
|
|
static void
|
|
webkit_web_view_load_finished_cb (WebKitWebView* web_view,
|
|
WebKitWebFrame* web_frame,
|
|
MidoriView* view)
|
|
{
|
|
view->progress = 1.0;
|
|
g_object_notify (G_OBJECT (view), "progress");
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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 void
|
|
webkit_web_view_hovering_over_link_cb (WebKitWebView* web_view,
|
|
const gchar* tooltip,
|
|
const gchar* link_uri,
|
|
MidoriView* view)
|
|
{
|
|
katze_assign (view->link_uri, g_strdup (link_uri));
|
|
g_object_set (G_OBJECT (view), "statusbar-text", link_uri, NULL);
|
|
}
|
|
|
|
static gboolean
|
|
gtk_widget_button_press_event_cb (WebKitWebView* web_view,
|
|
GdkEventButton* event,
|
|
MidoriView* view)
|
|
{
|
|
GdkModifierType state;
|
|
gint x, y;
|
|
GtkClipboard* clipboard;
|
|
gchar* uri;
|
|
gchar* new_uri;
|
|
const gchar* link_uri;
|
|
gboolean background;
|
|
|
|
gdk_window_get_pointer (NULL, &x, &y, &state);
|
|
link_uri = midori_view_get_link_uri (MIDORI_VIEW (view));
|
|
|
|
switch (event->button)
|
|
{
|
|
case 1:
|
|
if (!link_uri)
|
|
return FALSE;
|
|
if (state & GDK_SHIFT_MASK)
|
|
{
|
|
/* Open link in new window */
|
|
g_signal_emit_by_name (view, "new-window", link_uri);
|
|
return TRUE;
|
|
}
|
|
else if (state & GDK_MOD1_MASK)
|
|
{
|
|
/* Open link in new tab */
|
|
background = view->open_tabs_in_the_background;
|
|
if (state & GDK_CONTROL_MASK)
|
|
background = !background;
|
|
g_signal_emit_by_name (view, "new-tab", link_uri, background);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (link_uri)
|
|
{
|
|
/* Open link in new tab */
|
|
background = view->open_tabs_in_the_background;
|
|
if (state & GDK_CONTROL_MASK)
|
|
background = !background;
|
|
g_signal_emit_by_name (view, "new-tab", link_uri, background);
|
|
return TRUE;
|
|
}
|
|
else if (state & GDK_CONTROL_MASK)
|
|
{
|
|
midori_view_set_zoom_level (MIDORI_VIEW (view), 1.0);
|
|
return FALSE; /* Allow Ctrl + Middle click */
|
|
}
|
|
else if (view->middle_click_opens_selection)
|
|
{
|
|
state = (GdkModifierType) event->state;
|
|
clipboard = gtk_clipboard_get_for_display (
|
|
gtk_widget_get_display (GTK_WIDGET (view)),
|
|
GDK_SELECTION_PRIMARY);
|
|
uri = gtk_clipboard_wait_for_text (clipboard);
|
|
if (uri && strchr (uri, '.') && !strchr (uri, ' '))
|
|
{
|
|
new_uri = sokoke_magic_uri (uri, NULL);
|
|
if (state & GDK_CONTROL_MASK)
|
|
{
|
|
background = view->open_tabs_in_the_background;
|
|
if (state & GDK_CONTROL_MASK)
|
|
background = !background;
|
|
g_signal_emit_by_name (view, "new-tab", new_uri, background);
|
|
}
|
|
else
|
|
{
|
|
midori_view_set_uri (MIDORI_VIEW (view), new_uri);
|
|
gtk_widget_grab_focus (GTK_WIDGET (view));
|
|
}
|
|
g_free (new_uri);
|
|
g_free (uri);
|
|
return TRUE;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
gtk_widget_button_release_event_cb (WebKitWebView* web_view,
|
|
GdkEventButton* event,
|
|
MidoriView* view)
|
|
{
|
|
GtkClipboard* clipboard;
|
|
gchar* text;
|
|
|
|
/* Emulate the primary clipboard, which WebKit doesn't support */
|
|
text = webkit_web_view_get_selected_text (WEBKIT_WEB_VIEW (web_view));
|
|
clipboard = gtk_clipboard_get_for_display (
|
|
gtk_widget_get_display (GTK_WIDGET (web_view)), GDK_SELECTION_PRIMARY);
|
|
gtk_clipboard_set_text (clipboard, text, -1);
|
|
g_free (text);
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
gtk_widget_scroll_event_cb (WebKitWebView* web_view,
|
|
GdkEventScroll* event,
|
|
MidoriView* view)
|
|
{
|
|
GdkModifierType state = (GdkModifierType)0;
|
|
gint x, y;
|
|
|
|
gdk_window_get_pointer (NULL, &x, &y, &state);
|
|
if (state & GDK_CONTROL_MASK)
|
|
{
|
|
if (event->direction == GDK_SCROLL_DOWN)
|
|
webkit_web_view_zoom_out (WEBKIT_WEB_VIEW (web_view));
|
|
else if(event->direction == GDK_SCROLL_UP)
|
|
webkit_web_view_zoom_in (WEBKIT_WEB_VIEW (web_view));
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
midori_web_view_menu_new_tab_activate_cb (GtkWidget* widget,
|
|
MidoriView* view)
|
|
{
|
|
g_signal_emit (view, signals[NEW_TAB], 0, view->link_uri,
|
|
view->open_tabs_in_the_background);
|
|
}
|
|
|
|
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_download_activate_cb (GtkWidget* widget,
|
|
MidoriView* view)
|
|
{
|
|
sokoke_spawn_program (view->download_manager, view->link_uri);
|
|
}
|
|
|
|
static void
|
|
midori_web_view_menu_add_bookmark_activate_cb (GtkWidget* widget,
|
|
MidoriView* view)
|
|
{
|
|
g_signal_emit (view, signals[ADD_BOOKMARK], 0, view->link_uri);
|
|
}
|
|
|
|
static void
|
|
midori_web_view_menu_action_activate_cb (GtkWidget* widget,
|
|
MidoriView* view)
|
|
{
|
|
const gchar* action = g_object_get_data (G_OBJECT (widget), "action");
|
|
g_signal_emit_by_name (view, "activate-action", action);
|
|
}
|
|
|
|
static void
|
|
webkit_web_view_populate_popup_cb (WebKitWebView* web_view,
|
|
GtkWidget* menu,
|
|
MidoriView* view)
|
|
{
|
|
GtkWidget* menuitem;
|
|
GtkWidget* icon;
|
|
gchar* stock_id;
|
|
GdkScreen* screen;
|
|
GtkIconTheme* icon_theme;
|
|
GList* items;
|
|
|
|
/* We do not want to modify the Edit menu.
|
|
The only reliable indicator is inspecting the first item. */
|
|
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_CUT))
|
|
return;
|
|
}
|
|
|
|
if (view->link_uri)
|
|
{
|
|
menuitem = gtk_image_menu_item_new_with_mnemonic (
|
|
_("Open Link in New _Tab"));
|
|
screen = gtk_widget_get_screen (GTK_WIDGET (view));
|
|
icon_theme = gtk_icon_theme_get_for_screen (screen);
|
|
if (gtk_icon_theme_has_icon (icon_theme, STOCK_TAB_NEW))
|
|
{
|
|
icon = gtk_image_new_from_stock (STOCK_TAB_NEW, GTK_ICON_SIZE_MENU);
|
|
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon);
|
|
}
|
|
gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 1);
|
|
g_signal_connect (menuitem, "activate",
|
|
G_CALLBACK (midori_web_view_menu_new_tab_activate_cb), view);
|
|
gtk_widget_show (menuitem);
|
|
/* hack to implement New Window */
|
|
items = gtk_container_get_children (GTK_CONTAINER (menu));
|
|
menuitem = (GtkWidget*)g_list_nth_data (items, 2);
|
|
g_signal_connect (menuitem, "activate",
|
|
G_CALLBACK (midori_web_view_menu_new_window_activate_cb), view);
|
|
menuitem = (GtkWidget*)g_list_nth_data (items, 3);
|
|
/* hack to disable non-functional Download File */
|
|
gtk_widget_set_sensitive (menuitem, FALSE);
|
|
g_list_free (items);
|
|
if (view->download_manager && *view->download_manager)
|
|
{
|
|
menuitem = gtk_image_menu_item_new_with_mnemonic (
|
|
_("Download Link with Download _Manager"));
|
|
icon = gtk_image_new_from_stock (GTK_STOCK_SAVE_AS,
|
|
GTK_ICON_SIZE_MENU);
|
|
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon);
|
|
gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 4);
|
|
g_signal_connect (menuitem, "activate",
|
|
G_CALLBACK (midori_web_view_menu_download_activate_cb), view);
|
|
gtk_widget_show (menuitem);
|
|
}
|
|
menuitem = gtk_image_menu_item_new_from_stock (STOCK_BOOKMARK_ADD, NULL);
|
|
gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 5);
|
|
g_signal_connect (menuitem, "activate",
|
|
G_CALLBACK (midori_web_view_menu_add_bookmark_activate_cb), view);
|
|
gtk_widget_show (menuitem);
|
|
}
|
|
|
|
if (!view->link_uri && midori_view_has_selection (view))
|
|
{
|
|
if (strchr (view->selected_text, '.')
|
|
&& !strchr (view->selected_text, ' '))
|
|
{
|
|
menuitem = gtk_image_menu_item_new_with_mnemonic (
|
|
_("Open URL in New _Tab"));
|
|
icon = gtk_image_new_from_stock (GTK_STOCK_JUMP_TO,
|
|
GTK_ICON_SIZE_MENU);
|
|
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon);
|
|
gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, -1);
|
|
g_object_set_data (G_OBJECT (menuitem), "uri", view->selected_text);
|
|
g_signal_connect (menuitem, "activate",
|
|
G_CALLBACK (midori_web_view_menu_new_tab_activate_cb), view);
|
|
gtk_widget_show (menuitem);
|
|
}
|
|
/* FIXME: view selection source */
|
|
}
|
|
|
|
if (!view->link_uri && !midori_view_has_selection (view))
|
|
{
|
|
/* FIXME: Make this sensitive only when there is a tab to undo */
|
|
menuitem = gtk_image_menu_item_new_with_mnemonic (_("Undo Close Tab"));
|
|
icon = gtk_image_new_from_stock (GTK_STOCK_UNDELETE, GTK_ICON_SIZE_MENU);
|
|
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
|
g_object_set_data (G_OBJECT (menuitem), "action", "UndoTabClose");
|
|
g_signal_connect (menuitem, "activate",
|
|
G_CALLBACK (midori_web_view_menu_action_activate_cb), view);
|
|
gtk_widget_show (menuitem);
|
|
menuitem = gtk_separator_menu_item_new ();
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
|
gtk_widget_show (menuitem);
|
|
menuitem = gtk_image_menu_item_new_from_stock (STOCK_BOOKMARK_ADD, NULL);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
|
g_object_set_data (G_OBJECT (menuitem), "action", "BookmarkAdd");
|
|
g_signal_connect (menuitem, "activate",
|
|
G_CALLBACK (midori_web_view_menu_action_activate_cb), view);
|
|
gtk_widget_show (menuitem);
|
|
menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_SAVE_AS, NULL);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
|
g_object_set_data (G_OBJECT (menuitem), "action", "SaveAs");
|
|
g_signal_connect (menuitem, "activate",
|
|
G_CALLBACK (midori_web_view_menu_action_activate_cb), view);
|
|
gtk_widget_show (menuitem);
|
|
/* FIXME: Make this sensitive once it's implemented */
|
|
gtk_widget_set_sensitive (menuitem, FALSE);
|
|
menuitem = gtk_image_menu_item_new_with_mnemonic (_("View _Source"));
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
|
g_object_set_data (G_OBJECT (menuitem), "action", "SourceView");
|
|
g_signal_connect (menuitem, "activate",
|
|
G_CALLBACK (midori_web_view_menu_action_activate_cb), view);
|
|
gtk_widget_show (menuitem);
|
|
#if !HAVE_GIO
|
|
gtk_widget_set_sensitive (menuitem, FALSE);
|
|
#endif
|
|
menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_PRINT, NULL);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
|
g_object_set_data (G_OBJECT (menuitem), "action", "Print");
|
|
g_signal_connect (menuitem, "activate",
|
|
G_CALLBACK (midori_web_view_menu_action_activate_cb), view);
|
|
gtk_widget_show (menuitem);
|
|
}
|
|
}
|
|
|
|
static void
|
|
webkit_web_view_console_message_cb (GtkWidget* web_view,
|
|
const gchar* message,
|
|
guint line,
|
|
const gchar* source_id,
|
|
MidoriView* view)
|
|
{
|
|
g_signal_emit_by_name (view, "console-message", message, line, source_id);
|
|
}
|
|
|
|
static gboolean
|
|
gtk_widget_focus_out_event_cb (GtkWidget* web_view,
|
|
GdkEventFocus* event,
|
|
MidoriView* view)
|
|
{
|
|
gchar* data;
|
|
|
|
data = g_strdup_printf ("%d %d %d",
|
|
midori_view_can_cut_clipboard (view),
|
|
midori_view_can_copy_clipboard (view),
|
|
midori_view_can_paste_clipboard (view));
|
|
send_command (view, "clipboard", data);
|
|
g_free (data);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
midori_view_realize (MidoriView* view)
|
|
{
|
|
WebKitWebFrame* web_frame;
|
|
|
|
view->web_view = webkit_web_view_new ();
|
|
/* Adjustments are not created automatically */
|
|
g_object_set (view, "hadjustment", NULL, "vadjustment", NULL, NULL);
|
|
|
|
/* FIXME: Strictly we should send a command to query
|
|
the policy or send it as an argument */
|
|
/* The socket view is not supposed to scroll at all */
|
|
if (midori_view_is_socket (view))
|
|
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (view),
|
|
GTK_POLICY_NEVER, GTK_POLICY_NEVER);
|
|
/* The plug view should use the policy of the socket */
|
|
if (midori_view_is_plug (view))
|
|
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (view),
|
|
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
|
|
|
gtk_widget_show (view->web_view);
|
|
|
|
web_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (view->web_view));
|
|
|
|
g_object_connect (view->web_view,
|
|
"signal::load-started",
|
|
webkit_web_view_load_started_cb, view,
|
|
"signal::window-object-cleared",
|
|
webkit_web_view_window_object_cleared_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,
|
|
"signal::title-changed",
|
|
webkit_web_view_title_changed_cb, view,
|
|
"signal::status-bar-text-changed",
|
|
webkit_web_view_statusbar_text_changed_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::button-release-event",
|
|
gtk_widget_button_release_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::focus-out-event",
|
|
gtk_widget_focus_out_event_cb, view,
|
|
NULL);
|
|
g_object_connect (web_frame,
|
|
"signal::load-done",
|
|
webkit_web_frame_load_done_cb, view,
|
|
NULL);
|
|
|
|
gtk_container_add (GTK_CONTAINER (view), view->web_view);
|
|
if (view->premature_uri)
|
|
{
|
|
midori_debug ("Loading premature uri '%s' now", view->premature_uri);
|
|
midori_view_set_uri (view, view->premature_uri);
|
|
}
|
|
katze_assign (view->premature_uri, NULL);
|
|
}
|
|
|
|
static void
|
|
gtk_socket_realize_cb (GtkWidget* socket,
|
|
MidoriView* view)
|
|
{
|
|
gchar* socket_id;
|
|
GError* error;
|
|
gboolean success;
|
|
gint stdin;
|
|
gint stdout;
|
|
gchar* argv[] = { NULL, "--id", NULL, NULL };
|
|
|
|
/* Sockets are not supported on all platforms,
|
|
so fallback to working without any socket or plug. */
|
|
if (!gtk_socket_get_id (GTK_SOCKET (socket)))
|
|
{
|
|
gtk_widget_destroy (socket);
|
|
midori_view_realize (view);
|
|
return;
|
|
}
|
|
|
|
socket_id = g_strdup_printf ("%d", gtk_socket_get_id (GTK_SOCKET (socket)));
|
|
argv[0] = (gchar*)sokoke_remember_argv0 (NULL);
|
|
argv[2] = socket_id;
|
|
error = NULL;
|
|
success = g_spawn_async_with_pipes (NULL, argv, NULL, G_SPAWN_SEARCH_PATH,
|
|
NULL, NULL, NULL,
|
|
&stdin, &stdout, NULL, &error);
|
|
g_free (socket_id);
|
|
|
|
if (!success)
|
|
{
|
|
/* Fallback to operating without a socket */
|
|
view->socket_id = 0;
|
|
midori_view_realize (view);
|
|
|
|
g_error_free (error);
|
|
return;
|
|
}
|
|
|
|
view->output = fdopen (stdin, "w");
|
|
view->input = g_io_channel_unix_new (stdout);
|
|
g_io_channel_set_close_on_unref (view->input, TRUE);
|
|
g_io_add_watch (view->input,
|
|
G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_NVAL | G_IO_HUP,
|
|
(GIOFunc)io_input_watch_cb, view);
|
|
|
|
if (view->command_cache)
|
|
{
|
|
/* Send cached commands if any */
|
|
fwrite (view->command_cache,
|
|
strlen (view->command_cache) + 1, 1, view->output);
|
|
katze_assign (view->command_cache, NULL);
|
|
fflush (view->output);
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
gtk_socket_plug_removed_cb (GtkWidget* socket,
|
|
MidoriView* view)
|
|
{
|
|
if (view->output)
|
|
{
|
|
fclose (view->output);
|
|
view->output = NULL;
|
|
}
|
|
|
|
if (view->input)
|
|
{
|
|
g_io_channel_unref (view->input);
|
|
view->input = NULL;
|
|
}
|
|
|
|
midori_debug ("'%s' died.", view->uri);
|
|
send_command (view, "set-uri error:died", view->uri ? view->uri : "");
|
|
if (GTK_WIDGET_REALIZED (view))
|
|
gtk_socket_realize_cb (socket, view);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
midori_view_realize_cb (MidoriView* view)
|
|
{
|
|
GtkWidget* plug;
|
|
GtkWidget* socket;
|
|
|
|
if (midori_view_is_plug (view))
|
|
{
|
|
plug = gtk_plug_new (view->socket_id);
|
|
midori_view_realize (view);
|
|
gtk_widget_show (plug);
|
|
|
|
view->input = g_io_channel_unix_new (0); /* 0 is stdin */
|
|
g_io_channel_set_close_on_unref (view->input, TRUE);
|
|
g_io_add_watch (view->input,
|
|
G_IO_IN | G_IO_ERR | G_IO_NVAL | G_IO_HUP,
|
|
(GIOFunc)io_input_watch_cb, view);
|
|
view->output = fdopen (1, "w"); /* 1 is stdout */
|
|
}
|
|
else if (midori_view_is_socket (view))
|
|
{
|
|
socket = gtk_socket_new ();
|
|
g_signal_connect (socket, "realize",
|
|
G_CALLBACK (gtk_socket_realize_cb), view);
|
|
g_signal_connect (socket, "plug-removed",
|
|
G_CALLBACK (gtk_socket_plug_removed_cb), view);
|
|
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (view),
|
|
GTK_WIDGET (socket));
|
|
gtk_widget_show (socket);
|
|
}
|
|
}
|
|
|
|
static void
|
|
midori_view_init (MidoriView* view)
|
|
{
|
|
view->command_cache = NULL;
|
|
view->premature_uri = NULL;
|
|
view->uri = NULL;
|
|
view->title = NULL;
|
|
view->icon = gtk_widget_render_icon (GTK_WIDGET (view), GTK_STOCK_FILE,
|
|
GTK_ICON_SIZE_MENU, NULL);
|
|
view->progress = 0.0;
|
|
view->load_status = MIDORI_LOAD_FINISHED;
|
|
view->statusbar_text = NULL;
|
|
view->link_uri = NULL;
|
|
view->selected_text = NULL;
|
|
view->settings = NULL;
|
|
view->item = NULL;
|
|
|
|
view->download_manager = NULL;
|
|
view->default_font_family = NULL;
|
|
view->default_encoding = NULL;
|
|
view->http_proxy = NULL;
|
|
|
|
g_object_connect (view,
|
|
"signal::notify::uri",
|
|
midori_view_notify_uri_cb, NULL,
|
|
"signal::notify::icon",
|
|
midori_view_notify_icon_cb, NULL,
|
|
"signal::notify::load-status",
|
|
midori_view_notify_load_status_cb, NULL,
|
|
"signal::notify::progress",
|
|
midori_view_notify_progress_cb, NULL,
|
|
"signal::realize",
|
|
midori_view_realize_cb, NULL,
|
|
"signal::activate-action",
|
|
midori_view_action_cb, NULL,
|
|
"signal::console-message",
|
|
midori_view_console_message_cb, NULL,
|
|
"signal::new-tab",
|
|
midori_view_new_tab_cb, NULL,
|
|
"signal::new-window",
|
|
midori_view_new_window_cb, NULL,
|
|
"signal::search-text",
|
|
midori_view_search_text_cb, NULL,
|
|
"signal::add-bookmark",
|
|
midori_view_add_bookmark_cb, NULL,
|
|
NULL);
|
|
}
|
|
|
|
static void
|
|
midori_view_finalize (GObject* object)
|
|
{
|
|
MidoriView* view;
|
|
/* WebKitWebFrame* web_frame; */
|
|
|
|
view = MIDORI_VIEW (object);
|
|
|
|
g_free (view->command_cache);
|
|
g_free (view->premature_uri);
|
|
g_free (view->uri);
|
|
g_free (view->title);
|
|
if (view->icon)
|
|
g_object_unref (view->icon);
|
|
g_free (view->statusbar_text);
|
|
g_free (view->link_uri);
|
|
g_free (view->selected_text);
|
|
if (view->settings)
|
|
g_object_unref (view->settings);
|
|
if (view->item)
|
|
g_object_unref (view->item);
|
|
|
|
g_free (view->download_manager);
|
|
|
|
/* web_frame = webkit_web_view_get_main_frame
|
|
(WEBKIT_WEB_VIEW (view->web_view));
|
|
g_signal_handlers_disconnect_by_func (web_frame,
|
|
webkit_web_frame_load_done, view); */
|
|
|
|
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_SOCKET_ID:
|
|
view->socket_id = g_value_get_uint (value);
|
|
break;
|
|
case PROP_TITLE:
|
|
katze_assign (view->title, g_value_dup_string (value));
|
|
if (!midori_view_is_plug (view))
|
|
{
|
|
#define title midori_view_get_display_title (view)
|
|
if (view->tab_label)
|
|
{
|
|
gtk_label_set_text (GTK_LABEL (view->tab_title), 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);
|
|
if (view->item)
|
|
katze_item_set_name (view->item, title);
|
|
#undef title
|
|
}
|
|
if (midori_view_is_plug (view))
|
|
/* We must not send a NULL string here */
|
|
send_command (view, "title", view->title ? view->title : "");
|
|
break;
|
|
case PROP_ZOOM_LEVEL:
|
|
midori_view_set_zoom_level (view, g_value_get_float (value));
|
|
if (midori_view_is_plug (view))
|
|
send_command (view, "zoom-level", float_to_str (view->zoom_level));
|
|
break;
|
|
case PROP_STATUSBAR_TEXT:
|
|
katze_assign (view->statusbar_text, g_value_dup_string (value));
|
|
if (midori_view_is_plug (view))
|
|
/* We must not send a NULL string here */
|
|
send_command (view, "statusbar-text",
|
|
view->statusbar_text ? view->statusbar_text : "");
|
|
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_SOCKET_ID:
|
|
g_value_set_uint (value, view->socket_id);
|
|
break;
|
|
case PROP_URI:
|
|
g_value_set_string (value, view->uri);
|
|
break;
|
|
case PROP_TITLE:
|
|
g_value_set_string (value, view->title);
|
|
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_ZOOM_LEVEL:
|
|
g_value_set_float (value, midori_view_get_zoom_level (view));
|
|
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;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* midori_view_new:
|
|
* @view: a #MidoriView
|
|
*
|
|
* Creates a new view.
|
|
*
|
|
* Return value: a new #MidoriView
|
|
**/
|
|
GtkWidget*
|
|
midori_view_new (void)
|
|
{
|
|
return g_object_new (MIDORI_TYPE_VIEW, NULL);
|
|
}
|
|
|
|
/**
|
|
* midori_view_new_with_uri:
|
|
* @view: a #MidoriView
|
|
* @uri: an URI
|
|
*
|
|
* Creates a new view with a particular URI.
|
|
*
|
|
* This constructor supports opaque views and is
|
|
* in fact currently the only way to create them.
|
|
*
|
|
* The only currently supported opaque view is
|
|
* the source view, implementing a #MidoriSource.
|
|
* Pass an URI prefixed with "view-source:" in
|
|
* order to create a source view.
|
|
*
|
|
* Return value: a new #MidoriView
|
|
**/
|
|
GtkWidget*
|
|
midori_view_new_with_uri (const gchar* uri)
|
|
{
|
|
MidoriView* view;
|
|
gchar* title;
|
|
GtkWidget* widget;
|
|
|
|
view = g_object_new (MIDORI_TYPE_VIEW, NULL);
|
|
|
|
if (uri && g_str_has_prefix (uri, "view-source:"))
|
|
{
|
|
view->socket_id = -1;
|
|
katze_assign (view->uri, g_strdup (uri));
|
|
g_object_notify (G_OBJECT (view), "uri");
|
|
title = g_strdup_printf ("%s - %s", _("Source"), &uri[12]);
|
|
g_object_set (view, "title", title, NULL);
|
|
g_free (title);
|
|
katze_object_assign (view->icon,
|
|
gtk_widget_render_icon (GTK_WIDGET (view),
|
|
GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU, NULL));
|
|
widget = midori_source_new (&uri[12]);
|
|
/* Adjustments are not created automatically */
|
|
g_object_set (view, "hadjustment", NULL, "vadjustment", NULL, NULL);
|
|
gtk_container_add (GTK_CONTAINER (view), widget);
|
|
gtk_widget_show (widget);
|
|
}
|
|
else
|
|
midori_view_set_uri (view, uri);
|
|
|
|
return (GtkWidget*)view;
|
|
}
|
|
|
|
static void
|
|
_update_label_size (GtkWidget* label,
|
|
gint size)
|
|
{
|
|
gint width, height;
|
|
|
|
if (size < 1)
|
|
size = 10;
|
|
|
|
sokoke_widget_get_text_size (label, "M", &width, &height);
|
|
gtk_widget_set_size_request (label, width * size, -1);
|
|
gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
|
|
}
|
|
|
|
static void
|
|
_midori_view_update_settings (MidoriView* view)
|
|
{
|
|
g_object_get (view->settings,
|
|
"download-manager", &view->download_manager,
|
|
"default-font-family", &view->default_font_family,
|
|
"default-font-size", &view->default_font_size,
|
|
"minimum-font-size", &view->minimum_font_size,
|
|
"default-encoding", &view->default_encoding,
|
|
"auto-load-images", &view->auto_load_images,
|
|
"auto-shrink-images", &view->auto_shrink_images,
|
|
"print-backgrounds", &view->print_backgrounds,
|
|
"resizable-text-areas", &view->resizable_text_areas,
|
|
"enable-scripts", &view->enable_scripts,
|
|
"enable-plugins", &view->enable_plugins,
|
|
"close-buttons-on-tabs", &view->close_buttons_on_tabs,
|
|
"middle-click-opens-selection", &view->middle_click_opens_selection,
|
|
"open-tabs-in-the-background", &view->open_tabs_in_the_background,
|
|
"http-proxy", &view->http_proxy,
|
|
NULL);
|
|
|
|
if (midori_view_is_socket (view))
|
|
{
|
|
send_command (view, "dlmgr", view->download_manager);
|
|
send_command (view, "dffamily", view->default_font_family);
|
|
send_command (view, "dfsize", int_to_str (view->default_font_size));
|
|
send_command (view, "mfsize", int_to_str (view->minimum_font_size));
|
|
send_command (view, "denc", view->default_encoding);
|
|
send_command (view, "alimg", int_to_str (view->auto_load_images));
|
|
send_command (view, "asimg", int_to_str (view->auto_shrink_images));
|
|
send_command (view, "pbkg", int_to_str (view->print_backgrounds));
|
|
send_command (view, "rta", int_to_str (view->resizable_text_areas));
|
|
send_command (view, "escripts", int_to_str (view->enable_scripts));
|
|
send_command (view, "eplugins", int_to_str (view->enable_plugins));
|
|
send_command (view, "mclksel",
|
|
int_to_str (view->middle_click_opens_selection));
|
|
send_command (view, "tabsbkg",
|
|
int_to_str (view->open_tabs_in_the_background));
|
|
send_command (view, "proxy", view->http_proxy);
|
|
}
|
|
}
|
|
|
|
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 ("download-manager"))
|
|
{
|
|
katze_assign (view->download_manager, g_value_dup_string (&value));
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "dlmgr", view->download_manager);
|
|
}
|
|
else if (name == g_intern_string ("default-font-family"))
|
|
{
|
|
katze_assign (view->default_font_family, g_value_dup_string (&value));
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "dffamily", view->default_font_family);
|
|
}
|
|
else if (name == g_intern_string ("default-font-size"))
|
|
{
|
|
view->default_font_size = g_value_get_int (&value);
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "dfsize", int_to_str (view->default_font_size));
|
|
}
|
|
else if (name == g_intern_string ("minimum-font-size"))
|
|
{
|
|
view->minimum_font_size = g_value_get_int (&value);
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "mfsize", int_to_str (view->minimum_font_size));
|
|
}
|
|
else if (name == g_intern_string ("default-encoding"))
|
|
{
|
|
katze_assign (view->default_encoding, g_value_dup_string (&value));
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "denc", view->default_encoding);
|
|
}
|
|
else if (name == g_intern_string ("auto-load-images"))
|
|
{
|
|
view->auto_load_images = g_value_get_boolean (&value);
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "alimg", int_to_str (view->auto_load_images));
|
|
}
|
|
else if (name == g_intern_string ("auto-shrink-images"))
|
|
{
|
|
view->auto_shrink_images = g_value_get_boolean (&value);
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "asimg", int_to_str (view->auto_shrink_images));
|
|
}
|
|
else if (name == g_intern_string ("print-backgrounds"))
|
|
{
|
|
view->print_backgrounds = g_value_get_boolean (&value);
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "pbkg", int_to_str (view->print_backgrounds));
|
|
}
|
|
else if (name == g_intern_string ("resizable-text-areas"))
|
|
{
|
|
view->resizable_text_areas = g_value_get_boolean (&value);
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "rta", int_to_str (view->resizable_text_areas));
|
|
}
|
|
else if (name == g_intern_string ("enable-scripts"))
|
|
{
|
|
view->enable_scripts = g_value_get_boolean (&value);
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "escripts", int_to_str (view->enable_scripts));
|
|
}
|
|
else if (name == g_intern_string ("enable-plugins"))
|
|
{
|
|
view->enable_plugins = g_value_get_boolean (&value);
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "eplugins", int_to_str (view->enable_plugins));
|
|
}
|
|
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 ("middle-click-opens-selection"))
|
|
{
|
|
view->middle_click_opens_selection = g_value_get_boolean (&value);
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "mclksel",
|
|
int_to_str (view->middle_click_opens_selection));
|
|
}
|
|
else if (name == g_intern_string ("open-tabs-in-the-background"))
|
|
{
|
|
view->open_tabs_in_the_background = g_value_get_boolean (&value);
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "tabsbkg",
|
|
int_to_str (view->open_tabs_in_the_background));
|
|
}
|
|
else if (name == g_intern_string ("http-proxy"))
|
|
{
|
|
katze_assign (view->http_proxy, g_value_dup_string (&value));
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "proxy", view->http_proxy);
|
|
}
|
|
|
|
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)
|
|
{
|
|
if (view->settings)
|
|
g_signal_handlers_disconnect_by_func (view->settings,
|
|
midori_view_settings_notify_cb, view);
|
|
katze_object_assign (view->settings, g_object_ref (settings));
|
|
_midori_view_update_settings (view);
|
|
g_signal_connect (settings, "notify",
|
|
G_CALLBACK (midori_view_settings_notify_cb), view);
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* midori_view_set_uri:
|
|
* @view: a #MidoriView
|
|
*
|
|
* Opens the specified URI in the view.
|
|
*
|
|
* FIXME:
|
|
* If the view doesn't allow changing the URI it
|
|
* will automatically request a new tab.
|
|
**/
|
|
void
|
|
midori_view_set_uri (MidoriView* view,
|
|
const gchar* uri)
|
|
{
|
|
gchar* data;
|
|
|
|
g_return_if_fail (MIDORI_IS_VIEW (view));
|
|
|
|
if (midori_view_is_socket (view))
|
|
/* We must not send a NULL string here */
|
|
send_command (view, "set-uri", uri ? uri : "");
|
|
else
|
|
{
|
|
if (!view->web_view)
|
|
{
|
|
/* An URI is requested before the view was realized.
|
|
We special case this to load it when we are ready. */
|
|
midori_debug ("Deferring premature uri '%s'", uri);
|
|
katze_assign (view->premature_uri, g_strdup (uri));
|
|
return;
|
|
}
|
|
midori_debug ("Opening URI: %s", uri);
|
|
/* This is not prefectly elegant, but creating an
|
|
error page inline is the simplest solution. */
|
|
if (g_str_has_prefix (uri, "error:"))
|
|
{
|
|
data = NULL;
|
|
if (!strncmp (uri, "error:died ", 11))
|
|
{
|
|
katze_assign (view->uri, g_strdup (&uri[11]));
|
|
data = g_strdup_printf (
|
|
"<html><head><title>Page died - %s</title></head>"
|
|
"<body><h1>Page died - %s</h1>"
|
|
"<p />The page you were navigating on died."
|
|
"<p />Try to <a href=\"%s\">load the page again</a>, "
|
|
"or move on to another page."
|
|
"</body></html>",
|
|
view->uri, view->uri, view->uri);
|
|
}
|
|
else if (!strncmp (uri, "error:404 ", 10))
|
|
{
|
|
katze_assign (view->uri, g_strdup (&uri[10]));
|
|
data = g_strdup_printf (
|
|
"<html><head><title>Not found - %s</title></head>"
|
|
"<body><h1>Not found - %s</h1>"
|
|
"<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>",
|
|
view->uri, view->uri, view->uri);
|
|
}
|
|
if (data)
|
|
{
|
|
webkit_web_view_load_html_string (
|
|
WEBKIT_WEB_VIEW (view->web_view), data, view->uri);
|
|
g_free (data);
|
|
g_object_notify (G_OBJECT (view), "uri");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
katze_assign (view->uri, g_strdup (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 !(view->uri && *view->uri);
|
|
}
|
|
|
|
/**
|
|
* midori_view_get_icon:
|
|
* @view: a #MidoriView
|
|
*
|
|
* Retrieves the icon of the view.
|
|
*
|
|
* Return value: a #GdkPixbuf
|
|
**/
|
|
GdkPixbuf*
|
|
midori_view_get_icon (MidoriView* view)
|
|
{
|
|
g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL);
|
|
|
|
return view->icon;
|
|
}
|
|
|
|
/**
|
|
* midori_view_get_display_uri:
|
|
* @view: a #MidoriView
|
|
*
|
|
* Retrieves a string that is suitable for displaying,
|
|
* particularly an empty URI is represented as "about:blank".
|
|
*
|
|
* 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), "about:blank");
|
|
|
|
if (view->uri && *view->uri)
|
|
return view->uri;
|
|
return "about:blank";
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
*
|
|
* 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;
|
|
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);
|
|
|
|
if (midori_view_is_socket (view))
|
|
return view->has_selection;
|
|
else
|
|
{
|
|
view->selected_text = webkit_web_view_get_selected_text (
|
|
WEBKIT_WEB_VIEW (view->web_view));
|
|
if (view->selected_text && *view->selected_text)
|
|
return TRUE;
|
|
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_is_socket (view))
|
|
return view->selected_text;
|
|
else if (midori_view_has_selection (view))
|
|
return midori_view_get_selected_text (view);
|
|
else
|
|
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 (midori_view_is_socket (view))
|
|
return view->can_cut_clipboard;
|
|
else if (view->web_view)
|
|
{
|
|
view->can_cut_clipboard = webkit_web_view_can_cut_clipboard (
|
|
WEBKIT_WEB_VIEW (view->web_view));
|
|
return view->can_cut_clipboard;
|
|
}
|
|
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 (midori_view_is_socket (view))
|
|
return view->can_copy_clipboard;
|
|
else if (view->web_view)
|
|
{
|
|
view->can_copy_clipboard = webkit_web_view_can_copy_clipboard (
|
|
WEBKIT_WEB_VIEW (view->web_view));
|
|
return view->can_copy_clipboard;
|
|
}
|
|
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 (midori_view_is_socket (view))
|
|
return view->can_paste_clipboard;
|
|
else if (view->web_view)
|
|
{
|
|
view->can_paste_clipboard = webkit_web_view_can_paste_clipboard (
|
|
WEBKIT_WEB_VIEW (view->web_view));
|
|
return view->can_paste_clipboard;
|
|
}
|
|
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 = sokoke_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 gboolean
|
|
midori_view_tab_label_button_release_event (GtkWidget* tab_label,
|
|
GdkEventButton* event,
|
|
GtkWidget* widget)
|
|
{
|
|
if (event->button == 2)
|
|
{
|
|
/* Close the widget on middle click */
|
|
gtk_widget_destroy (widget);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
midori_view_tab_icon_style_set (GtkWidget* tab_icon,
|
|
GtkStyle* previous_style)
|
|
{
|
|
GtkSettings* gtk_settings;
|
|
gint width, height;
|
|
|
|
gtk_settings = gtk_widget_get_settings (tab_icon);
|
|
gtk_icon_size_lookup_for_settings (gtk_settings, GTK_ICON_SIZE_MENU,
|
|
&width, &height);
|
|
gtk_widget_set_size_request (tab_icon, width + 2, height + 2);
|
|
}
|
|
|
|
static void
|
|
midori_view_tab_close_clicked (GtkWidget* tab_close,
|
|
GtkWidget* widget)
|
|
{
|
|
gtk_widget_destroy (widget);
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
*
|
|
* 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;
|
|
|
|
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));
|
|
|
|
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_border_width (GTK_CONTAINER (hbox), 2);
|
|
gtk_container_add (GTK_CONTAINER (event_box), GTK_WIDGET (hbox));
|
|
gtk_misc_set_alignment (GTK_MISC (view->tab_icon), 0.0, 0.5);
|
|
gtk_box_pack_start (GTK_BOX (hbox), view->tab_icon, FALSE, FALSE, 0);
|
|
gtk_misc_set_alignment (GTK_MISC (view->tab_title), 0.0, 0.5);
|
|
/* TODO: make the tab initially look "unvisited" until it's focused */
|
|
gtk_box_pack_start (GTK_BOX (hbox), view->tab_title, FALSE, TRUE, 0);
|
|
_update_label_size (view->tab_title, 10);
|
|
|
|
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 = katze_throbber_new ();
|
|
katze_throbber_set_static_stock_id (KATZE_THROBBER (image),
|
|
GTK_STOCK_CLOSE);
|
|
gtk_button_set_image (GTK_BUTTON (view->tab_close), image);
|
|
gtk_misc_set_alignment (GTK_MISC (image), 0.0, 0.0);
|
|
gtk_box_pack_end (GTK_BOX (hbox), view->tab_close, FALSE, FALSE, 0);
|
|
gtk_widget_show_all (GTK_WIDGET (event_box));
|
|
|
|
if (view->settings &&
|
|
!sokoke_object_get_boolean (view->settings, "close-buttons-on-tabs"))
|
|
gtk_widget_hide (view->tab_close);
|
|
|
|
g_signal_connect (event_box, "button-release-event",
|
|
G_CALLBACK (midori_view_tab_label_button_release_event), view);
|
|
g_signal_connect (view->tab_close, "style-set",
|
|
G_CALLBACK (midori_view_tab_icon_style_set), 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_label, "destroy",
|
|
G_CALLBACK (gtk_widget_destroyed),
|
|
&view->tab_label);
|
|
}
|
|
return view->tab_label;
|
|
}
|
|
|
|
/**
|
|
* 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 is created on the first call and will be updated to reflect
|
|
* changes to the title and uri automatically.
|
|
*
|
|
* Return value: the proxy #KatzeItem
|
|
**/
|
|
KatzeItem*
|
|
midori_view_get_proxy_item (MidoriView* view)
|
|
{
|
|
const gchar* uri;
|
|
const gchar* title;
|
|
|
|
g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL);
|
|
|
|
if (!view->item)
|
|
{
|
|
view->item = katze_item_new ();
|
|
uri = midori_view_get_display_uri (view);
|
|
katze_item_set_uri (view->item, uri);
|
|
title = midori_view_get_display_title (view);
|
|
katze_item_set_name (view->item, title);
|
|
}
|
|
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.0);
|
|
|
|
if (midori_view_is_socket (view))
|
|
return view->zoom_level;
|
|
else if (view->web_view)
|
|
return webkit_web_view_get_zoom_level (WEBKIT_WEB_VIEW (view->web_view));
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* 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));
|
|
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "set-zoom-level", float_to_str (zoom_level));
|
|
else
|
|
webkit_web_view_set_zoom_level (
|
|
WEBKIT_WEB_VIEW (view->web_view), zoom_level);
|
|
}
|
|
|
|
#define can_do(what) \
|
|
gboolean \
|
|
midori_view_can_##what (MidoriView* view) \
|
|
{ \
|
|
g_return_val_if_fail (MIDORI_IS_VIEW (view), FALSE); \
|
|
\
|
|
return view->socket_id > -1; \
|
|
}
|
|
|
|
can_do (zoom_in)
|
|
can_do (zoom_out)
|
|
can_do (reload)
|
|
can_do (print)
|
|
#if HAVE_GIO
|
|
can_do (view_source)
|
|
#else
|
|
gboolean midori_view_can_view_source (MidoriView* view)
|
|
{
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
can_do (find)
|
|
|
|
/**
|
|
* midori_view_reload:
|
|
* @view: a #MidoriView
|
|
* @from_cache: whether to allow caching
|
|
*
|
|
* Reloads the view.
|
|
*
|
|
* Note: The @from_cache value is currently ignored.
|
|
**/
|
|
void
|
|
midori_view_reload (MidoriView* view,
|
|
gboolean from_cache)
|
|
{
|
|
g_return_if_fail (MIDORI_IS_VIEW (view));
|
|
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "reload", int_to_str (from_cache));
|
|
else
|
|
webkit_web_view_reload (WEBKIT_WEB_VIEW (view->web_view));
|
|
}
|
|
|
|
/**
|
|
* 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));
|
|
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "stop-loading", NULL);
|
|
else
|
|
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 (midori_view_is_socket (view))
|
|
return view->can_go_back;
|
|
else 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));
|
|
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "go-back", NULL);
|
|
else
|
|
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 (midori_view_is_socket (view))
|
|
return view->can_go_forward;
|
|
else 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));
|
|
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "go-forward", NULL);
|
|
else
|
|
webkit_web_view_go_forward (WEBKIT_WEB_VIEW (view->web_view));
|
|
}
|
|
|
|
/**
|
|
* midori_view_print
|
|
* @view: a #MidoriView
|
|
*
|
|
* Prints the contents of the view.
|
|
**/
|
|
void
|
|
midori_view_print (MidoriView* view)
|
|
{
|
|
g_return_if_fail (MIDORI_IS_VIEW (view));
|
|
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "print", NULL);
|
|
else
|
|
webkit_web_view_execute_script (
|
|
WEBKIT_WEB_VIEW (view->web_view), "print();");
|
|
}
|
|
|
|
/**
|
|
* 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));
|
|
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "unmark-matches", NULL);
|
|
else
|
|
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)
|
|
{
|
|
gchar* data;
|
|
|
|
g_return_if_fail (MIDORI_IS_VIEW (view));
|
|
|
|
if (midori_view_is_socket (view))
|
|
{
|
|
/* (text, case_sensitive, forward) => (forward, case_sensitive, text) */
|
|
data = g_strdup_printf ("%d %d %s", forward, case_sensitive, text);
|
|
send_command (view, "search-text", data);
|
|
g_free (data);
|
|
}
|
|
else
|
|
g_signal_emit (view, signals[SEARCH_TEXT], 0,
|
|
webkit_web_view_search_text (WEBKIT_WEB_VIEW (view->web_view),
|
|
text, case_sensitive, forward, TRUE));
|
|
}
|
|
|
|
/**
|
|
* 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)
|
|
{
|
|
gchar* data;
|
|
|
|
g_return_if_fail (MIDORI_IS_VIEW (view));
|
|
|
|
if (midori_view_is_socket (view))
|
|
{
|
|
/* (text, case_sensitive) => (case_sensitive, text) */
|
|
data = g_strdup_printf ("%d %s", case_sensitive, text);
|
|
send_command (view, "mark-matches", data);
|
|
g_free (data);
|
|
}
|
|
else
|
|
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));
|
|
|
|
if (midori_view_is_socket (view))
|
|
send_command (view, "hl-matches", int_to_str (highlight));
|
|
else
|
|
webkit_web_view_set_highlight_text_matches (
|
|
WEBKIT_WEB_VIEW (view->web_view), highlight);
|
|
}
|