From 8cfde671558bbfb53bd68ec8891ca852537715f1 Mon Sep 17 00:00:00 2001 From: Daniel Carl Date: Tue, 6 Aug 2013 20:32:47 +0200 Subject: [PATCH] Focus only visible items with 'focus-input' (#47). --- src/dom.c | 58 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/src/dom.c b/src/dom.c index 5a40fd4..65d9c43 100644 --- a/src/dom.c +++ b/src/dom.c @@ -23,6 +23,7 @@ extern VbCore vb; +static gboolean element_is_visible(WebKitDOMDOMWindow* win, WebKitDOMElement* element); static gboolean auto_insert(Element *element); static gboolean editable_focus_cb(Element *element, Event *event); static Element *get_active_element(Document *doc); @@ -64,22 +65,42 @@ void dom_clear_focus(WebKitWebView *view) gboolean dom_focus_input(WebKitWebView *view) { gboolean found = false; - gulong count; - WebKitDOMDocument *doc = webkit_web_view_get_dom_document(view); - WebKitDOMNodeList *elems = webkit_dom_document_get_elements_by_tag_name(doc, "*"); - Element *elem; + WebKitDOMNode *html, *node; + WebKitDOMDocument *doc; + WebKitDOMDOMWindow *win; + WebKitDOMNodeList *list; + WebKitDOMXPathNSResolver *resolver; + WebKitDOMXPathResult* result; + + doc = webkit_web_view_get_dom_document(view); + win = webkit_dom_document_get_default_view(doc); + list = webkit_dom_document_get_elements_by_tag_name(doc, "html"); + if (!list) { + return false; + } + + html = webkit_dom_node_list_item(list, 0); - count = webkit_dom_node_list_get_length(elems); - for (int i = 0; i < count; i++) { - elem = WEBKIT_DOM_ELEMENT(webkit_dom_node_list_item(elems, i)); + resolver = webkit_dom_document_create_ns_resolver(doc, html); + if (!resolver) { + return false; + } - if (dom_is_editable(elem)) { - webkit_dom_element_focus(elem); + result = webkit_dom_document_evaluate( + doc, "//input[@type='text']|//input[@type='password']|//textarea", + html, resolver, 0, NULL, NULL + ); + if (!result) { + return false; + } + while ((node = webkit_dom_xpath_result_iterate_next(result, NULL))) { + if (element_is_visible(win, WEBKIT_DOM_ELEMENT(node))) { + webkit_dom_element_focus(WEBKIT_DOM_ELEMENT(node)); found = true; break; } } - g_object_unref(elems); + g_object_unref(list); return found; } @@ -154,6 +175,23 @@ void dom_editable_element_set_disable(Element *element, gboolean value) } } +static gboolean element_is_visible(WebKitDOMDOMWindow* win, WebKitDOMElement* element) +{ + gchar* value = NULL; + + WebKitDOMCSSStyleDeclaration* style = webkit_dom_dom_window_get_computed_style(win, element, ""); + value = webkit_dom_css_style_declaration_get_property_value(style, "visibility"); + if (value && g_ascii_strcasecmp(value, "hidden") == 0) { + return false; + } + value = webkit_dom_css_style_declaration_get_property_value(style, "display"); + if (value && g_ascii_strcasecmp(value, "none") == 0) { + return false; + } + + return true; +} + static gboolean auto_insert(Element *element) { if (dom_is_editable(element)) { -- 2.20.1