First attempt at an extension interface.
This commit is contained in:
parent
b354aed640
commit
7039d48e48
4 changed files with 647 additions and 249 deletions
|
@ -54,15 +54,34 @@ midori_addons_class_init (MidoriAddonsClass* class)
|
||||||
g_type_class_add_private (class, sizeof (MidoriAddonsPrivate));
|
g_type_class_add_private (class, sizeof (MidoriAddonsPrivate));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const
|
||||||
|
gchar* _folder_for_kind (MidoriAddonKind kind)
|
||||||
|
{
|
||||||
|
switch (kind)
|
||||||
|
{
|
||||||
|
case MIDORI_ADDON_EXTENSIONS:
|
||||||
|
return "extensions";
|
||||||
|
case MIDORI_ADDON_USER_SCRIPTS:
|
||||||
|
return "scripts";
|
||||||
|
case MIDORI_ADDON_USER_STYLES:
|
||||||
|
return "styles";
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
midori_addons_button_add_clicked_cb (GtkToolItem* toolitem,
|
midori_addons_button_add_clicked_cb (GtkToolItem* toolitem,
|
||||||
MidoriAddons* addons)
|
MidoriAddons* addons)
|
||||||
{
|
{
|
||||||
|
MidoriAddonsPrivate* priv = addons->priv;
|
||||||
|
|
||||||
GtkWidget* dialog = gtk_message_dialog_new (
|
GtkWidget* dialog = gtk_message_dialog_new (
|
||||||
GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (addons))),
|
GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (addons))),
|
||||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||||
GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
|
GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
|
||||||
"Put scripts in the folder ~/.local/share/midori/scripts");
|
"Put scripts in the folder ~/.local/share/midori/%s",
|
||||||
|
_folder_for_kind (priv->kind));
|
||||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||||
gtk_widget_destroy (dialog);
|
gtk_widget_destroy (dialog);
|
||||||
}
|
}
|
||||||
|
@ -119,6 +138,401 @@ midori_addons_treeview_row_activated_cb (GtkTreeView* treeview,
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gchar*
|
||||||
|
_js_string_utf8 (JSStringRef js_string)
|
||||||
|
{
|
||||||
|
size_t size_utf8 = JSStringGetMaximumUTF8CStringSize (js_string);
|
||||||
|
gchar* string_utf8 = (gchar*)g_malloc (size_utf8);
|
||||||
|
JSStringGetUTF8CString (js_string, string_utf8, size_utf8);
|
||||||
|
return string_utf8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_js_class_get_property_names_cb (JSContextRef js_context,
|
||||||
|
JSObjectRef js_object,
|
||||||
|
JSPropertyNameAccumulatorRef js_properties)
|
||||||
|
{
|
||||||
|
GObject* object = JSObjectGetPrivate (js_object);
|
||||||
|
if (object)
|
||||||
|
{
|
||||||
|
guint n_properties;
|
||||||
|
GParamSpec** pspecs = g_object_class_list_properties (
|
||||||
|
G_OBJECT_GET_CLASS (object), &n_properties);
|
||||||
|
gint i;
|
||||||
|
for (i = 0; i < n_properties; i++)
|
||||||
|
{
|
||||||
|
const gchar* property = g_param_spec_get_name (pspecs[i]);
|
||||||
|
JSStringRef js_property = JSStringCreateWithUTF8CString (property);
|
||||||
|
JSPropertyNameAccumulatorAddName (js_properties, js_property);
|
||||||
|
JSStringRelease (js_property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
_js_class_has_property_cb (JSContextRef js_context,
|
||||||
|
JSObjectRef js_object,
|
||||||
|
JSStringRef js_property)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
gchar* property = _js_string_utf8 (js_property);
|
||||||
|
GObject* object = JSObjectGetPrivate (js_object);
|
||||||
|
if (object)
|
||||||
|
{
|
||||||
|
if (g_object_class_find_property (G_OBJECT_GET_CLASS (object),
|
||||||
|
property))
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
else if (js_object == JSContextGetGlobalObject (js_context))
|
||||||
|
{
|
||||||
|
gchar* property = _js_string_utf8 (js_property);
|
||||||
|
GType type = g_type_from_name (property);
|
||||||
|
result = type ? type : false;
|
||||||
|
}
|
||||||
|
g_free (property);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSObjectRef
|
||||||
|
_js_object_new (JSContextRef js_context,
|
||||||
|
gpointer object);
|
||||||
|
|
||||||
|
static void
|
||||||
|
_js_object_set_property (JSContextRef js_context,
|
||||||
|
JSObjectRef js_object,
|
||||||
|
const gchar* name,
|
||||||
|
JSValueRef js_value)
|
||||||
|
{
|
||||||
|
JSStringRef js_name = JSStringCreateWithUTF8CString (name);
|
||||||
|
JSObjectSetProperty(js_context, js_object, js_name, js_value,
|
||||||
|
kJSPropertyAttributeNone, NULL);
|
||||||
|
JSStringRelease (js_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSObjectRef
|
||||||
|
_js_object_call_as_constructor_cb (JSContextRef js_context,
|
||||||
|
JSObjectRef js_object,
|
||||||
|
size_t n_arguments,
|
||||||
|
const JSValueRef js_arguments[],
|
||||||
|
JSValueRef* js_exception)
|
||||||
|
{
|
||||||
|
gchar* type_name = JSObjectGetPrivate (js_object);
|
||||||
|
if (type_name)
|
||||||
|
{
|
||||||
|
GType type = g_type_from_name (type_name);
|
||||||
|
if (type)
|
||||||
|
{
|
||||||
|
GObject* object = g_object_new (type, NULL);
|
||||||
|
JSObjectRef js_object = _js_object_new (js_context, object);
|
||||||
|
return js_object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return JSValueMakeNull (js_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValueRef
|
||||||
|
_js_class_get_property_cb (JSContextRef js_context,
|
||||||
|
JSObjectRef js_object,
|
||||||
|
JSStringRef js_property,
|
||||||
|
JSValueRef* js_exception)
|
||||||
|
{
|
||||||
|
if (js_object == JSContextGetGlobalObject (js_context))
|
||||||
|
{
|
||||||
|
gchar* property = _js_string_utf8 (js_property);
|
||||||
|
GType type = g_type_from_name (property);
|
||||||
|
if (type)
|
||||||
|
{
|
||||||
|
JSClassDefinition js_class_def = kJSClassDefinitionEmpty;
|
||||||
|
js_class_def.className = g_strdup (property);
|
||||||
|
js_class_def.callAsConstructor = _js_object_call_as_constructor_cb;
|
||||||
|
JSClassRef js_class = JSClassCreate (&js_class_def);
|
||||||
|
return JSObjectMake (js_context, js_class, property);
|
||||||
|
}
|
||||||
|
g_free (property);
|
||||||
|
return JSValueMakeNull (js_context);
|
||||||
|
}
|
||||||
|
GObject* object = JSObjectGetPrivate (js_object);
|
||||||
|
JSValueRef js_result = NULL;
|
||||||
|
if (object)
|
||||||
|
{
|
||||||
|
gchar* property = _js_string_utf8 (js_property);
|
||||||
|
GParamSpec* pspec = g_object_class_find_property (
|
||||||
|
G_OBJECT_GET_CLASS (object), property);
|
||||||
|
if (!pspec)
|
||||||
|
{
|
||||||
|
gchar* message = g_strdup_printf (_("%s has no property '%s'"),
|
||||||
|
KATZE_OBJECT_NAME (object), property);
|
||||||
|
JSStringRef js_message = JSStringCreateWithUTF8CString (message);
|
||||||
|
*js_exception = JSValueMakeString (js_context, js_message);
|
||||||
|
JSStringRelease (js_message);
|
||||||
|
g_free (message);
|
||||||
|
g_free (property);
|
||||||
|
return JSValueMakeNull (js_context);
|
||||||
|
}
|
||||||
|
if (!(pspec->flags & G_PARAM_READABLE))
|
||||||
|
{
|
||||||
|
g_free (property);
|
||||||
|
return JSValueMakeUndefined (js_context);
|
||||||
|
}
|
||||||
|
GType type = G_PARAM_SPEC_TYPE (pspec);
|
||||||
|
if (type == G_TYPE_PARAM_STRING)
|
||||||
|
{
|
||||||
|
gchar* value;
|
||||||
|
g_object_get (object, property, &value, NULL);
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
JSStringRef js_string = JSStringCreateWithUTF8CString (value);
|
||||||
|
js_result = JSValueMakeString (js_context, js_string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == G_TYPE_PARAM_INT
|
||||||
|
|| type == G_TYPE_PARAM_UINT)
|
||||||
|
{
|
||||||
|
gint value;
|
||||||
|
g_object_get (object, property, &value, NULL);
|
||||||
|
js_result = JSValueMakeNumber (js_context, value);
|
||||||
|
}
|
||||||
|
else if (type == G_TYPE_PARAM_BOOLEAN)
|
||||||
|
{
|
||||||
|
gboolean value;
|
||||||
|
g_object_get (object, property, &value, NULL);
|
||||||
|
js_result = JSValueMakeBoolean (js_context, value ? true : false);
|
||||||
|
}
|
||||||
|
else if (type == G_TYPE_PARAM_OBJECT)
|
||||||
|
{
|
||||||
|
GObject* value;
|
||||||
|
g_object_get (object, property, &value, NULL);
|
||||||
|
if (value)
|
||||||
|
js_result = _js_object_new (js_context, value);
|
||||||
|
}
|
||||||
|
else if (type == G_TYPE_PARAM_ENUM)
|
||||||
|
{
|
||||||
|
gint value;
|
||||||
|
g_object_get (object, property, &value, NULL);
|
||||||
|
js_result = JSValueMakeNumber (js_context, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
js_result = JSValueMakeUndefined (js_context);
|
||||||
|
g_free (property);
|
||||||
|
}
|
||||||
|
return js_result ? js_result : JSValueMakeNull (js_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
_js_class_set_property_cb (JSContextRef js_context,
|
||||||
|
JSObjectRef js_object,
|
||||||
|
JSStringRef js_property,
|
||||||
|
JSValueRef js_value,
|
||||||
|
JSValueRef* js_exception)
|
||||||
|
{
|
||||||
|
GObject* object = JSObjectGetPrivate (js_object);
|
||||||
|
bool result = false;
|
||||||
|
if (object)
|
||||||
|
{
|
||||||
|
gchar* property = _js_string_utf8 (js_property);
|
||||||
|
GParamSpec* pspec = g_object_class_find_property (
|
||||||
|
G_OBJECT_GET_CLASS (object), property);
|
||||||
|
if (!pspec)
|
||||||
|
{
|
||||||
|
gchar* message = g_strdup_printf (_("%s has no property '%s'"),
|
||||||
|
KATZE_OBJECT_NAME (object), property);
|
||||||
|
JSStringRef js_message = JSStringCreateWithUTF8CString (message);
|
||||||
|
*js_exception = JSValueMakeString (js_context, js_message);
|
||||||
|
JSStringRelease (js_message);
|
||||||
|
g_free (message);
|
||||||
|
g_free (property);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(pspec->flags & G_PARAM_WRITABLE))
|
||||||
|
{
|
||||||
|
g_free (property);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
GType type = G_PARAM_SPEC_TYPE (pspec);
|
||||||
|
if (type == G_TYPE_PARAM_STRING)
|
||||||
|
{
|
||||||
|
JSStringRef js_string_value = JSValueToStringCopy (js_context,
|
||||||
|
js_value, js_exception);
|
||||||
|
if (js_string_value)
|
||||||
|
{
|
||||||
|
gchar* string_value = _js_string_utf8 (js_string_value);
|
||||||
|
g_object_set (object, property, string_value, NULL);
|
||||||
|
g_free (string_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == G_TYPE_PARAM_INT
|
||||||
|
|| type == G_TYPE_PARAM_UINT)
|
||||||
|
{
|
||||||
|
int value = JSValueToNumber (js_context, js_value,
|
||||||
|
js_exception);
|
||||||
|
g_object_set (object, property, value, NULL);
|
||||||
|
}
|
||||||
|
else if (type == G_TYPE_PARAM_BOOLEAN)
|
||||||
|
{
|
||||||
|
bool value = JSValueToBoolean (js_context, js_value);
|
||||||
|
g_object_set (object, property, value ? TRUE : FALSE, NULL);
|
||||||
|
}
|
||||||
|
else if (type == G_TYPE_PARAM_OBJECT)
|
||||||
|
{
|
||||||
|
JSObjectRef js_object_value = JSValueToObject (
|
||||||
|
js_context, js_value, NULL);
|
||||||
|
GObject* object_value = JSObjectGetPrivate (js_object_value);
|
||||||
|
if (object_value)
|
||||||
|
g_object_set (object, property, object_value, NULL);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gchar* message = g_strdup_printf (_("%s cannot be assigned to %s.%s"),
|
||||||
|
"[object]", KATZE_OBJECT_NAME (object), property);
|
||||||
|
JSStringRef js_message = JSStringCreateWithUTF8CString (message);
|
||||||
|
*js_exception = JSValueMakeString (js_context, js_message);
|
||||||
|
JSStringRelease (js_message);
|
||||||
|
g_free (message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gchar* message = g_strdup_printf (_("%s.%s cannot be accessed"),
|
||||||
|
KATZE_OBJECT_NAME (object), property);
|
||||||
|
JSStringRef js_message = JSStringCreateWithUTF8CString (message);
|
||||||
|
*js_exception = JSValueMakeString (js_context, js_message);
|
||||||
|
JSStringRelease (js_message);
|
||||||
|
g_free (message);
|
||||||
|
}
|
||||||
|
g_free (property);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValueRef
|
||||||
|
_js_foo_call_as_function_cb (JSContextRef js_context,
|
||||||
|
JSObjectRef js_function,
|
||||||
|
JSObjectRef js_this,
|
||||||
|
size_t n_arguments,
|
||||||
|
const JSValueRef js_arguments[],
|
||||||
|
JSValueRef* js_exception)
|
||||||
|
{
|
||||||
|
GObject* object = JSObjectGetPrivate (js_this);
|
||||||
|
if (object)
|
||||||
|
{
|
||||||
|
if (!n_arguments)
|
||||||
|
{
|
||||||
|
gtk_widget_show (GTK_WIDGET (object));
|
||||||
|
}
|
||||||
|
else if (n_arguments == 1)
|
||||||
|
{
|
||||||
|
JSObjectRef js_arg1 = JSValueToObject (
|
||||||
|
js_context, js_arguments[0], NULL);
|
||||||
|
GObject* arg1 = JSObjectGetPrivate (js_arg1);
|
||||||
|
if (arg1)
|
||||||
|
gtk_container_add (GTK_CONTAINER (object), GTK_WIDGET (arg1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSValueMakeUndefined (js_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_js_foo_add_function (JSContextRef js_context,
|
||||||
|
JSObjectRef js_object,
|
||||||
|
const gchar* func)
|
||||||
|
{
|
||||||
|
JSStringRef js_func = JSStringCreateWithUTF8CString (func);
|
||||||
|
JSObjectRef js_function = JSObjectMakeFunctionWithCallback (
|
||||||
|
js_context, js_func, _js_foo_call_as_function_cb);
|
||||||
|
JSStringRelease (js_func);
|
||||||
|
_js_object_set_property (js_context, js_object, func, js_function);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSObjectRef
|
||||||
|
_js_object_new (JSContextRef js_context,
|
||||||
|
gpointer object)
|
||||||
|
{
|
||||||
|
JSClassDefinition js_class_def = kJSClassDefinitionEmpty;
|
||||||
|
js_class_def.className = g_strdup (KATZE_OBJECT_NAME (object));
|
||||||
|
js_class_def.getPropertyNames = _js_class_get_property_names_cb;
|
||||||
|
js_class_def.hasProperty = _js_class_has_property_cb;
|
||||||
|
js_class_def.getProperty = _js_class_get_property_cb;
|
||||||
|
js_class_def.setProperty = _js_class_set_property_cb;
|
||||||
|
JSClassRef js_class = JSClassCreate (&js_class_def);
|
||||||
|
JSObjectRef js_object = JSObjectMake (js_context, js_class, object);
|
||||||
|
if (GTK_IS_WIDGET (object))
|
||||||
|
{
|
||||||
|
_js_foo_add_function (js_context, js_object, "show");
|
||||||
|
}
|
||||||
|
if (GTK_IS_CONTAINER (object))
|
||||||
|
{
|
||||||
|
_js_foo_add_function (js_context, js_object, "add");
|
||||||
|
}
|
||||||
|
return js_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValueRef
|
||||||
|
_js_eval (JSContextRef js_context,
|
||||||
|
const gchar* script,
|
||||||
|
gchar** exception)
|
||||||
|
{
|
||||||
|
JSStringRef js_script = JSStringCreateWithUTF8CString (script);
|
||||||
|
JSValueRef js_exception = NULL;
|
||||||
|
JSValueRef js_value = JSEvaluateScript (js_context, js_script,
|
||||||
|
JSContextGetGlobalObject (js_context), NULL, 0, &js_exception);
|
||||||
|
if (!js_value && exception)
|
||||||
|
{
|
||||||
|
JSStringRef js_message = JSValueToStringCopy (js_context,
|
||||||
|
js_exception, NULL);
|
||||||
|
*exception = _js_string_utf8 (js_message);
|
||||||
|
JSStringRelease (js_message);
|
||||||
|
js_value = JSValueMakeNull (js_context);
|
||||||
|
}
|
||||||
|
JSStringRelease (js_script);
|
||||||
|
return js_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
_js_check_syntax (JSContextRef js_context,
|
||||||
|
const gchar* script,
|
||||||
|
const gchar* source_id,
|
||||||
|
int line,
|
||||||
|
gchar** exception)
|
||||||
|
{
|
||||||
|
JSStringRef js_script = JSStringCreateWithUTF8CString (script);
|
||||||
|
JSStringRef js_source_id = JSStringCreateWithUTF8CString (source_id);
|
||||||
|
JSValueRef js_exception = NULL;
|
||||||
|
bool result = JSCheckScriptSyntax (js_context, js_script, js_source_id,
|
||||||
|
line, &js_exception);
|
||||||
|
if (!result && exception)
|
||||||
|
{
|
||||||
|
JSStringRef js_message = JSValueToStringCopy (js_context,
|
||||||
|
js_exception, NULL);
|
||||||
|
*exception = _js_string_utf8 (js_message);
|
||||||
|
JSStringRelease (js_message);
|
||||||
|
}
|
||||||
|
JSStringRelease (js_source_id);
|
||||||
|
JSStringRelease (js_script);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_js_document_load_script_file (JSContextRef js_context,
|
||||||
|
const gchar* filename,
|
||||||
|
gchar** exception)
|
||||||
|
{
|
||||||
|
gboolean result = FALSE;
|
||||||
|
gchar* script;
|
||||||
|
GError* error = NULL;
|
||||||
|
if (g_file_get_contents (filename, &script, NULL, &error))
|
||||||
|
{
|
||||||
|
if (_js_eval (js_context, script, exception))
|
||||||
|
result = TRUE;
|
||||||
|
g_free (script);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*exception = g_strdup (error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
midori_addons_init (MidoriAddons* addons)
|
midori_addons_init (MidoriAddons* addons)
|
||||||
{
|
{
|
||||||
|
@ -150,237 +564,91 @@ midori_addons_init (MidoriAddons* addons)
|
||||||
gtk_box_pack_start (GTK_BOX (addons), priv->treeview, TRUE, TRUE, 0);
|
gtk_box_pack_start (GTK_BOX (addons), priv->treeview, TRUE, TRUE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gchar*
|
|
||||||
_js_string_utf8 (JSStringRef js_string)
|
|
||||||
{
|
|
||||||
size_t size_utf8 = JSStringGetMaximumUTF8CStringSize (js_string);
|
|
||||||
gchar* string_utf8 = (gchar*)g_malloc (size_utf8);
|
|
||||||
JSStringGetUTF8CString (js_string, string_utf8, size_utf8);
|
|
||||||
return string_utf8;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_js_class_get_property_names_cb (JSContextRef js_context,
|
|
||||||
JSObjectRef js_object,
|
|
||||||
JSPropertyNameAccumulatorRef js_properties)
|
|
||||||
{
|
|
||||||
GObject* object = JSObjectGetPrivate (js_object);
|
|
||||||
if (object)
|
|
||||||
{
|
|
||||||
guint n_properties;
|
|
||||||
GParamSpec** pspecs = g_object_class_list_properties (
|
|
||||||
G_OBJECT_GET_CLASS (object), &n_properties);
|
|
||||||
gint i;
|
|
||||||
for (i = 0; i < n_properties; i++)
|
|
||||||
{
|
|
||||||
GType type = G_PARAM_SPEC_TYPE (pspecs[i]);
|
|
||||||
const gchar* property = g_param_spec_get_name (pspecs[i]);
|
|
||||||
JSStringRef js_property = JSStringCreateWithUTF8CString (property);
|
|
||||||
JSPropertyNameAccumulatorAddName (js_properties, js_property);
|
|
||||||
JSStringRelease (js_property);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
_js_class_has_property_cb (JSContextRef js_context,
|
|
||||||
JSObjectRef js_object,
|
|
||||||
JSStringRef js_property)
|
|
||||||
{
|
|
||||||
GObject* object = JSObjectGetPrivate (js_object);
|
|
||||||
bool result = false;
|
|
||||||
if (object)
|
|
||||||
{
|
|
||||||
gchar* property = _js_string_utf8 (js_property);
|
|
||||||
if (g_object_class_find_property (G_OBJECT_GET_CLASS (object),
|
|
||||||
property))
|
|
||||||
result = true;
|
|
||||||
g_free (property);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSValueRef
|
static JSValueRef
|
||||||
_js_class_get_property_cb (JSContextRef js_context,
|
_js_info_call_as_function_cb (JSContextRef js_context,
|
||||||
JSObjectRef js_object,
|
JSObjectRef js_function,
|
||||||
JSStringRef js_property,
|
JSObjectRef js_this,
|
||||||
|
size_t n_arguments,
|
||||||
|
const JSValueRef js_arguments[],
|
||||||
JSValueRef* js_exception)
|
JSValueRef* js_exception)
|
||||||
{
|
{
|
||||||
GObject* object = JSObjectGetPrivate (js_object);
|
if (n_arguments > 0) {
|
||||||
JSValueRef js_result = NULL;
|
JSStringRef js_string = JSValueToStringCopy (
|
||||||
if (object)
|
js_context, js_arguments[0], NULL);
|
||||||
{
|
|
||||||
gchar* property = _js_string_utf8 (js_property);
|
|
||||||
GParamSpec* pspec = g_object_class_find_property (
|
|
||||||
G_OBJECT_GET_CLASS (object), property);
|
|
||||||
if (!pspec)
|
|
||||||
{
|
|
||||||
gchar* message = g_strdup_printf (_("%s has no property '%s'"),
|
|
||||||
KATZE_OBJECT_NAME (object), property);
|
|
||||||
JSStringRef js_message = JSStringCreateWithUTF8CString (message);
|
|
||||||
*js_exception = JSValueMakeString (js_context, js_message);
|
|
||||||
JSStringRelease (js_message);
|
|
||||||
g_free (message);
|
|
||||||
}
|
|
||||||
GType type = G_PARAM_SPEC_TYPE (pspec);
|
|
||||||
if (type == G_TYPE_PARAM_STRING)
|
|
||||||
{
|
|
||||||
gchar* value;
|
|
||||||
g_object_get (object, property, &value, NULL);
|
|
||||||
JSStringRef js_string = JSStringCreateWithUTF8CString (value);
|
|
||||||
js_result = JSValueMakeString (js_context, js_string);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gchar* message = g_strdup_printf (_("%s.%s cannot be accessed"),
|
|
||||||
KATZE_OBJECT_NAME (object), property);
|
|
||||||
JSStringRef js_message = JSStringCreateWithUTF8CString (message);
|
|
||||||
*js_exception = JSValueMakeString (js_context, js_message);
|
|
||||||
JSStringRelease (js_message);
|
|
||||||
g_free (message);
|
|
||||||
}
|
|
||||||
g_free (property);
|
|
||||||
}
|
|
||||||
return js_result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
_js_class_set_property_cb (JSContextRef js_context,
|
|
||||||
JSObjectRef js_object,
|
|
||||||
JSStringRef js_property,
|
|
||||||
JSValueRef js_value,
|
|
||||||
JSValueRef* js_exception)
|
|
||||||
{
|
|
||||||
GObject* object = JSObjectGetPrivate (js_object);
|
|
||||||
bool result = false;
|
|
||||||
if (object)
|
|
||||||
{
|
|
||||||
gchar* property = _js_string_utf8 (js_property);
|
|
||||||
GParamSpec* pspec = g_object_class_find_property (
|
|
||||||
G_OBJECT_GET_CLASS (object), property);
|
|
||||||
if (!pspec)
|
|
||||||
{
|
|
||||||
gchar* message = g_strdup_printf (_("%s has no property '%s'"),
|
|
||||||
KATZE_OBJECT_NAME (object), property);
|
|
||||||
JSStringRef js_message = JSStringCreateWithUTF8CString (message);
|
|
||||||
*js_exception = JSValueMakeString (js_context, js_message);
|
|
||||||
JSStringRelease (js_message);
|
|
||||||
g_free (message);
|
|
||||||
}
|
|
||||||
if (!(pspec->flags & G_PARAM_WRITABLE))
|
|
||||||
{
|
|
||||||
g_free (property);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GType type = G_PARAM_SPEC_TYPE (pspec);
|
|
||||||
if (type == G_TYPE_PARAM_STRING)
|
|
||||||
{
|
|
||||||
JSStringRef js_string = JSValueToStringCopy (js_context, js_value,
|
|
||||||
js_exception);
|
|
||||||
if (js_string)
|
|
||||||
{
|
|
||||||
gchar* string = _js_string_utf8 (js_string);
|
gchar* string = _js_string_utf8 (js_string);
|
||||||
g_object_set (object, property, string, NULL);
|
// FIXME: Do we want to print this somewhere else?
|
||||||
|
printf ("console.info: %s\n", string);
|
||||||
g_free (string);
|
g_free (string);
|
||||||
|
JSStringRelease (js_string);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gchar* message = g_strdup_printf (_("%s.%s cannot be accessed"),
|
|
||||||
KATZE_OBJECT_NAME (object), property);
|
|
||||||
JSStringRef js_message = JSStringCreateWithUTF8CString (message);
|
|
||||||
*js_exception = JSValueMakeString (js_context, js_message);
|
|
||||||
JSStringRelease (js_message);
|
|
||||||
g_free (message);
|
|
||||||
}
|
|
||||||
g_free (property);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSObjectRef
|
return JSValueMakeUndefined (js_context);
|
||||||
_js_object_new (JSContextRef js_context,
|
|
||||||
GObject* object)
|
|
||||||
{
|
|
||||||
JSClassDefinition js_class_def = kJSClassDefinitionEmpty;
|
|
||||||
js_class_def.className = g_strdup (KATZE_OBJECT_NAME (object));
|
|
||||||
js_class_def.getPropertyNames = _js_class_get_property_names_cb;
|
|
||||||
js_class_def.hasProperty = _js_class_has_property_cb;
|
|
||||||
js_class_def.getProperty = _js_class_get_property_cb;
|
|
||||||
js_class_def.setProperty = _js_class_set_property_cb;
|
|
||||||
// js_class_def.staticFunctions = JSStaticFunction*;
|
|
||||||
JSClassRef js_class = JSClassCreate (&js_class_def);
|
|
||||||
return JSObjectMake (js_context, js_class, object);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_js_object_set_property (JSContextRef js_context,
|
_midori_addons_extensions_main (MidoriAddons* addons,
|
||||||
JSObjectRef js_object,
|
GtkWidget* web_widget)
|
||||||
const gchar* name,
|
|
||||||
JSValueRef js_value)
|
|
||||||
{
|
{
|
||||||
JSStringRef js_name = JSStringCreateWithUTF8CString (name);
|
MidoriAddonsPrivate* priv = addons->priv;
|
||||||
JSObjectSetProperty(js_context, js_object, js_name, js_value,
|
|
||||||
|
JSClassDefinition js_global_def = kJSClassDefinitionEmpty;
|
||||||
|
js_global_def.getPropertyNames = _js_class_get_property_names_cb;
|
||||||
|
js_global_def.hasProperty = _js_class_has_property_cb;
|
||||||
|
js_global_def.getProperty = _js_class_get_property_cb;
|
||||||
|
JSClassRef js_global_class = JSClassCreate (&js_global_def);
|
||||||
|
JSGlobalContextRef js_context = JSGlobalContextCreate (js_global_class);
|
||||||
|
JSClassDefinition js_class_def = kJSClassDefinitionEmpty;
|
||||||
|
js_class_def.className = g_strdup ("console");
|
||||||
|
JSClassRef js_class = JSClassCreate (&js_class_def);
|
||||||
|
JSObjectRef js_console = JSObjectMake (js_context, js_class, NULL);
|
||||||
|
JSStringRef js_info = JSStringCreateWithUTF8CString ("info");
|
||||||
|
JSObjectRef js_info_function = JSObjectMakeFunctionWithCallback (
|
||||||
|
js_context, js_info, _js_info_call_as_function_cb);
|
||||||
|
JSObjectSetProperty (js_context, js_console, js_info, js_info_function,
|
||||||
kJSPropertyAttributeNone, NULL);
|
kJSPropertyAttributeNone, NULL);
|
||||||
JSStringRelease (js_name);
|
JSStringRelease (js_info);
|
||||||
}
|
_js_object_set_property (js_context,
|
||||||
|
|
||||||
static JSValueRef
|
|
||||||
_js_eval (JSContextRef js_context,
|
|
||||||
const gchar* script,
|
|
||||||
gchar** exception)
|
|
||||||
{
|
|
||||||
JSStringRef js_script = JSStringCreateWithUTF8CString (script);
|
|
||||||
JSValueRef js_exception;
|
|
||||||
JSValueRef js_value = JSEvaluateScript (js_context, js_script,
|
|
||||||
JSContextGetGlobalObject (js_context),
|
JSContextGetGlobalObject (js_context),
|
||||||
NULL, 0, &js_exception);
|
"console", js_console);
|
||||||
if (!js_value && exception)
|
|
||||||
{
|
|
||||||
JSStringRef js_message = JSValueToStringCopy (js_context,
|
|
||||||
js_exception, NULL);
|
|
||||||
*exception = _js_string_utf8 (js_message);
|
|
||||||
JSStringRelease (js_message);
|
|
||||||
}
|
|
||||||
JSStringRelease (js_script);
|
|
||||||
return js_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
GtkWidget* browser = gtk_widget_get_toplevel (GTK_WIDGET (web_widget));
|
||||||
_js_document_load_script_file (JSContextRef js_context,
|
if (GTK_WIDGET_TOPLEVEL (browser))
|
||||||
const gchar* filename,
|
|
||||||
gchar** exception)
|
|
||||||
{
|
|
||||||
gboolean result = FALSE;
|
|
||||||
gchar* script;
|
|
||||||
GError* error = NULL;
|
|
||||||
if (g_file_get_contents (filename, &script, NULL, &error))
|
|
||||||
{
|
{
|
||||||
if (_js_eval (js_context, script, exception))
|
// FIXME: Midori should be backed up by a real GObject
|
||||||
result = TRUE;
|
JSClassDefinition js_class_def = kJSClassDefinitionEmpty;
|
||||||
g_free (script);
|
js_class_def.className = g_strdup ("Midori");
|
||||||
|
JSClassRef js_class = JSClassCreate (&js_class_def);
|
||||||
|
JSObjectRef js_midori = JSObjectMake (js_context, js_class, NULL);
|
||||||
|
_js_object_set_property (js_context,
|
||||||
|
JSContextGetGlobalObject (js_context),
|
||||||
|
"midori", js_midori);
|
||||||
|
JSObjectRef js_browser = _js_object_new (js_context, browser);
|
||||||
|
_js_object_set_property (js_context,
|
||||||
|
js_midori,
|
||||||
|
"browser", js_browser);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
*exception = g_strdup (error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const gchar* _folder_for_kind (MidoriAddonKind kind)
|
// FIXME: We want to honor system installed addons as well
|
||||||
{
|
gchar* addon_path = g_build_filename (g_get_user_data_dir (), PACKAGE_NAME,
|
||||||
switch (kind)
|
_folder_for_kind (priv->kind), NULL);
|
||||||
|
GDir* addon_dir = g_dir_open (addon_path, 0, NULL);
|
||||||
|
if (addon_dir)
|
||||||
{
|
{
|
||||||
case MIDORI_ADDON_EXTENSIONS:
|
const gchar* filename;
|
||||||
return "extensions";
|
while ((filename = g_dir_read_name (addon_dir)))
|
||||||
case MIDORI_ADDON_USER_SCRIPTS:
|
{
|
||||||
return "scripts";
|
gchar* fullname = g_build_filename (addon_path, filename, NULL);
|
||||||
case MIDORI_ADDON_USER_STYLES:
|
gchar* exception = NULL;
|
||||||
return "styles";
|
_js_document_load_script_file (js_context, fullname, &exception);
|
||||||
default:
|
if (exception)
|
||||||
return NULL;
|
// FIXME: Do we want to print this somewhere else?
|
||||||
|
// FIXME Convert the filename to UTF8
|
||||||
|
printf ("%s - Exception: %s\n", filename, exception);
|
||||||
|
g_free (fullname);
|
||||||
}
|
}
|
||||||
|
g_dir_close (addon_dir);
|
||||||
|
}
|
||||||
|
JSGlobalContextRelease (js_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -392,13 +660,6 @@ midori_web_widget_window_object_cleared_cb (GtkWidget* web_widget,
|
||||||
{
|
{
|
||||||
MidoriAddonsPrivate* priv = addons->priv;
|
MidoriAddonsPrivate* priv = addons->priv;
|
||||||
|
|
||||||
GObject* settings;
|
|
||||||
g_object_get (web_widget, "settings", &settings, NULL);
|
|
||||||
JSObjectRef js_settings = _js_object_new (js_context, settings);
|
|
||||||
_js_object_set_property (js_context,
|
|
||||||
JSContextGetGlobalObject (js_context),
|
|
||||||
KATZE_OBJECT_NAME (settings), js_settings);
|
|
||||||
|
|
||||||
// FIXME: We want to honor system installed addons as well
|
// FIXME: We want to honor system installed addons as well
|
||||||
gchar* addon_path = g_build_filename (g_get_user_data_dir (), PACKAGE_NAME,
|
gchar* addon_path = g_build_filename (g_get_user_data_dir (), PACKAGE_NAME,
|
||||||
_folder_for_kind (priv->kind), NULL);
|
_folder_for_kind (priv->kind), NULL);
|
||||||
|
@ -453,7 +714,9 @@ midori_addons_new (GtkWidget* web_widget,
|
||||||
MidoriAddonsPrivate* priv = addons->priv;
|
MidoriAddonsPrivate* priv = addons->priv;
|
||||||
priv->kind = kind;
|
priv->kind = kind;
|
||||||
|
|
||||||
if (kind == MIDORI_ADDON_USER_SCRIPTS)
|
if (kind == MIDORI_ADDON_EXTENSIONS)
|
||||||
|
_midori_addons_extensions_main (addons, web_widget);
|
||||||
|
else if (kind == MIDORI_ADDON_USER_SCRIPTS)
|
||||||
g_signal_connect (web_widget, "window-object-cleared",
|
g_signal_connect (web_widget, "window-object-cleared",
|
||||||
G_CALLBACK (midori_web_widget_window_object_cleared_cb), addons);
|
G_CALLBACK (midori_web_widget_window_object_cleared_cb), addons);
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,10 @@ enum
|
||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_MENUBAR,
|
||||||
|
PROP_NAVIGATIONBAR,
|
||||||
|
PROP_TAB,
|
||||||
|
PROP_STATUSBAR,
|
||||||
PROP_SETTINGS,
|
PROP_SETTINGS,
|
||||||
PROP_STATUSBAR_TEXT,
|
PROP_STATUSBAR_TEXT,
|
||||||
PROP_TRASH
|
PROP_TRASH
|
||||||
|
@ -595,6 +599,62 @@ midori_browser_class_init (MidoriBrowserClass* class)
|
||||||
|
|
||||||
GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT;
|
GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MidoriBrowser::menubar
|
||||||
|
*
|
||||||
|
* The menubar.
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_MENUBAR,
|
||||||
|
g_param_spec_object (
|
||||||
|
"menubar",
|
||||||
|
_("Menubar"),
|
||||||
|
_("The menubar"),
|
||||||
|
GTK_TYPE_MENU_BAR,
|
||||||
|
G_PARAM_READABLE));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MidoriBrowser::navigationbar
|
||||||
|
*
|
||||||
|
* The navigationbar.
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_NAVIGATIONBAR,
|
||||||
|
g_param_spec_object (
|
||||||
|
"navigationbar",
|
||||||
|
_("Navigationbar"),
|
||||||
|
_("The navigationbar"),
|
||||||
|
GTK_TYPE_TOOLBAR,
|
||||||
|
G_PARAM_READABLE));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MidoriBrowser::tab
|
||||||
|
*
|
||||||
|
* The current tab.
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_TAB,
|
||||||
|
g_param_spec_object (
|
||||||
|
"tab",
|
||||||
|
_("Tab"),
|
||||||
|
_("The current tab"),
|
||||||
|
GTK_TYPE_WIDGET,
|
||||||
|
G_PARAM_READWRITE));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MidoriBrowser::statusbar
|
||||||
|
*
|
||||||
|
* The statusbar.
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_STATUSBAR,
|
||||||
|
g_param_spec_object (
|
||||||
|
"statusbar",
|
||||||
|
_("Statusbar"),
|
||||||
|
_("The statusbar"),
|
||||||
|
GTK_TYPE_STATUSBAR,
|
||||||
|
G_PARAM_READABLE));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MidoriBrowser::settings
|
* MidoriBrowser::settings
|
||||||
*
|
*
|
||||||
|
@ -607,7 +667,7 @@ midori_browser_class_init (MidoriBrowserClass* class)
|
||||||
PROP_SETTINGS,
|
PROP_SETTINGS,
|
||||||
g_param_spec_object (
|
g_param_spec_object (
|
||||||
"settings",
|
"settings",
|
||||||
"Settings",
|
_("Settings"),
|
||||||
_("The associated settings"),
|
_("The associated settings"),
|
||||||
MIDORI_TYPE_WEB_SETTINGS,
|
MIDORI_TYPE_WEB_SETTINGS,
|
||||||
G_PARAM_READWRITE));
|
G_PARAM_READWRITE));
|
||||||
|
@ -627,7 +687,7 @@ midori_browser_class_init (MidoriBrowserClass* class)
|
||||||
PROP_STATUSBAR_TEXT,
|
PROP_STATUSBAR_TEXT,
|
||||||
g_param_spec_string (
|
g_param_spec_string (
|
||||||
"statusbar-text",
|
"statusbar-text",
|
||||||
"Statusbar Text",
|
_("Statusbar Text"),
|
||||||
_("The text that is displayed in the statusbar"),
|
_("The text that is displayed in the statusbar"),
|
||||||
"",
|
"",
|
||||||
flags));
|
flags));
|
||||||
|
@ -646,7 +706,7 @@ midori_browser_class_init (MidoriBrowserClass* class)
|
||||||
PROP_TRASH,
|
PROP_TRASH,
|
||||||
g_param_spec_object (
|
g_param_spec_object (
|
||||||
"trash",
|
"trash",
|
||||||
"Trash",
|
_("Trash"),
|
||||||
_("The trash, collecting recently closed tabs and windows"),
|
_("The trash, collecting recently closed tabs and windows"),
|
||||||
MIDORI_TYPE_TRASH,
|
MIDORI_TYPE_TRASH,
|
||||||
G_PARAM_READWRITE));
|
G_PARAM_READWRITE));
|
||||||
|
@ -697,7 +757,7 @@ static void
|
||||||
_action_tab_close_activate (GtkAction* action,
|
_action_tab_close_activate (GtkAction* action,
|
||||||
MidoriBrowser* browser)
|
MidoriBrowser* browser)
|
||||||
{
|
{
|
||||||
GtkWidget* widget = midori_browser_get_current_page (browser);
|
GtkWidget* widget = midori_browser_get_current_tab (browser);
|
||||||
GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, widget);
|
GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, widget);
|
||||||
gtk_widget_destroy (scrolled);
|
gtk_widget_destroy (scrolled);
|
||||||
}
|
}
|
||||||
|
@ -2651,14 +2711,7 @@ midori_browser_init (MidoriBrowser* browser)
|
||||||
priv->panel_pageholder, NULL,
|
priv->panel_pageholder, NULL,
|
||||||
GTK_STOCK_CONVERT, _("Pageholder"));
|
GTK_STOCK_CONVERT, _("Pageholder"));
|
||||||
|
|
||||||
// Addons
|
// Userscripts
|
||||||
/*panel = midori_addons_new (GTK_WIDGET (browser), MIDORI_ADDON_EXTENSIONS);
|
|
||||||
gtk_widget_show (panel);
|
|
||||||
toolbar = midori_addons_get_toolbar (MIDORI_ADDONS (panel));
|
|
||||||
gtk_widget_show (toolbar);
|
|
||||||
midori_panel_append_page (MIDORI_PANEL (priv->panel),
|
|
||||||
panel, toolbar,
|
|
||||||
"", _("Extensions"));*/
|
|
||||||
panel = midori_addons_new (GTK_WIDGET (browser), MIDORI_ADDON_USER_SCRIPTS);
|
panel = midori_addons_new (GTK_WIDGET (browser), MIDORI_ADDON_USER_SCRIPTS);
|
||||||
gtk_widget_show (panel);
|
gtk_widget_show (panel);
|
||||||
toolbar = midori_addons_get_toolbar (MIDORI_ADDONS (panel));
|
toolbar = midori_addons_get_toolbar (MIDORI_ADDONS (panel));
|
||||||
|
@ -2666,6 +2719,7 @@ midori_browser_init (MidoriBrowser* browser)
|
||||||
midori_panel_append_page (MIDORI_PANEL (priv->panel),
|
midori_panel_append_page (MIDORI_PANEL (priv->panel),
|
||||||
panel, toolbar,
|
panel, toolbar,
|
||||||
"", _("Userscripts"));
|
"", _("Userscripts"));
|
||||||
|
// Userstyles
|
||||||
/*panel = midori_addons_new (GTK_WIDGET (browser), MIDORI_ADDON_USER_STYLES);
|
/*panel = midori_addons_new (GTK_WIDGET (browser), MIDORI_ADDON_USER_STYLES);
|
||||||
gtk_widget_show (panel);
|
gtk_widget_show (panel);
|
||||||
toolbar = midori_addons_get_toolbar (MIDORI_ADDONS (panel));
|
toolbar = midori_addons_get_toolbar (MIDORI_ADDONS (panel));
|
||||||
|
@ -2750,6 +2804,15 @@ midori_browser_init (MidoriBrowser* browser)
|
||||||
gtk_box_pack_start (GTK_BOX (priv->statusbar), priv->progressbar,
|
gtk_box_pack_start (GTK_BOX (priv->statusbar), priv->progressbar,
|
||||||
FALSE, FALSE, 3);
|
FALSE, FALSE, 3);
|
||||||
|
|
||||||
|
// Extensions
|
||||||
|
panel = midori_addons_new (GTK_WIDGET (browser), MIDORI_ADDON_EXTENSIONS);
|
||||||
|
gtk_widget_show (panel);
|
||||||
|
toolbar = midori_addons_get_toolbar (MIDORI_ADDONS (panel));
|
||||||
|
gtk_widget_show (toolbar);
|
||||||
|
midori_panel_append_page (MIDORI_PANEL (priv->panel),
|
||||||
|
panel, toolbar,
|
||||||
|
"", _("Extensions"));
|
||||||
|
|
||||||
g_object_unref (ui_manager);
|
g_object_unref (ui_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2921,6 +2984,9 @@ midori_browser_set_property (GObject* object,
|
||||||
|
|
||||||
switch (prop_id)
|
switch (prop_id)
|
||||||
{
|
{
|
||||||
|
case PROP_TAB:
|
||||||
|
midori_browser_set_current_tab (browser, g_value_get_object (value));
|
||||||
|
break;
|
||||||
case PROP_STATUSBAR_TEXT:
|
case PROP_STATUSBAR_TEXT:
|
||||||
_midori_browser_set_statusbar_text (browser, g_value_get_string (value));
|
_midori_browser_set_statusbar_text (browser, g_value_get_string (value));
|
||||||
break;
|
break;
|
||||||
|
@ -2962,6 +3028,18 @@ midori_browser_get_property (GObject* object,
|
||||||
|
|
||||||
switch (prop_id)
|
switch (prop_id)
|
||||||
{
|
{
|
||||||
|
case PROP_MENUBAR:
|
||||||
|
g_value_set_object (value, priv->menubar);
|
||||||
|
break;
|
||||||
|
case PROP_NAVIGATIONBAR:
|
||||||
|
g_value_set_object (value, priv->navigationbar);
|
||||||
|
break;
|
||||||
|
case PROP_TAB:
|
||||||
|
g_value_set_object (value, midori_browser_get_current_tab (browser));
|
||||||
|
break;
|
||||||
|
case PROP_STATUSBAR:
|
||||||
|
g_value_set_object (value, priv->statusbar);
|
||||||
|
break;
|
||||||
case PROP_STATUSBAR_TEXT:
|
case PROP_STATUSBAR_TEXT:
|
||||||
g_value_set_string (value, priv->statusbar_text);
|
g_value_set_string (value, priv->statusbar_text);
|
||||||
break;
|
break;
|
||||||
|
@ -3217,7 +3295,6 @@ midori_browser_set_current_page (MidoriBrowser* browser,
|
||||||
gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n);
|
gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n);
|
||||||
GtkWidget* scrolled = gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook), n);
|
GtkWidget* scrolled = gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook), n);
|
||||||
GtkWidget* widget = _midori_browser_child_for_scrolled (browser, scrolled);
|
GtkWidget* widget = _midori_browser_child_for_scrolled (browser, scrolled);
|
||||||
printf ("_nth_page: %s\n", G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (widget)));
|
|
||||||
if (widget && MIDORI_IS_WEB_VIEW (widget)
|
if (widget && MIDORI_IS_WEB_VIEW (widget)
|
||||||
&& !strcmp (midori_web_view_get_display_uri (
|
&& !strcmp (midori_web_view_get_display_uri (
|
||||||
MIDORI_WEB_VIEW (widget)), ""))
|
MIDORI_WEB_VIEW (widget)), ""))
|
||||||
|
@ -3234,19 +3311,70 @@ midori_browser_set_current_page (MidoriBrowser* browser,
|
||||||
*
|
*
|
||||||
* If there is no page present at all, %NULL is returned.
|
* If there is no page present at all, %NULL is returned.
|
||||||
*
|
*
|
||||||
* Return value: the selected page, or %NULL
|
* Return value: the selected page, or -1
|
||||||
|
**/
|
||||||
|
gint
|
||||||
|
midori_browser_get_current_page (MidoriBrowser* browser)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (MIDORI_IS_BROWSER (browser), -1);
|
||||||
|
|
||||||
|
MidoriBrowserPrivate* priv = browser->priv;
|
||||||
|
|
||||||
|
return gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_browser_set_current_tab:
|
||||||
|
* @browser: a #MidoriBrowser
|
||||||
|
* @widget: a #GtkWidget
|
||||||
|
*
|
||||||
|
* Switches to the page containing @widget.
|
||||||
|
*
|
||||||
|
* The widget will also grab the focus automatically.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
midori_browser_set_current_tab (MidoriBrowser* browser,
|
||||||
|
GtkWidget* widget)
|
||||||
|
{
|
||||||
|
MidoriBrowserPrivate* priv = browser->priv;
|
||||||
|
|
||||||
|
GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, widget);
|
||||||
|
gint n = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), scrolled);
|
||||||
|
gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n);
|
||||||
|
if (widget && MIDORI_IS_WEB_VIEW (widget)
|
||||||
|
&& !strcmp (midori_web_view_get_display_uri (
|
||||||
|
MIDORI_WEB_VIEW (widget)), ""))
|
||||||
|
gtk_widget_grab_focus (priv->location);
|
||||||
|
else
|
||||||
|
gtk_widget_grab_focus (widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_browser_get_current_tab:
|
||||||
|
* @browser: a #MidoriBrowser
|
||||||
|
*
|
||||||
|
* Retrieves the currently selected tab.
|
||||||
|
*
|
||||||
|
* If there is no tab present at all, %NULL is returned.
|
||||||
|
*
|
||||||
|
* Return value: the selected tab, or %NULL
|
||||||
**/
|
**/
|
||||||
GtkWidget*
|
GtkWidget*
|
||||||
midori_browser_get_current_page (MidoriBrowser* browser)
|
midori_browser_get_current_tab (MidoriBrowser* browser)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (MIDORI_IS_BROWSER (browser), NULL);
|
g_return_val_if_fail (MIDORI_IS_BROWSER (browser), NULL);
|
||||||
|
|
||||||
MidoriBrowserPrivate* priv = browser->priv;
|
MidoriBrowserPrivate* priv = browser->priv;
|
||||||
|
|
||||||
gint n = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
|
gint n = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
|
||||||
|
if (n >= 0)
|
||||||
|
{
|
||||||
GtkWidget* widget = _midori_browser_child_for_scrolled (browser,
|
GtkWidget* widget = _midori_browser_child_for_scrolled (browser,
|
||||||
gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook), n));
|
gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook), n));
|
||||||
return widget;
|
return widget;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3267,7 +3395,7 @@ midori_browser_get_current_web_view (MidoriBrowser* browser)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (MIDORI_IS_BROWSER (browser), NULL);
|
g_return_val_if_fail (MIDORI_IS_BROWSER (browser), NULL);
|
||||||
|
|
||||||
GtkWidget* web_view = midori_browser_get_current_page (browser);
|
GtkWidget* web_view = midori_browser_get_current_tab (browser);
|
||||||
return MIDORI_IS_WEB_VIEW (web_view) ? web_view : NULL;
|
return MIDORI_IS_WEB_VIEW (web_view) ? web_view : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,9 +95,16 @@ void
|
||||||
midori_browser_set_current_page (MidoriBrowser* browser,
|
midori_browser_set_current_page (MidoriBrowser* browser,
|
||||||
gint n);
|
gint n);
|
||||||
|
|
||||||
GtkWidget*
|
gint
|
||||||
midori_browser_get_current_page (MidoriBrowser* browser);
|
midori_browser_get_current_page (MidoriBrowser* browser);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_browser_set_current_tab (MidoriBrowser* browser,
|
||||||
|
GtkWidget* widget);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
midori_browser_get_current_tab (MidoriBrowser* browser);
|
||||||
|
|
||||||
GtkWidget*
|
GtkWidget*
|
||||||
midori_browser_get_current_web_view (MidoriBrowser* browser);
|
midori_browser_get_current_web_view (MidoriBrowser* browser);
|
||||||
|
|
||||||
|
|
|
@ -463,7 +463,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
|
||||||
"close-buttons-on-tabs",
|
"close-buttons-on-tabs",
|
||||||
_("Close Buttons on Tabs"),
|
_("Close Buttons on Tabs"),
|
||||||
_("Whether tabs have close buttons"),
|
_("Whether tabs have close buttons"),
|
||||||
FALSE,
|
TRUE,
|
||||||
flags));
|
flags));
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class,
|
g_object_class_install_property (gobject_class,
|
||||||
|
|
Loading…
Reference in a new issue