gpointer data);
static void dbus_call(Client *c, const char *method, GVariant *param,
GAsyncReadyCallback callback);
-static void on_editable_change_focus(GDBusConnection *connection,
- const char *sender_name, const char *object_path,
- const char *interface_name, const char *signal_name,
- GVariant *parameters, gpointer data);
static void on_web_extension_page_created(GDBusConnection *connection,
const char *sender_name, const char *object_path,
const char *interface_name, const char *signal_name,
g_dbus_proxy_call(c->dbusproxy, method, param, G_DBUS_CALL_FLAGS_NONE, -1, NULL, callback, c);
}
-/**
- * Callback called if a editable element changes it's focus state.
- */
-static void on_editable_change_focus(GDBusConnection *connection,
- const char *sender_name, const char *object_path,
- const char *interface_name, const char *signal_name,
- GVariant *parameters, gpointer data)
-{
- gboolean is_focused;
- Client *c = (Client*)data;
- g_variant_get(parameters, "(b)", &is_focused);
-
- /* Don't change the mode if we are in pass through mode. */
- if (c->mode->id == 'n' && is_focused) {
- vb_enter(c, 'i');
- } else if (c->mode->id == 'i' && !is_focused) {
- vb_enter(c, 'n');
- }
- /* TODO allo strict-focus to ignore focus event for initial set focus */
-}
-
-/**
- * Listen to the VerticalScroll signal of the webextension and set the scroll
- * percent value on the client to update the statusbar.
- */
-static void on_vertical_scroll(GDBusConnection *connection,
- const char *sender_name, const char *object_path,
- const char *interface_name, const char *signal_name,
- GVariant *parameters, gpointer data)
-{
- Client *c = (Client*)data;
- g_variant_get(parameters, "(tt)", &c->state.scroll_max, &c->state.scroll_percent);
-
- vb_statusbar_update(c);
-}
-
/**
* Called when the web context created the page.
*
/* Set the dbus proxy on the right client based on page id. */
p->dbusproxy = (GDBusProxy*)data;
- g_dbus_connection_signal_subscribe(connection, NULL,
- VB_WEBEXTENSION_INTERFACE, "VerticalScroll",
- VB_WEBEXTENSION_OBJECT_PATH, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
- (GDBusSignalCallback)on_vertical_scroll, p, NULL);
- g_dbus_connection_signal_subscribe(connection, NULL,
- VB_WEBEXTENSION_INTERFACE, "EditableChangeFocus",
- VB_WEBEXTENSION_OBJECT_PATH, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
- (GDBusSignalCallback)on_editable_change_focus, p, NULL);
+ /* TODO Subscribe to debus signals here. */
}
}
#endif
static void vimb_setup(void);
static WebKitWebView *webview_new(Client *c, WebKitWebView *webview);
+static void on_script_message_focus(WebKitUserContentManager *manager,
+ WebKitJavascriptResult *message, Client *c);
struct Vimb vb;
webkit_user_script_unref(script);
}
+ /* Inject the global utility script. */
+ script = webkit_user_script_new(VIMB_UTIL,
+ WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES,
+ WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END, NULL, NULL);
+ webkit_user_content_manager_add_script(ucm, script);
+ webkit_user_script_unref(script);
+
+ /* Setup script message handlers. */
+ webkit_user_content_manager_register_script_message_handler(ucm, "focus");
+ g_signal_connect(ucm, "script-message-received::focus", G_CALLBACK(on_script_message_focus), c);
+
return new;
}
+static void on_script_message_focus(WebKitUserContentManager *manager,
+ WebKitJavascriptResult *message, Client *c)
+{
+ gboolean is_focused;
+
+ is_focused = (gboolean)util_js_result_as_number(message);
+ /* Don't change the mode if we are in pass through mode. */
+ if (c->mode->id == 'n' && is_focused) {
+ vb_enter(c, 'i');
+ } else if (c->mode->id == 'i' && !is_focused) {
+ vb_enter(c, 'n');
+ }
+}
+
int main(int argc, char* argv[])
{
Client *c;
--- /dev/null
+/* Utility object injected into all frames. */
+var vimb = Object.freeze((function(){
+ 'use strict';
+ /* Checks if given element is editable */
+ function isEditable(e) {
+ if (e) {
+ var name = e.tagName.toLowerCase();
+ return e.isContentEditable
+ || name == "textarea"
+ || (name == "input" && /^(?:color|date|datetime|datetime-local|email|month|number|password|search|tel|text|time|url|week)$/i.test(e.type));
+ }
+ return false;
+ }
+
+ return {
+ init: function() {
+ var b = document.body;
+ b.addEventListener(
+ "focus",
+ function(ev) {
+ var e = ev.target, n;
+ if (isEditable(e)) {
+ window.webkit.messageHandlers.focus.postMessage(1);
+ }
+ },
+ true
+ );
+ b.addEventListener(
+ "blur",
+ function() {
+ window.webkit.messageHandlers.focus.postMessage(0);
+ },
+ true
+ );
+ }
+ };
+})());
+vimb.init();
#include <ctype.h>
#include <fcntl.h>
#include <glib.h>
+#include <JavaScriptCore/JavaScript.h>
#include <pwd.h>
#include <stdio.h>
#include <string.h>
return found;
}
+char *util_js_result_as_string(WebKitJavascriptResult *result)
+{
+ JSValueRef value;
+ JSStringRef string;
+ size_t len;
+ char *retval = NULL;
+
+ value = webkit_javascript_result_get_value(result);
+ string = JSValueToStringCopy(webkit_javascript_result_get_global_context(result),
+ value, NULL);
+
+ len = JSStringGetMaximumUTF8CStringSize(string);
+ if (len) {
+ retval = g_malloc(len);
+ JSStringGetUTF8CString(string, retval, len);
+ }
+ JSStringRelease(string);
+
+ return retval;
+}
+
+double util_js_result_as_number(WebKitJavascriptResult *result)
+{
+ JSValueRef value = webkit_javascript_result_get_value(result);
+
+ return JSValueToNumber(webkit_javascript_result_get_global_context(result), value,
+ NULL);
+}
+
/**
* Reads given input and try to parse ~/, ~user, $VAR or ${VAR} expansion
* from the start of the input and moves the input pointer to the first
guint max_items);
gboolean util_fill_completion(GtkListStore *store, const char *input, GList *src);
gboolean util_filename_fill_completion(Client *c, GtkListStore *store, const char *input);
+char *util_js_result_as_string(WebKitJavascriptResult *result);
+double util_js_result_as_number(WebKitJavascriptResult *result);
gboolean util_parse_expansion(Client *c, const char **input, GString *str,
int flags, const char *quoteable);
char *util_str_replace(const char* search, const char* replace, const char* string);
static void emit_page_created(GDBusConnection *connection, guint64 pageid);
static void emit_page_created_pending(GDBusConnection *connection);
static void queue_page_created_signal(guint64 pageid);
+#if 0
static void dbus_emit_signal(const char *name, WebKitWebExtension* extension,
GVariant *data);
+#endif
static void dbus_handle_method_call(GDBusConnection *conn, const char *sender,
const char *object_path, const char *interface_name, const char *method,
GVariant *parameters, GDBusMethodInvocation *invocation, gpointer data);
-static void on_editable_change_focus(WebKitDOMEventTarget *target,
- WebKitDOMEvent *event, WebKitWebExtension *extension);
static void on_page_created(WebKitWebExtension *ext, WebKitWebPage *webpage, gpointer data);
static void on_web_page_document_loaded(WebKitWebPage *webpage, gpointer extension);
static gboolean on_web_page_send_request(WebKitWebPage *webpage, WebKitURIRequest *request,
static const char introspection_xml[] =
"<node>"
" <interface name='" VB_WEBEXTENSION_INTERFACE "'>"
- " <signal name='EditableChangeFocus'>"
- " <arg type='b' name='focused' direction='out'/>"
- " </signal>"
" <method name='FocusInput'>"
" </method>"
" <signal name='PageCreated'>"
static void add_onload_event_observers(WebKitDOMDocument *doc,
WebKitWebExtension *extension)
{
+#if 0 /* might soon be use for some events */
WebKitDOMEventTarget *target;
/* Add the document to the table of known documents or if already exists
* function is called with content document of an iframe. Else the event
* observing does not work. */
target = WEBKIT_DOM_EVENT_TARGET(webkit_dom_document_get_default_view(doc));
-
- webkit_dom_event_target_add_event_listener(target, "focus",
- G_CALLBACK(on_editable_change_focus), TRUE, extension);
- webkit_dom_event_target_add_event_listener(target, "blur",
- G_CALLBACK(on_editable_change_focus), TRUE, extension);
- /* Check for focused editable elements also if they where focused before
- * the event observer where set up. */
- /* TODO this is not needed for strict-focus=on */
- on_editable_change_focus(target, NULL, extension);
+#endif
}
/**
ext.page_created_signals = g_array_append_val(ext.page_created_signals, pageid);
}
+#if 0
/**
* Emits a signal over dbus.
*
g_error_free(error);
}
}
+#endif
/**
* Handle dbus method calls.
}
}
-/**
- * Callback called if a editable element changes it focus state.
- * Event target may be a WebKitDOMDocument (in case of iframe) or a
- * WebKitDOMDOMWindow.
- */
-static void on_editable_change_focus(WebKitDOMEventTarget *target,
- WebKitDOMEvent *event, WebKitWebExtension *extension)
-{
- gboolean input_focus;
- WebKitDOMDocument *doc;
- WebKitDOMElement *active;
-
- if (WEBKIT_DOM_IS_DOM_WINDOW(target)) {
- g_object_get(target, "document", &doc, NULL);
- } else {
- /* target is a doc document */
- doc = WEBKIT_DOM_DOCUMENT(target);
- }
- active = webkit_dom_document_get_active_element(doc);
- /* Don't do anything if there is no active element or the active element
- * is the same as before. */
- if (!active || active == ext.active) {
- return;
- }
- if (WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT(active)) {
- WebKitDOMHTMLIFrameElement *iframe;
- WebKitDOMDocument *subdoc;
-
- iframe = WEBKIT_DOM_HTML_IFRAME_ELEMENT(active);
- subdoc = webkit_dom_html_iframe_element_get_content_document(iframe);
- add_onload_event_observers(subdoc, extension);
- return;
- }
-
- ext.active = active;
-
- /* Check if the active element is an editable element. */
- input_focus = ext_dom_is_editable(active);
- if (input_focus != ext.input_focus) {
- ext.input_focus = input_focus;
-
- dbus_emit_signal("EditableChangeFocus", extension,
- g_variant_new("(b)", input_focus));
- }
-}
-
/**
* Callback for web extensions page-created signal.
*/