"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