Check for dom focus/blur event on window object cleared (#201).
authorDaniel Carl <danielcarl@gmx.de>
Sun, 26 Apr 2015 21:30:36 +0000 (23:30 +0200)
committerDaniel Carl <danielcarl@gmx.de>
Sun, 26 Apr 2015 21:39:29 +0000 (23:39 +0200)
This allows us to track also focus changes within frames and iframes also  if
they are loaded dynamically. The previous logic added the event listeners to
the document on WEBKIT_LOAD_FINISHED, but if there where later created iframes
in the dom, these where not observers for focus events.
This is only a first attempt to fix the focus issue and does break the logic
behind `set strict-focus=on`.

src/dom.c
src/dom.h
src/main.c
tests/manual/201-editable-focus-in-iframes.html [new file with mode: 0644]

index a151d6b..75457d5 100644 (file)
--- a/src/dom.c
+++ b/src/dom.c
@@ -30,37 +30,40 @@ static gboolean editable_focus_cb(Element *element, Event *event);
 static Element *get_active_element(Document *doc);
 
 
-void dom_check_auto_insert(WebKitWebView *view)
+void dom_check_auto_insert(Document *doc)
 {
     Element *active;
     HtmlElement *element;
-    Document *doc = webkit_web_view_get_dom_document(view);
 
-    /* FIrst check for current active element that bocomes focused before we
+    /* First check for current active element that becomes focused before we
      * could add the evnet observers. */
-    active = get_active_element(doc);
-    if (!vb.config.strict_focus) {
-        auto_insert(active);
-    } else if (vb.mode->id != 'i') {
-        /* If strict-focus is enabled and the editable element becomes focus,
-         * we explicitely remove the focus. But only if vim isn't in input
-         * mode at the time. This prevents from leaving input mode that was
-         * started by user interaction like click to editable element, or the
-         * gi normal mode command. */
-        webkit_dom_element_blur(active);
+    active = webkit_dom_html_document_get_active_element(WEBKIT_DOM_HTML_DOCUMENT(doc));
+    if (active) {
+        if (!vb.config.strict_focus) {
+            auto_insert(active);
+        } else if (vb.mode->id != 'i') {
+            /* If strict-focus is enabled and the editable element becomes
+             * focus, we explicitely remove the focus. But only if vim isn't
+             * in input mode at the time. This prevents from leaving input
+             * mode that was started by user interaction like click to
+             * editable element, or the gi normal mode command. */
+            webkit_dom_element_blur(active);
+        }
     }
 
     element = webkit_dom_document_get_body(doc);
     if (!element) {
         element = WEBKIT_DOM_HTML_ELEMENT(webkit_dom_document_get_document_element(doc));
     }
-    /* add event listener to track focus and blur events on the document */
-    webkit_dom_event_target_add_event_listener(
-        WEBKIT_DOM_EVENT_TARGET(element), "blur", G_CALLBACK(editable_blur_cb), true, NULL
-    );
-    webkit_dom_event_target_add_event_listener(
-        WEBKIT_DOM_EVENT_TARGET(element), "focus", G_CALLBACK(editable_focus_cb), true, NULL
-    );
+    if (element) {
+        /* add event listener to track focus and blur events on the document */
+        webkit_dom_event_target_add_event_listener(
+            WEBKIT_DOM_EVENT_TARGET(element), "blur", G_CALLBACK(editable_blur_cb), true, NULL
+        );
+        webkit_dom_event_target_add_event_listener(
+            WEBKIT_DOM_EVENT_TARGET(element), "focus", G_CALLBACK(editable_focus_cb), true, NULL
+        );
+    }
 }
 
 /**
@@ -251,6 +254,7 @@ static gboolean auto_insert(Element *element)
 
 static gboolean editable_blur_cb(Element *element, Event *event)
 {
+    g_message("blur");
     if (vb.mode->id == 'i') {
         vb_enter('n');
     }
@@ -259,6 +263,7 @@ static gboolean editable_blur_cb(Element *element, Event *event)
 
 static gboolean editable_focus_cb(Element *element, Event *event)
 {
+    g_message("focus");
     auto_insert((Element*)webkit_dom_event_get_target(event));
 
     return false;
index 2c82281..a78b362 100644 (file)
--- a/src/dom.h
+++ b/src/dom.h
@@ -32,7 +32,7 @@
 #define HtmlInputElement    WebKitDOMHTMLInputElement
 #define HtmlTextareaElement WebKitDOMHTMLTextAreaElement
 
-void dom_check_auto_insert(WebKitWebView *view);
+void dom_check_auto_insert(Document *doc);
 void dom_clear_focus(WebKitWebView *view);
 void dom_focus_input(WebKitWebView *view);
 gboolean dom_is_editable(Element *element);
index 5b2d701..ba14735 100644 (file)
@@ -87,6 +87,8 @@ static gboolean navigation_decision_requested_cb(WebKitWebView *view,
     WebKitWebFrame *frame, WebKitNetworkRequest *request,
     WebKitWebNavigationAction *action, WebKitWebPolicyDecision *policy,
     gpointer data);
+static void window_object_cleared_cb(GtkWidget *widget, WebKitWebFrame *frame,
+    JSContextRef js, JSObjectRef win, gpointer user_data);
 static void hover_link_cb(WebKitWebView *webview, const char *title, const char *link);
 static void title_changed_cb(WebKitWebView *webview, WebKitWebFrame *frame, const char *title);
 static gboolean mimetype_decision_cb(WebKitWebView *webview,
@@ -776,7 +778,6 @@ static void webview_load_status_cb(WebKitWebView *view, GParamSpec *pspec)
             update_title();
 
             if (strncmp(uri, "about:", 6)) {
-                dom_check_auto_insert(view);
                 history_add(HISTORY_URL, uri, webkit_web_view_get_title(view));
             }
             break;
@@ -1131,6 +1132,7 @@ static void setup_signals()
         "signal::should-show-delete-interface-for-element", G_CALLBACK(gtk_false), NULL,
         "signal::resource-request-starting", G_CALLBACK(webview_request_starting_cb), NULL,
         "signal::navigation-policy-decision-requested", G_CALLBACK(navigation_decision_requested_cb), NULL,
+        "signal::window-object-cleared", G_CALLBACK(window_object_cleared_cb), NULL,
         NULL
     );
 
@@ -1408,6 +1410,13 @@ static gboolean navigation_decision_requested_cb(WebKitWebView *view,
     return false;
 }
 
+static void window_object_cleared_cb(GtkWidget *widget, WebKitWebFrame *frame,
+    JSContextRef js, JSObjectRef win, gpointer user_data)
+{
+    Document *doc = webkit_web_frame_get_dom_document(frame);
+    dom_check_auto_insert(doc);
+}
+
 static void hover_link_cb(WebKitWebView *webview, const char *title, const char *link)
 {
     char *message;
diff --git a/tests/manual/201-editable-focus-in-iframes.html b/tests/manual/201-editable-focus-in-iframes.html
new file mode 100644 (file)
index 0000000..d02c0fb
--- /dev/null
@@ -0,0 +1,9 @@
+<html>
+<head>
+<title>Track Focu/Blur also within iFrames</title>
+</head>
+<body>
+<iframe style="border: 1px solid #000; width: 500px; height: 500px;" src="./112-editable-focus.html"></iframe>
+</body>
+</html>
+