Linux doesn't play nice with fputs return values, found the hard way by Ryan Mullen...
[xombrero.git] / inputfocus.c
blobfaebb3fef780125d933250fe17af2269306bf3b0
1 /*
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.
17 #include <xxxterm.h>
19 #if WEBKIT_CHECK_VERSION(1, 5, 0)
20 /* we got the DOM API we need */
21 int
22 focus_input_document(struct tab *t, WebKitDOMDocument *doc)
24 WebKitDOMNodeList *input = NULL, *textarea = NULL;
25 WebKitDOMNode *n;
26 char *es;
27 int i, rv = 0 /* not found */;
29 WebKitDOMHTMLTextAreaElement *ta;
30 WebKitDOMHTMLInputElement *in;
32 /* we are deliberately ignoring tab index! */
34 /* try input first */
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)) {
42 /* skip not text */
43 g_free(es);
44 continue;
46 webkit_dom_element_focus((WebKitDOMElement*)in);
47 g_free(es);
48 rv = 1; /* found */
49 goto done;
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 */
59 continue;
61 webkit_dom_element_focus((WebKitDOMElement*)ta);
62 rv = 1; /* found */
63 goto done;
65 done:
66 if (input)
67 g_object_unref(input);
68 if (textarea)
69 g_object_unref(textarea);
71 return (rv);
73 int
74 focus_input(struct tab *t)
76 WebKitDOMDocument *doc;
77 WebKitDOMNode *n;
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
91 * text area
94 doc = webkit_web_view_get_dom_document(t->wv);
96 /* get frames */
97 fl = webkit_dom_document_get_elements_by_tag_name(doc, "frame");
98 fl_count = webkit_dom_node_list_get_length(fl);
100 /* get iframes */
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)) {
111 rv = 1;
112 goto done;
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)) {
123 rv = 1;
124 goto done;
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))) {
130 rv = 1;
131 goto done;
133 done:
134 if (fl)
135 g_object_unref(fl);
136 if (ifl)
137 g_object_unref(ifl);
139 return (rv);
143 dom_is_input(struct tab *t, WebKitDOMElement **active)
145 WebKitDOMDocument *doc;
146 WebKitDOMElement *a;
147 WebKitDOMHTMLElement *aa;
148 WebKitDOMHTMLObjectElement *object;
150 WebKitDOMHTMLFrameElement *frame;
151 WebKitDOMHTMLIFrameElement *iframe;
153 /* proof positive that OO is stupid */
155 doc = webkit_web_view_get_dom_document(t->wv);
157 /* unwind frames and iframes until the cows come home */
158 for (;;) {
159 a = webkit_dom_html_document_get_active_element(
160 (WebKitDOMHTMLDocument*)doc);
161 if (a == NULL)
162 return (0);
164 frame = (WebKitDOMHTMLFrameElement *)a;
165 if (WEBKIT_DOM_IS_HTML_FRAME_ELEMENT(frame)) {
166 doc = webkit_dom_html_frame_element_get_content_document(
167 frame);
168 continue;
171 iframe = (WebKitDOMHTMLIFrameElement *)a;
172 if (WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT(iframe)) {
173 doc = webkit_dom_html_iframe_element_get_content_document(
174 iframe);
175 continue;
178 object = (WebKitDOMHTMLObjectElement *)a;
179 if (WEBKIT_DOM_IS_HTML_OBJECT_ELEMENT(object)) {
180 doc = webkit_dom_html_object_element_get_content_document(
181 object);
182 continue;
186 * I think this is a total hack because this property isn't
187 * set for textareas or input however, it is set for jquery
188 * textareas that do rich text. Since this works around issues
189 * in RT we'll simply keep it!
191 * This might break some other stuff but for now it helps.
193 aa = (WebKitDOMHTMLElement*)a;
194 if (WEBKIT_DOM_IS_HTML_ELEMENT(aa) &&
195 webkit_dom_html_element_get_is_content_editable(aa)) {
196 *active = a;
197 return (1);
199 break;
202 if (a == NULL)
203 return (0);
205 if (WEBKIT_DOM_IS_HTML_INPUT_ELEMENT((WebKitDOMNode *)a) ||
206 WEBKIT_DOM_IS_HTML_TEXT_AREA_ELEMENT((WebKitDOMNode *)a)) {
207 *active = a;
208 return (1);
211 return (0);
214 void *
215 input_check_mode(struct tab *t)
217 WebKitDOMElement *active = NULL;
219 if (dom_is_input(t, &active))
220 t->mode = XT_MODE_INSERT;
222 return (active);
225 void
226 input_focus_blur(struct tab *t, void *active)
228 /* active is (WebKitDOMElement*) */
229 if (active)
230 webkit_dom_element_blur(active);
234 command_mode(struct tab *t, struct karg *args)
236 WebKitDOMElement *active = NULL;
238 if (args->i == XT_MODE_COMMAND) {
239 if (dom_is_input(t, &active))
240 if (active)
241 webkit_dom_element_blur(active);
242 t->mode = XT_MODE_COMMAND;
243 } else {
244 if (focus_input(t))
245 t->mode = XT_MODE_INSERT;
248 return (XT_CB_HANDLED);
251 void
252 input_autofocus(struct tab *t)
254 WebKitDOMElement *active = NULL;
256 if (autofocus_onload &&
257 t->tab_id == gtk_notebook_get_current_page(notebook)) {
258 if (focus_input(t))
259 t->mode = XT_MODE_INSERT;
260 else
261 t->mode = XT_MODE_COMMAND;
262 } else {
263 if (dom_is_input(t, &active))
264 if (active)
265 webkit_dom_element_blur(active);
266 t->mode = XT_MODE_COMMAND;
269 #else /* WEBKIT_CHECK_VERSION */
270 /* incomplete DOM API */
273 * XXX
274 * note that we can't check the return value of run_script so we
275 * have to assume that the command worked; this may leave you in
276 * insertmode when in fact you shouldn't be
278 void
279 input_autofocus(struct tab *t)
281 if (autofocus_onload &&
282 t->tab_id == gtk_notebook_get_current_page(notebook)) {
283 run_script(t, "hints.focusInput();");
284 t->mode = XT_MODE_INSERT;
285 } else {
286 run_script(t, "hints.clearFocus();");
287 t->mode = XT_MODE_COMMAND;
291 void
292 input_focus_blur(struct tab *t, void *active)
294 run_script(t, "hints.clearFocus();");
295 t->mode = XT_MODE_COMMAND;
298 void *
299 input_check_mode(struct tab *t)
301 return (NULL);
305 command_mode(struct tab *t, struct karg *args)
307 if (args->i == XT_MODE_COMMAND) {
308 run_script(t, "hints.clearFocus();");
309 t->mode = XT_MODE_COMMAND;
310 } else {
311 run_script(t, "hints.focusInput();");
312 t->mode = XT_MODE_INSERT;
315 return (XT_CB_HANDLED);
317 #endif