about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorJosh Rickmar <jrick@devio.us>2012-06-20 16:51:24 -0400
committerJosh Rickmar <jrick@devio.us>2012-06-28 15:26:21 -0400
commitead88eca150b84b8fad610e5181dc0f08225751d (patch)
tree8af555d488ef20ff7e88606c759817800814e98a
parentee30c86ecbe478be1a9279571cfc5011a2dae8f8 (diff)
downloadxombrero-ead88eca150b84b8fad610e5181dc0f08225751d.tar.gz
Save a pointer to the text entry box that is focused when the page is
load for each tab.  Try to use this first when using the insert_mode
command instead of just focusing on the first text box in the html.

Don't switch to command mode if the currently-focused input box
contains any text in it.  This prevents an annoying switch to command
after the page has focused a particular element and the user has
already begun typing something.
-rw-r--r--inputfocus.c108
-rw-r--r--xombrero.c5
-rw-r--r--xombrero.h4
3 files changed, 78 insertions, 39 deletions
diff --git a/inputfocus.c b/inputfocus.c
index 4fcda11..ccb371c 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
@@ -72,19 +73,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
@@ -95,6 +116,24 @@ 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 (WEBKIT_DOM_IS_HTML_INPUT_ELEMENT((WebKitDOMNode *)a) ||
+	    WEBKIT_DOM_IS_HTML_TEXT_AREA_ELEMENT((WebKitDOMNode *)a)) {
+		rv = 1; /* found */
+		goto done;
+	}
+
+	/* try previous active element */
+	if (WEBKIT_DOM_IS_HTML_INPUT_ELEMENT((WebKitDOMNode *)t->active) ||
+	    WEBKIT_DOM_IS_HTML_TEXT_AREA_ELEMENT((WebKitDOMNode *)t->active)) {
+		webkit_dom_element_focus((WebKitDOMElement*)t->active);
+		webkit_dom_html_element_click((WebKitDOMHTMLElement*)t->active);
+		rv = 1; /* found */
+		goto done;
+	}
+
 	/* get frames */
 	fl = webkit_dom_document_get_elements_by_tag_name(doc, "frame");
 	fl_count = webkit_dom_node_list_get_length(fl);
@@ -110,7 +149,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;
 		}
 	}
@@ -122,16 +161,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);
@@ -142,7 +180,7 @@ done:
 }
 
 int
-dom_is_input(struct tab *t, WebKitDOMElement **active)
+dom_is_input(struct tab *t, char **text)
 {
 	WebKitDOMDocument	*doc;
 	WebKitDOMElement	*a;
@@ -195,7 +233,8 @@ 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;
+			t->active = a;
+			*text = get_element_text((WebKitDOMNode *)a);
 			return (1);
 		}
 		break;
@@ -206,7 +245,8 @@ dom_is_input(struct tab *t, WebKitDOMElement **active)
 
 	if (WEBKIT_DOM_IS_HTML_INPUT_ELEMENT((WebKitDOMNode *)a) ||
 	    WEBKIT_DOM_IS_HTML_TEXT_AREA_ELEMENT((WebKitDOMNode *)a)) {
-		*active = a;
+		t->active = a;
+		*text = get_element_text((WebKitDOMNode *)a);
 		return (1);
 	}
 
@@ -216,31 +256,24 @@ 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;
+	char			*text = NULL;
 
 	if (args->i == XT_MODE_COMMAND) {
-		if (dom_is_input(t, &active))
-			if (active)
-				webkit_dom_element_blur(active);
+		if (dom_is_input(t, &text))
+			if (t->active)
+				webkit_dom_element_blur(t->active);
 		t->mode = XT_MODE_COMMAND;
 	} else {
 		if (focus_input(t))
@@ -253,7 +286,7 @@ command_mode(struct tab *t, struct karg *args)
 void
 input_autofocus(struct tab *t)
 {
-	WebKitDOMElement	*active = NULL;
+	char			*text = NULL;
 
 	if (autofocus_onload &&
 	    t->tab_id == gtk_notebook_get_current_page(notebook)) {
@@ -262,10 +295,16 @@ 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, "")) {
+				g_free(text);
+				t->mode = XT_MODE_INSERT;
+			} else if (t->active) {
+				webkit_dom_element_blur(t->active);
+				t->mode = XT_MODE_COMMAND;
+			}
+		} else
+			t->mode = XT_MODE_COMMAND;
 	}
 }
 #else /* WEBKIT_CHECK_VERSION */
@@ -290,13 +329,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 b003bfe..6268399 100644
--- a/xombrero.c
+++ b/xombrero.c
@@ -4085,6 +4085,9 @@ notify_load_status_cb(WebKitWebView* wview, GParamSpec* pspec, struct tab *t)
 		g_free(text);
 		g_free(base);
 
+		/* DOM is changing, unreference the previous focused element */
+		t->active = NULL;
+
 		/* take focus if we are visible */
 		focus_webview(t);
 		t->focus_wv = 1;
@@ -7326,6 +7329,8 @@ create_new_tab(char *title, struct undo *u, int focus, int position)
 	t->user_agent_id = 0;
 	t->http_accept_id = 0;
 
+	t->active = NULL;
+
 #if GTK_CHECK_VERSION(2, 20, 0)
 	t->spinner = gtk_spinner_new();
 #endif
diff --git a/xombrero.h b/xombrero.h
index 4dbc2ad..13baebb 100644
--- a/xombrero.h
+++ b/xombrero.h
@@ -283,6 +283,9 @@ struct tab {
 	WebKitWebInspector	*inspector;
 	GtkWidget		*inspector_window;
 	GtkWidget		*inspector_view;
+
+	/* focused text entry */
+	WebKitDOMElement	*active;
 };
 TAILQ_HEAD(tab_list, tab);
 
@@ -555,7 +558,6 @@ int		toggle_pl(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 *);