2 * Copyright (c) 2011 Marco Peereboom <marco@peereboom.us>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #if WEBKIT_CHECK_VERSION(1, 5, 0)
20 /* we got the DOM API we need */
22 focus_input_document(struct tab
*t
, WebKitDOMDocument
*doc
)
24 WebKitDOMNodeList
*input
= NULL
, *textarea
= NULL
;
27 int i
, rv
= 0 /* not found */;
29 WebKitDOMHTMLTextAreaElement
*ta
;
30 WebKitDOMHTMLInputElement
*in
;
32 /* we are deliberately ignoring tab index! */
35 input
= webkit_dom_document_get_elements_by_tag_name(doc
, "input");
36 for (i
= 0; i
< webkit_dom_node_list_get_length(input
); i
++) {
37 n
= webkit_dom_node_list_item(input
, i
);
38 in
= (WebKitDOMHTMLInputElement
*)n
;
39 g_object_get(G_OBJECT(in
), "type", &es
, (char *)NULL
);
40 if ((!g_str_equal("text", es
) && !g_str_equal("password",es
)) ||
41 webkit_dom_html_input_element_get_disabled(in
)) {
46 webkit_dom_element_focus((WebKitDOMElement
*)in
);
52 /* now try textarea */
53 textarea
= webkit_dom_document_get_elements_by_tag_name(doc
, "textarea");
54 for (i
= 0; i
< webkit_dom_node_list_get_length(textarea
); i
++) {
55 n
= webkit_dom_node_list_item(textarea
, i
);
56 ta
= (WebKitDOMHTMLTextAreaElement
*)n
;
57 if (webkit_dom_html_text_area_element_get_disabled(ta
)) {
58 /* it is hidden so skip */
61 webkit_dom_element_focus((WebKitDOMElement
*)ta
);
67 g_object_unref(input
);
69 g_object_unref(textarea
);
74 focus_input(struct tab
*t
)
76 WebKitDOMDocument
*doc
;
78 WebKitDOMNodeList
*fl
= NULL
, *ifl
= NULL
;
79 int i
, fl_count
, ifl_count
, rv
= 0;
81 WebKitDOMHTMLFrameElement
*frame
;
82 WebKitDOMHTMLIFrameElement
*iframe
;
85 * Here is what we are doing:
86 * See if we got frames or iframes
88 * if we do focus on input or textarea in frame or in iframe
90 * if we find nothing or there are no frames focus on first input or
94 doc
= webkit_web_view_get_dom_document(t
->wv
);
97 fl
= webkit_dom_document_get_elements_by_tag_name(doc
, "frame");
98 fl_count
= webkit_dom_node_list_get_length(fl
);
101 ifl
= webkit_dom_document_get_elements_by_tag_name(doc
, "iframe");
102 ifl_count
= webkit_dom_node_list_get_length(ifl
);
104 /* walk frames and look for a text input */
105 for (i
= 0; i
< fl_count
; i
++) {
106 n
= webkit_dom_node_list_item(fl
, i
);
107 frame
= (WebKitDOMHTMLFrameElement
*)n
;
108 doc
= webkit_dom_html_frame_element_get_content_document(frame
);
110 if (focus_input_document(t
, doc
)) {
116 /* walk iframes and look for a text input */
117 for (i
= 0; i
< ifl_count
; i
++) {
118 n
= webkit_dom_node_list_item(ifl
, i
);
119 iframe
= (WebKitDOMHTMLIFrameElement
*)n
;
120 doc
= webkit_dom_html_iframe_element_get_content_document(iframe
);
122 if (focus_input_document(t
, doc
)) {
128 /* if we made it here nothing got focused so use normal heuristic */
129 if (focus_input_document(t
, webkit_web_view_get_dom_document(t
->wv
))) {
143 dom_is_input(struct tab
*t
, WebKitDOMElement
**active
)
145 WebKitDOMDocument
*doc
;
148 WebKitDOMHTMLFrameElement
*frame
;
149 WebKitDOMHTMLIFrameElement
*iframe
;
151 /* proof positive that OO is stupid */
153 doc
= webkit_web_view_get_dom_document(t
->wv
);
155 /* unwind frames and iframes until the cows come home */
157 a
= webkit_dom_html_document_get_active_element(
158 (WebKitDOMHTMLDocument
*)doc
);
163 * I think this is a total hack because this property isn't
164 * set for textareas or input however, it is set for jquery
165 * textareas that do rich text. Since this works around issues
166 * in RT we'll simply keep it!
168 * This might break some other stuff but for now it helps.
170 if (webkit_dom_html_element_get_is_content_editable(
171 (WebKitDOMHTMLElement
*)a
)) {
176 frame
= (WebKitDOMHTMLFrameElement
*)a
;
177 if (WEBKIT_DOM_IS_HTML_FRAME_ELEMENT(frame
)) {
178 doc
= webkit_dom_html_frame_element_get_content_document(
183 iframe
= (WebKitDOMHTMLIFrameElement
*)a
;
184 if (WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT(iframe
)) {
185 doc
= webkit_dom_html_iframe_element_get_content_document(
196 if (WEBKIT_DOM_IS_HTML_INPUT_ELEMENT((WebKitDOMNode
*)a
) ||
197 WEBKIT_DOM_IS_HTML_TEXT_AREA_ELEMENT((WebKitDOMNode
*)a
)) {
206 input_check_mode(struct tab
*t
)
208 WebKitDOMElement
*active
= NULL
;
210 if (dom_is_input(t
, &active
))
211 t
->mode
= XT_MODE_INSERT
;
213 t
->mode
= XT_MODE_COMMAND
;
219 input_focus_blur(struct tab
*t
, void *active
)
221 /* active is (WebKitDOMElement*) */
223 webkit_dom_element_blur(active
);
227 command_mode(struct tab
*t
, struct karg
*args
)
229 WebKitDOMElement
*active
= NULL
;
231 if (args
->i
== XT_MODE_COMMAND
) {
232 if (dom_is_input(t
, &active
))
234 webkit_dom_element_blur(active
);
235 t
->mode
= XT_MODE_COMMAND
;
238 t
->mode
= XT_MODE_INSERT
;
241 return (XT_CB_HANDLED
);
245 input_autofocus(struct tab
*t
)
247 WebKitDOMElement
*active
= NULL
;
249 if (autofocus_onload
&&
250 t
->tab_id
== gtk_notebook_get_current_page(notebook
)) {
252 t
->mode
= XT_MODE_INSERT
;
254 t
->mode
= XT_MODE_COMMAND
;
256 if (dom_is_input(t
, &active
))
258 webkit_dom_element_blur(active
);
259 t
->mode
= XT_MODE_COMMAND
;
262 #else /* WEBKIT_CHECK_VERSION */
263 /* incomplete DOM API */
267 * note that we can't check the return value of run_script so we
268 * have to assume that the command worked; this may leave you in
269 * insertmode when in fact you shouldn't be
272 input_autofocus(struct tab
*t
)
274 if (autofocus_onload
&&
275 t
->tab_id
== gtk_notebook_get_current_page(notebook
)) {
276 run_script(t
, "hints.focusInput();");
277 t
->mode
= XT_MODE_INSERT
;
279 run_script(t
, "hints.clearFocus();");
280 t
->mode
= XT_MODE_COMMAND
;
285 input_focus_blur(struct tab
*t
, void *active
)
287 run_script(t
, "hints.clearFocus();");
288 t
->mode
= XT_MODE_COMMAND
;
292 input_check_mode(struct tab
*t
)
298 command_mode(struct tab
*t
, struct karg
*args
)
300 if (args
->i
== XT_MODE_COMMAND
) {
301 run_script(t
, "hints.clearFocus();");
302 t
->mode
= XT_MODE_COMMAND
;
304 run_script(t
, "hints.focusInput();");
305 t
->mode
= XT_MODE_INSERT
;
308 return (XT_CB_HANDLED
);