diff options
author | Josh Rickmar <jrick@devio.us> | 2012-08-14 16:31:15 -0400 |
---|---|---|
committer | Josh Rickmar <jrick@devio.us> | 2012-08-14 16:31:15 -0400 |
commit | 8db050048457eeda2a54f782fe4e6f0c5fabeb57 (patch) | |
tree | ca044850d4e856eca9c10d4cba9305095de9cd47 | |
parent | d53713ed449dc0afe4bf778158f8438b09fdc703 (diff) | |
download | xombrero-8db050048457eeda2a54f782fe4e6f0c5fabeb57.tar.gz |
Undo the backout of all the inputfocus changes.
We thought these were the cause of the focus bugs, but it was something else instead. Now that we have that fixed, these can go back in.
-rw-r--r-- | inputfocus.c | 196 | ||||
-rw-r--r-- | xombrero.c | 36 | ||||
-rw-r--r-- | xombrero.h | 7 |
3 files changed, 185 insertions, 54 deletions
diff --git a/inputfocus.c b/inputfocus.c index 9115e66..fc6f259 100644 --- a/inputfocus.c +++ b/inputfocus.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2011 Marco Peereboom <marco@peereboom.us> + * Copyright (c) 2012 Josh Rickmar <jrick@devio.us> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -18,6 +19,43 @@ #if WEBKIT_CHECK_VERSION(1, 5, 0) /* we got the DOM API we need */ + +void +focus_body(WebKitDOMDocument *doc) +{ + WebKitDOMNodeList *body = NULL; + WebKitDOMNode *n; + int i; + + body = webkit_dom_document_get_elements_by_tag_name(doc, "body"); + for (i = 0; i < webkit_dom_node_list_get_length(body); ++i) { + n = webkit_dom_node_list_item(body, i); + webkit_dom_element_focus((WebKitDOMElement *)n); +#if WEBKIT_CHECK_VERSION(1, 8, 0) + webkit_dom_html_element_click((WebKitDOMHTMLElement *)n); +#endif + break; + } +} + +int +node_is_valid_entry(WebKitDOMNode *n) +{ + if (n == NULL) + return (FALSE); + + if (WEBKIT_DOM_IS_HTML_INPUT_ELEMENT(n) && + webkit_dom_html_input_element_check_validity( + (WebKitDOMHTMLInputElement *)n)) + return (TRUE); + if (WEBKIT_DOM_IS_HTML_TEXT_AREA_ELEMENT(n) && + webkit_dom_html_text_area_element_check_validity( + (WebKitDOMHTMLTextAreaElement *)n)) + return (TRUE); + + return (FALSE); +} + int focus_input_document(struct tab *t, WebKitDOMDocument *doc) { @@ -37,13 +75,16 @@ focus_input_document(struct tab *t, WebKitDOMDocument *doc) n = webkit_dom_node_list_item(input, i); in = (WebKitDOMHTMLInputElement*)n; g_object_get(G_OBJECT(in), "type", &es, (char *)NULL); - if ((!g_str_equal("text", es) && !g_str_equal("password",es)) || + if ((g_strcmp0("text", es) && g_strcmp0("password",es)) || webkit_dom_html_input_element_get_disabled(in)) { /* skip not text */ g_free(es); continue; } webkit_dom_element_focus((WebKitDOMElement*)in); +#if WEBKIT_CHECK_VERSION(1, 8, 0) + webkit_dom_html_element_click((WebKitDOMHTMLElement*)in); +#endif g_free(es); rv = 1; /* found */ goto done; @@ -59,6 +100,9 @@ focus_input_document(struct tab *t, WebKitDOMDocument *doc) continue; } webkit_dom_element_focus((WebKitDOMElement*)ta); +#if WEBKIT_CHECK_VERSION(1, 8, 0) + webkit_dom_html_element_click((WebKitDOMHTMLElement*)ta); +#endif rv = 1; /* found */ goto done; } @@ -70,19 +114,39 @@ done: return (rv); } + +char * +get_element_text(WebKitDOMNode *n) +{ + if (WEBKIT_DOM_IS_HTML_INPUT_ELEMENT(n)) + return (g_strdup(webkit_dom_html_input_element_get_value( + (WebKitDOMHTMLInputElement *)n))); + else if (WEBKIT_DOM_IS_HTML_TEXT_AREA_ELEMENT(n)) + return (g_strdup(webkit_dom_html_text_area_element_get_value( + (WebKitDOMHTMLTextAreaElement *)n))); + return (NULL); +} + int focus_input(struct tab *t) { WebKitDOMDocument *doc; WebKitDOMNode *n; WebKitDOMNodeList *fl = NULL, *ifl = NULL; - int i, fl_count, ifl_count, rv = 0; + WebKitDOMElement *a; + int i, fl_count, ifl_count, rv = 0; /* not found */ WebKitDOMHTMLFrameElement *frame; WebKitDOMHTMLIFrameElement *iframe; /* * Here is what we are doing: + * + * If a textbox is already focused, leave it alone. + * + * Try the tab's previous active entry, for example if it was set by + * some javascript when the page loaded. + * * See if we got frames or iframes * * if we do focus on input or textarea in frame or in iframe @@ -93,6 +157,30 @@ focus_input(struct tab *t) doc = webkit_web_view_get_dom_document(t->wv); + /* try current active element */ + a = webkit_dom_html_document_get_active_element( + (WebKitDOMHTMLDocument*)doc); + if (node_is_valid_entry((WebKitDOMNode *)a)) { + rv = 1; /* found */ + goto done; + } + + /* try previous active element */ + if (node_is_valid_entry((WebKitDOMNode *)t->active)) { + webkit_dom_element_focus((WebKitDOMElement*)t->active); +#if WEBKIT_CHECK_VERSION(1, 8, 0) + webkit_dom_html_element_click((WebKitDOMHTMLElement*)t->active); +#endif + rv = 1; /* found */ + goto done; + } else { + t->active = NULL; + if (t->active_text) { + g_free(t->active_text); + t->active_text = NULL; + } + } + /* get frames */ fl = webkit_dom_document_get_elements_by_tag_name(doc, "frame"); fl_count = webkit_dom_node_list_get_length(fl); @@ -108,7 +196,7 @@ focus_input(struct tab *t) doc = webkit_dom_html_frame_element_get_content_document(frame); if (focus_input_document(t, doc)) { - rv = 1; + rv = 1; /* focus */ goto done; } } @@ -120,16 +208,15 @@ focus_input(struct tab *t) doc = webkit_dom_html_iframe_element_get_content_document(iframe); if (focus_input_document(t, doc)) { - rv = 1; + rv = 1; /* found */ goto done; } } /* if we made it here nothing got focused so use normal heuristic */ - if (focus_input_document(t, webkit_web_view_get_dom_document(t->wv))) { - rv = 1; - goto done; - } + if (focus_input_document(t, webkit_web_view_get_dom_document(t->wv))) + rv = 1; /* found */ + done: if (fl) g_object_unref(fl); @@ -140,7 +227,7 @@ done: } int -dom_is_input(struct tab *t, WebKitDOMElement **active) +dom_is_input(struct tab *t, char **text) { WebKitDOMDocument *doc; WebKitDOMElement *a; @@ -193,7 +280,11 @@ dom_is_input(struct tab *t, WebKitDOMElement **active) aa = (WebKitDOMHTMLElement*)a; if (WEBKIT_DOM_IS_HTML_ELEMENT(aa) && webkit_dom_html_element_get_is_content_editable(aa)) { - *active = a; + if (t->active == NULL) + t->active = a; + *text = get_element_text((WebKitDOMNode *)a); + if (t->active_text == NULL) + t->active_text = g_strdup(*text); return (1); } break; @@ -202,9 +293,19 @@ dom_is_input(struct tab *t, WebKitDOMElement **active) if (a == NULL) return (0); - if (WEBKIT_DOM_IS_HTML_INPUT_ELEMENT((WebKitDOMNode *)a) || - WEBKIT_DOM_IS_HTML_TEXT_AREA_ELEMENT((WebKitDOMNode *)a)) { - *active = a; + if (node_is_valid_entry((WebKitDOMNode *)a)) { + if (!node_is_valid_entry((WebKitDOMNode *)t->active)) { + t->active = NULL; + if (t->active_text) { + g_free(t->active_text); + t->active_text = NULL; + } + } + if (t->active == NULL) + t->active = a; + *text = get_element_text((WebKitDOMNode *)a); + if (t->active_text == NULL) + t->active_text = g_strdup(*text); return (1); } @@ -214,35 +315,41 @@ dom_is_input(struct tab *t, WebKitDOMElement **active) void * input_check_mode(struct tab *t) { - WebKitDOMElement *active = NULL; + char *text = NULL; - if (dom_is_input(t, &active)) + if (dom_is_input(t, &text)) { t->mode = XT_MODE_INSERT; - - return (active); -} - -void -input_focus_blur(struct tab *t, void *active) -{ - /* active is (WebKitDOMElement*) */ - if (active) - webkit_dom_element_blur(active); + return (t->active); + } else + return (NULL); } int command_mode(struct tab *t, struct karg *args) { - WebKitDOMElement *active = NULL; + WebKitDOMDocument *doc; + WebKitDOMElement *a; if (args->i == XT_MODE_COMMAND) { - if (dom_is_input(t, &active)) - if (active) - webkit_dom_element_blur(active); + doc = webkit_web_view_get_dom_document(t->wv); + a = webkit_dom_html_document_get_active_element( + (WebKitDOMHTMLDocument *)doc); + if (a) { + webkit_dom_element_blur(a); + focus_body(doc); + } t->mode = XT_MODE_COMMAND; - } else { - if (focus_input(t)) - t->mode = XT_MODE_INSERT; + } else if (args->i == XT_MODE_INSERT && focus_input(t)) + t->mode = XT_MODE_INSERT; + else if (args->i == XT_MODE_HINT || args->i == XT_MODE_PASSTHROUGH) + t->mode = args->i; + + if (!node_is_valid_entry((WebKitDOMNode *)t->active)) { + t->active = NULL; + if (t->active_text) { + g_free(t->active_text); + t->active_text = NULL; + } } return (XT_CB_HANDLED); @@ -251,7 +358,8 @@ command_mode(struct tab *t, struct karg *args) void input_autofocus(struct tab *t) { - WebKitDOMElement *active = NULL; + struct karg args = {0}; + char *text = NULL; if (autofocus_onload && t->tab_id == gtk_notebook_get_current_page(notebook)) { @@ -260,11 +368,18 @@ input_autofocus(struct tab *t) else t->mode = XT_MODE_COMMAND; } else { - if (dom_is_input(t, &active)) - if (active) - webkit_dom_element_blur(active); - t->mode = XT_MODE_COMMAND; + if (dom_is_input(t, &text)) { + if (text != NULL && g_strcmp0(text, t->active_text)) + args.i = XT_MODE_INSERT; + else + args.i = XT_MODE_COMMAND; + } else + args.i = XT_MODE_COMMAND; + command_mode(t, &args); } + + if (text) + g_free(text); } #else /* WEBKIT_CHECK_VERSION */ /* incomplete DOM API */ @@ -288,13 +403,6 @@ input_autofocus(struct tab *t) } } -void -input_focus_blur(struct tab *t, void *active) -{ - run_script(t, "hints.clearFocus();"); - t->mode = XT_MODE_COMMAND; -} - void * input_check_mode(struct tab *t) { diff --git a/xombrero.c b/xombrero.c index d02d471..53b68f3 100644 --- a/xombrero.c +++ b/xombrero.c @@ -476,6 +476,7 @@ hide_cmd(struct tab *t) history_at = NULL; /* just in case */ search_at = NULL; /* just in case */ + gtk_widget_set_can_focus(t->cmd, FALSE); gtk_widget_hide(t->cmd); } @@ -487,6 +488,7 @@ show_cmd(struct tab *t) history_at = NULL; search_at = NULL; gtk_widget_hide(t->oops); + gtk_widget_set_can_focus(t->cmd, TRUE); gtk_widget_show(t->cmd); } @@ -494,6 +496,7 @@ void hide_buffers(struct tab *t) { gtk_widget_hide(t->buffers); + gtk_widget_set_can_focus(t->buffers, FALSE); gtk_list_store_clear(buffers_store); } @@ -567,6 +570,7 @@ show_buffers(struct tab *t) gtk_tree_path_free(path); gtk_widget_show(t->buffers); + gtk_widget_set_can_focus(t->buffers, TRUE); gtk_widget_grab_focus(GTK_WIDGET(t->buffers)); } @@ -2805,7 +2809,7 @@ struct prompt_sub { int command(struct tab *t, struct karg *args) { - struct karg a; + struct karg a = {0}; int i; char *s = NULL, *sp = NULL, *sl = NULL; gchar **sv; @@ -2851,14 +2855,12 @@ command(struct tab *t, struct karg *args) break; case '.': t->mode = XT_MODE_HINT; - bzero(&a, sizeof a); a.i = 0; hint(t, &a); s = "."; break; case ',': t->mode = XT_MODE_HINT; - bzero(&a, sizeof a); a.i = XT_HINT_NEWTAB; hint(t, &a); s = ","; @@ -4227,6 +4229,15 @@ notify_load_status_cb(WebKitWebView* wview, GParamSpec* pspec, struct tab *t) g_free(base); #endif + /* DOM is changing, unreference the previous focused element */ +#if WEBKIT_CHECK_VERSION(1, 5, 0) + t->active = NULL; + if (t->active_text) { + g_free(t->active_text); + t->active_text = NULL; + } +#endif + /* take focus if we are visible */ focus_webview(t); t->focus_wv = 1; @@ -7000,6 +7011,7 @@ create_browser(struct tab *t) } w = gtk_scrolled_window_new(NULL, NULL); + gtk_widget_set_can_focus(w, FALSE); t->adjust_h = gtk_scrolled_window_get_hadjustment( GTK_SCROLLED_WINDOW(w)); t->adjust_v = gtk_scrolled_window_get_vadjustment( @@ -7115,16 +7127,13 @@ create_toolbar(struct tab *t) gtk_widget_set_sensitive(t->forward, FALSE); g_signal_connect(G_OBJECT(t->forward), "clicked", G_CALLBACK(forward_cb), t); - gtk_box_pack_start(GTK_BOX(b), t->forward, FALSE, - FALSE, 0); + gtk_box_pack_start(GTK_BOX(b), t->forward, FALSE, FALSE, 0); /* stop button */ t->stop = create_button("Stop", GTK_STOCK_STOP, 0); gtk_widget_set_sensitive(t->stop, FALSE); - g_signal_connect(G_OBJECT(t->stop), "clicked", - G_CALLBACK(stop_cb), t); - gtk_box_pack_start(GTK_BOX(b), t->stop, FALSE, - FALSE, 0); + g_signal_connect(G_OBJECT(t->stop), "clicked", G_CALLBACK(stop_cb), t); + gtk_box_pack_start(GTK_BOX(b), t->stop, FALSE, FALSE, 0); /* JS button */ t->js_toggle = create_button("JS-Toggle", enable_scripts ? @@ -7651,13 +7660,19 @@ create_new_tab(char *title, struct undo *u, int focus, int position) t->vbox = gtk_vbox_new(FALSE, 0); b = gtk_hbox_new(FALSE, 0); #endif + gtk_widget_set_can_focus(t->vbox, FALSE); /* label + button for tab */ t->tab_content = b; + gtk_widget_set_can_focus(t->tab_content, FALSE); t->user_agent_id = 0; t->http_accept_id = 0; +#if WEBKIT_CHECK_VERSION(1, 5, 0) + t->active = NULL; +#endif + #if GTK_CHECK_VERSION(2, 20, 0) t->spinner = gtk_spinner_new(); #endif @@ -8068,6 +8083,7 @@ create_button(char *name, char *stockid, int size) g_free(newstyle); #endif button = gtk_button_new(); + gtk_widget_set_can_focus(button, FALSE); gtk_button_set_focus_on_click(GTK_BUTTON(button), FALSE); gtk_icon_size = icon_size_map(size ? size : icon_size); @@ -8107,6 +8123,7 @@ create_canvas(void) vbox = gtk_vbox_new(FALSE, 0); #endif gtk_box_set_spacing(GTK_BOX(vbox), 0); + gtk_widget_set_can_focus(vbox, FALSE); notebook = GTK_NOTEBOOK(gtk_notebook_new()); #if !GTK_CHECK_VERSION(3, 0, 0) /* XXX seems to be needed with gtk+2 */ @@ -8117,6 +8134,7 @@ create_canvas(void) gtk_widget_set_can_focus(GTK_WIDGET(notebook), FALSE); abtn = gtk_button_new(); + gtk_widget_set_can_focus(abtn, FALSE); arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE); gtk_widget_set_name(abtn, "Arrow"); gtk_container_add(GTK_CONTAINER(abtn), arrow); diff --git a/xombrero.h b/xombrero.h index 64ac54a..094e3cc 100644 --- a/xombrero.h +++ b/xombrero.h @@ -285,6 +285,12 @@ struct tab { WebKitWebInspector *inspector; GtkWidget *inspector_window; GtkWidget *inspector_view; + + /* focused text entry */ +#if WEBKIT_CHECK_VERSION(1, 5, 0) + WebKitDOMElement *active; + char *active_text; +#endif }; TAILQ_HEAD(tab_list, tab); @@ -566,7 +572,6 @@ int toggle_force_https(struct tab *, struct karg *); /* input autofocus */ void input_autofocus(struct tab *); -void input_focus_blur(struct tab *, void *); void *input_check_mode(struct tab *); int command_mode(struct tab *, struct karg *); |