"Fossies" - the Fresh Open Source Software Archive 
Member "xombrero-1.6.4/inputfocus.c" (17 Feb 2015, 11489 Bytes) of package /linux/www/old/xombrero-1.6.4.tgz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "inputfocus.c" see the
Fossies "Dox" file reference documentation.
1 /*
2 * Copyright (c) 2011 Marco Peereboom <marco@peereboom.us>
3 * Copyright (c) 2012, 2013 Josh Rickmar <jrick@devio.us>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <xombrero.h>
19
20 #if WEBKIT_CHECK_VERSION(1, 5, 0)
21 /* we got the DOM API we need */
22
23 void
24 focus_body(WebKitDOMDocument *doc)
25 {
26 WebKitDOMNodeList *body = NULL;
27 WebKitDOMNode *n;
28 int i;
29
30 body = webkit_dom_document_get_elements_by_tag_name(doc, "body");
31 for (i = 0; i < webkit_dom_node_list_get_length(body); ++i) {
32 n = webkit_dom_node_list_item(body, i);
33 webkit_dom_element_focus((WebKitDOMElement *)n);
34 #if WEBKIT_CHECK_VERSION(1, 8, 0)
35 webkit_dom_html_element_click((WebKitDOMHTMLElement *)n);
36 #endif
37 break;
38 }
39 }
40
41 int
42 node_is_valid_entry(WebKitDOMNode *n)
43 {
44 if (n == NULL)
45 return (FALSE);
46
47 if (WEBKIT_DOM_IS_HTML_INPUT_ELEMENT(n) &&
48 webkit_dom_html_input_element_check_validity(
49 (WebKitDOMHTMLInputElement *)n))
50 return (TRUE);
51 if (WEBKIT_DOM_IS_HTML_TEXT_AREA_ELEMENT(n) &&
52 webkit_dom_html_text_area_element_check_validity(
53 (WebKitDOMHTMLTextAreaElement *)n))
54 return (TRUE);
55
56 return (FALSE);
57 }
58
59 int
60 focus_input_document(struct tab *t, WebKitDOMDocument *doc)
61 {
62 WebKitDOMNodeList *input = NULL, *textarea = NULL;
63 WebKitDOMNode *n;
64 char *es;
65 int i, rv = 0 /* not found */;
66
67 WebKitDOMHTMLTextAreaElement *ta;
68 WebKitDOMHTMLInputElement *in;
69
70 /* we are deliberately ignoring tab index! */
71
72 /* try input first */
73 input = webkit_dom_document_get_elements_by_tag_name(doc, "input");
74 for (i = 0; i < webkit_dom_node_list_get_length(input); i++) {
75 n = webkit_dom_node_list_item(input, i);
76 in = (WebKitDOMHTMLInputElement*)n;
77 g_object_get(G_OBJECT(in), "type", &es, (char *)NULL);
78 if ((g_strcmp0("text", es) && g_strcmp0("password",es)) ||
79 webkit_dom_html_input_element_get_disabled(in)) {
80 /* skip not text */
81 g_free(es);
82 continue;
83 }
84 webkit_dom_element_focus((WebKitDOMElement*)in);
85 #if WEBKIT_CHECK_VERSION(1, 8, 0)
86 webkit_dom_html_element_click((WebKitDOMHTMLElement*)in);
87 #endif
88 g_free(es);
89 rv = 1; /* found */
90 goto done;
91 }
92
93 /* now try textarea */
94 textarea = webkit_dom_document_get_elements_by_tag_name(doc, "textarea");
95 for (i = 0; i < webkit_dom_node_list_get_length(textarea); i++) {
96 n = webkit_dom_node_list_item(textarea, i);
97 ta = (WebKitDOMHTMLTextAreaElement*)n;
98 if (webkit_dom_html_text_area_element_get_disabled(ta)) {
99 /* it is hidden so skip */
100 continue;
101 }
102 webkit_dom_element_focus((WebKitDOMElement*)ta);
103 #if WEBKIT_CHECK_VERSION(1, 8, 0)
104 webkit_dom_html_element_click((WebKitDOMHTMLElement*)ta);
105 #endif
106 rv = 1; /* found */
107 goto done;
108 }
109 done:
110 if (input)
111 g_object_unref(input);
112 if (textarea)
113 g_object_unref(textarea);
114
115 return (rv);
116 }
117
118 char *
119 get_element_text(WebKitDOMNode *n)
120 {
121 if (WEBKIT_DOM_IS_HTML_INPUT_ELEMENT(n))
122 return (g_strdup(webkit_dom_html_input_element_get_value(
123 (WebKitDOMHTMLInputElement *)n)));
124 else if (WEBKIT_DOM_IS_HTML_TEXT_AREA_ELEMENT(n))
125 return (g_strdup(webkit_dom_html_text_area_element_get_value(
126 (WebKitDOMHTMLTextAreaElement *)n)));
127 return (NULL);
128 }
129
130 int
131 focus_input(struct tab *t)
132 {
133 WebKitDOMDocument *doc;
134 WebKitDOMNode *n;
135 WebKitDOMNodeList *fl = NULL, *ifl = NULL;
136 WebKitDOMElement *a;
137 int i, fl_count, ifl_count, rv = 0; /* not found */
138
139 WebKitDOMHTMLFrameElement *frame;
140 WebKitDOMHTMLIFrameElement *iframe;
141
142 /*
143 * Here is what we are doing:
144 *
145 * If a textbox is already focused, leave it alone.
146 *
147 * Try the tab's previous active entry, for example if it was set by
148 * some javascript when the page loaded.
149 *
150 * See if we got frames or iframes
151 *
152 * if we do focus on input or textarea in frame or in iframe
153 *
154 * if we find nothing or there are no frames focus on first input or
155 * text area
156 */
157
158 doc = webkit_web_view_get_dom_document(t->wv);
159 #if WEBKIT_CHECK_VERSION(2, 0, 0)
160 /* This check is broken on old webkit */
161 if (!WEBKIT_DOM_IS_HTML_DOCUMENT(doc)) {
162 show_oops(t, "%s: DOM node is not a valid HTML document",
163 __func__);
164 goto done;
165 }
166 #endif
167
168 /* try current active element */
169 a = webkit_dom_html_document_get_active_element(
170 (WebKitDOMHTMLDocument*)doc);
171 if (node_is_valid_entry((WebKitDOMNode *)a)) {
172 rv = 1; /* found */
173 goto done;
174 }
175
176 /* try previous active element */
177 if (node_is_valid_entry((WebKitDOMNode *)t->active)) {
178 webkit_dom_element_focus((WebKitDOMElement*)t->active);
179 #if WEBKIT_CHECK_VERSION(1, 8, 0)
180 webkit_dom_html_element_click((WebKitDOMHTMLElement*)t->active);
181 #endif
182 rv = 1; /* found */
183 goto done;
184 } else {
185 if (t->active)
186 g_object_unref(t->active);
187 t->active = NULL;
188 if (t->active_text) {
189 g_free(t->active_text);
190 t->active_text = NULL;
191 }
192 }
193
194 /* get frames */
195 fl = webkit_dom_document_get_elements_by_tag_name(doc, "frame");
196 fl_count = webkit_dom_node_list_get_length(fl);
197
198 /* get iframes */
199 ifl = webkit_dom_document_get_elements_by_tag_name(doc, "iframe");
200 ifl_count = webkit_dom_node_list_get_length(ifl);
201
202 /* walk frames and look for a text input */
203 for (i = 0; i < fl_count; i++) {
204 n = webkit_dom_node_list_item(fl, i);
205 frame = (WebKitDOMHTMLFrameElement*)n;
206 doc = webkit_dom_html_frame_element_get_content_document(frame);
207
208 if (focus_input_document(t, doc)) {
209 rv = 1; /* focus */
210 goto done;
211 }
212 }
213
214 /* walk iframes and look for a text input */
215 for (i = 0; i < ifl_count; i++) {
216 n = webkit_dom_node_list_item(ifl, i);
217 iframe = (WebKitDOMHTMLIFrameElement*)n;
218 doc = webkit_dom_html_iframe_element_get_content_document(iframe);
219
220 if (focus_input_document(t, doc)) {
221 rv = 1; /* found */
222 goto done;
223 }
224 }
225
226 /* if we made it here nothing got focused so use normal heuristic */
227 if (focus_input_document(t, webkit_web_view_get_dom_document(t->wv)))
228 rv = 1; /* found */
229
230 done:
231 if (fl)
232 g_object_unref(fl);
233 if (ifl)
234 g_object_unref(ifl);
235
236 return (rv);
237 }
238
239 int
240 dom_is_input(struct tab *t, char **text)
241 {
242 WebKitDOMDocument *doc;
243 WebKitDOMElement *a;
244 WebKitDOMHTMLElement *aa;
245 WebKitDOMHTMLObjectElement *object;
246
247 WebKitDOMHTMLFrameElement *frame;
248 WebKitDOMHTMLIFrameElement *iframe;
249
250 /* proof positive that OO is stupid */
251
252 doc = webkit_web_view_get_dom_document(t->wv);
253
254 /* unwind frames and iframes until the cows come home */
255 for (;;) {
256 #if WEBKIT_CHECK_VERSION(2, 0, 0)
257 if (!WEBKIT_DOM_IS_HTML_DOCUMENT(doc))
258 return (0);
259 #endif
260 a = webkit_dom_html_document_get_active_element(
261 (WebKitDOMHTMLDocument*)doc);
262 if (a == NULL)
263 return (0);
264
265 frame = (WebKitDOMHTMLFrameElement *)a;
266 if (WEBKIT_DOM_IS_HTML_FRAME_ELEMENT(frame)) {
267 doc = webkit_dom_html_frame_element_get_content_document(
268 frame);
269 continue;
270 }
271
272 iframe = (WebKitDOMHTMLIFrameElement *)a;
273 if (WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT(iframe)) {
274 doc = webkit_dom_html_iframe_element_get_content_document(
275 iframe);
276 continue;
277 }
278
279 object = (WebKitDOMHTMLObjectElement *)a;
280 if (WEBKIT_DOM_IS_HTML_OBJECT_ELEMENT(object)) {
281 doc = webkit_dom_html_object_element_get_content_document(
282 object);
283 continue;
284 }
285
286 /*
287 * I think this is a total hack because this property isn't
288 * set for textareas or input however, it is set for jquery
289 * textareas that do rich text. Since this works around issues
290 * in RT we'll simply keep it!
291 *
292 * This might break some other stuff but for now it helps.
293 */
294 aa = (WebKitDOMHTMLElement*)a;
295 if (WEBKIT_DOM_IS_HTML_ELEMENT(aa) &&
296 webkit_dom_html_element_get_is_content_editable(aa)) {
297 if (t->active == NULL) {
298 t->active = a;
299 g_object_ref(t->active);
300 }
301 *text = get_element_text((WebKitDOMNode *)a);
302 if (t->active_text == NULL)
303 t->active_text = g_strdup(*text);
304 return (1);
305 }
306 break;
307 }
308
309 if (a == NULL)
310 return (0);
311
312 if (node_is_valid_entry((WebKitDOMNode *)a)) {
313 if (!node_is_valid_entry((WebKitDOMNode *)t->active)) {
314 if (t->active)
315 g_object_unref(t->active);
316 t->active = NULL;
317 if (t->active_text) {
318 g_free(t->active_text);
319 t->active_text = NULL;
320 }
321 }
322 if (t->active == NULL) {
323 t->active = a;
324 g_object_ref(t->active);
325 }
326 *text = get_element_text((WebKitDOMNode *)a);
327 if (t->active_text == NULL)
328 t->active_text = g_strdup(*text);
329 return (1);
330 }
331
332 return (0);
333 }
334
335 void *
336 input_check_mode(struct tab *t)
337 {
338 char *text = NULL;
339
340 if (dom_is_input(t, &text)) {
341 t->mode = XT_MODE_INSERT;
342 return (t->active);
343 } else
344 return (NULL);
345 }
346
347 int
348 command_mode(struct tab *t, struct karg *args)
349 {
350 WebKitDOMDocument *doc;
351 WebKitDOMElement *a;
352
353 if (args->i == XT_MODE_COMMAND) {
354 doc = webkit_web_view_get_dom_document(t->wv);
355 #if WEBKIT_CHECK_VERSION(2, 0, 0)
356 if (!WEBKIT_DOM_IS_HTML_DOCUMENT(doc)) {
357 show_oops(t, "%s: DOM node is not a valid HTML "
358 "document", __func__);
359 return (XT_CB_HANDLED);
360 }
361 #endif
362 a = webkit_dom_html_document_get_active_element(
363 (WebKitDOMHTMLDocument *)doc);
364 if (a) {
365 webkit_dom_element_blur(a);
366 focus_body(doc);
367 }
368 t->mode = XT_MODE_COMMAND;
369 } else if (args->i == XT_MODE_INSERT && focus_input(t))
370 t->mode = XT_MODE_INSERT;
371 else if (args->i == XT_MODE_HINT || args->i == XT_MODE_PASSTHROUGH)
372 t->mode = args->i;
373
374 if (!node_is_valid_entry((WebKitDOMNode *)t->active)) {
375 if (t->active)
376 g_object_unref(t->active);
377 t->active = NULL;
378 if (t->active_text) {
379 g_free(t->active_text);
380 t->active_text = NULL;
381 }
382 }
383
384 return (XT_CB_HANDLED);
385 }
386
387 void
388 input_autofocus(struct tab *t)
389 {
390 struct karg args = {0};
391 char *text = NULL;
392
393 if (autofocus_onload &&
394 t->tab_id == gtk_notebook_get_current_page(notebook)) {
395 if (focus_input(t))
396 t->mode = XT_MODE_INSERT;
397 else
398 t->mode = XT_MODE_COMMAND;
399 } else {
400 if (dom_is_input(t, &text)) {
401 if (text != NULL && g_strcmp0(text, t->active_text))
402 args.i = XT_MODE_INSERT;
403 else
404 args.i = XT_MODE_COMMAND;
405 } else
406 args.i = XT_MODE_COMMAND;
407 command_mode(t, &args);
408 }
409
410 if (text)
411 g_free(text);
412 }
413 #else /* WEBKIT_CHECK_VERSION */
414 /* incomplete DOM API */
415
416 /*
417 * XXX
418 * note that we can't check the return value of run_script so we
419 * have to assume that the command worked; this may leave you in
420 * insertmode when in fact you shouldn't be
421 */
422 void
423 input_autofocus(struct tab *t)
424 {
425 if (autofocus_onload &&
426 t->tab_id == gtk_notebook_get_current_page(notebook)) {
427 run_script(t, "hints.focusInput();");
428 t->mode = XT_MODE_INSERT;
429 } else {
430 run_script(t, "hints.clearFocus();");
431 t->mode = XT_MODE_COMMAND;
432 }
433 }
434
435 void *
436 input_check_mode(struct tab *t)
437 {
438 return (NULL);
439 }
440
441 int
442 command_mode(struct tab *t, struct karg *args)
443 {
444 if (args->i == XT_MODE_COMMAND) {
445 run_script(t, "hints.clearFocus();");
446 t->mode = XT_MODE_COMMAND;
447 } else {
448 run_script(t, "hints.focusInput();");
449 t->mode = XT_MODE_INSERT;
450 }
451
452 return (XT_CB_HANDLED);
453 }
454 #endif