about summary refs log tree commit diff stats
path: root/xombrero.c
diff options
context:
space:
mode:
authorJosh Rickmar <jrick@devio.us>2012-08-09 10:42:55 -0400
committerJosh Rickmar <jrick@devio.us>2012-08-09 10:42:55 -0400
commitd53713ed449dc0afe4bf778158f8438b09fdc703 (patch)
tree9eaa52ccb5e78114cff169664a98f2d6f24860f8 /xombrero.c
parentac7ed850179d9a6569d3c688fac465de717756d8 (diff)
downloadxombrero-d53713ed449dc0afe4bf778158f8438b09fdc703.tar.gz
Send a fake focus-in event to fix the focus.
We probably shouldn't be relying on internal gtk functions (especially
since we can't link to them on linux), so try this instead.
Diffstat (limited to 'xombrero.c')
-rw-r--r--xombrero.c92
1 files changed, 79 insertions, 13 deletions
diff --git a/xombrero.c b/xombrero.c
index 214b104..d02d471 100644
--- a/xombrero.c
+++ b/xombrero.c
@@ -208,6 +208,7 @@ GtkNotebook		*notebook;
 GtkWidget		*tab_bar;
 GtkWidget		*tab_bar_box;
 GtkWidget		*arrow, *abtn;
+GdkEvent		*fevent = NULL;
 struct tab_list		tabs;
 struct history_list	hl;
 int			hl_purge_count = 0;
@@ -5854,12 +5855,41 @@ done:
 	return (XT_CB_HANDLED);
 }
 
+/*
+ * XXX we were seeing a bunch of focus issues with the toplevel
+ * main_window losing its is-active and has-toplevel-focus properties.
+ * This is the most correct and portable solution we could come up with
+ * without relying on calling internal GTK functions (which we
+ * couldn't link to in Linux). 
+ */
+void
+fake_focus_in(GtkWidget *w)
+{
+	if (fevent == NULL) {
+		fevent = gdk_event_new(GDK_FOCUS_CHANGE);
+		fevent->focus_change.window =
+		    gtk_widget_get_window(main_window);
+		fevent->focus_change.type = GDK_FOCUS_CHANGE;
+		fevent->focus_change.in = TRUE;
+	}
+	gtk_widget_send_focus_change(main_window, fevent);
+}
+
 gboolean
 handle_keypress(struct tab *t, GdkEventKey *e, int entry)
 {
 	struct karg		args;
 	struct key_binding	*k;
 
+	/*
+	 * This sometimes gets randomly unset for whatever reason in GTK3.
+	 * If we're handling a keypress, the main window's is-active propery
+	 * *must* be true, or else many things will break. 
+	 */
+#if GTK_CHECK_VERSION(3, 0, 0)
+	fake_focus_in(main_window);
+#endif
+
 	/* handle keybindings if buffercmd is empty.
 	   if not empty, allow commands like C-n */
 	if (bcmd[0] == '\0' || ((e->state & (CTRL | MOD1)) != 0))
@@ -6464,6 +6494,21 @@ save_runtime_setting(const char *name, const char *val)
 }
 
 int
+entry_focus_cb(GtkWidget *w, GdkEvent e, struct tab *t)
+{
+	/*
+	 * This sometimes gets randomly unset for whatever reason in GTK3,
+	 * causing a GtkEntry's text cursor becomes invisible.  When we focus
+	 * a GtkEntry, be sure to manually reset the main window's is-active
+	 * property so the cursor is shown correctly. 
+	 */
+#if GTK_CHECK_VERSION(3, 0, 0)
+	fake_focus_in(main_window);
+#endif
+	return (XT_CB_PASSTHROUGH);
+}
+
+int
 entry_key_cb(GtkEntry *w, GdkEventKey *e, struct tab *t)
 {
 	if (t == NULL) {
@@ -6610,7 +6655,6 @@ cmd_keypress_cb(GtkEntry *w, GdkEventKey *e, struct tab *t)
 		/* FALLTHROUGH */
 	case GDK_Escape:
 		hide_cmd(t);
-		focus_webview(t);
 
 		/* cancel search */
 		if (c != NULL && (c[0] == '/' || c[0] == '?'))
@@ -6701,12 +6745,21 @@ cmd_focusout_cb(GtkWidget *w, GdkEventFocus *e, struct tab *t)
 	hide_oops(t);
 	disable_hints(t);
 
+	return (XT_CB_PASSTHROUGH);
+}
+
+void
+cmd_hide_cb(GtkWidget *w, struct tab *t)
+{
+	if (t == NULL) {
+		show_oops(NULL, "%s: invalid parameters", __func__);
+		return;
+	}
+
 	if (show_url == 0 || t->focus_wv)
 		focus_webview(t);
 	else
 		gtk_widget_grab_focus(GTK_WIDGET(t->uri_entry));
-
-	return (XT_CB_PASSTHROUGH);
 }
 
 void
@@ -7024,6 +7077,8 @@ create_kiosk_toolbar(struct tab *t)
 
 	/* create widgets but don't use them */
 	t->uri_entry = gtk_entry_new();
+	g_signal_connect(G_OBJECT(t->uri_entry), "focus-in-event",
+	    G_CALLBACK(entry_focus_cb), t);
 #if !GTK_CHECK_VERSION(3, 0, 0)
 	t->default_style = gtk_rc_get_style(t->uri_entry);
 #endif
@@ -7084,6 +7139,8 @@ create_toolbar(struct tab *t)
 	    G_CALLBACK(activate_uri_entry_cb), t);
 	g_signal_connect(G_OBJECT(t->uri_entry), "key-press-event",
 	    G_CALLBACK(entry_key_cb), t);
+	g_signal_connect(G_OBJECT(t->uri_entry), "focus-in-event",
+	    G_CALLBACK(entry_focus_cb), t);
 	completion_add(t);
 	gtk_box_pack_start(GTK_BOX(b), t->uri_entry, TRUE, TRUE, 0);
 
@@ -7094,6 +7151,8 @@ create_toolbar(struct tab *t)
 	    G_CALLBACK(activate_search_entry_cb), t);
 	g_signal_connect(G_OBJECT(t->search_entry), "key-press-event",
 	    G_CALLBACK(entry_key_cb), t);
+	g_signal_connect(G_OBJECT(t->search_entry), "focus-in-event",
+	    G_CALLBACK(entry_focus_cb), t);
 	gtk_box_pack_start(GTK_BOX(b), t->search_entry, FALSE, FALSE, 0);
 
 #if !GTK_CHECK_VERSION(3, 0, 0)
@@ -7324,6 +7383,8 @@ delete_tab(struct tab *t)
 		gtk_widget_destroy(t->js_toggle);
 	}
 
+	g_object_unref(t->completion);
+
 	gtk_widget_destroy(t->tab_elems.eventbox);
 	gtk_widget_destroy(t->vbox);
 
@@ -7659,6 +7720,8 @@ create_new_tab(char *title, struct undo *u, int focus, int position)
 
 	/* command entry */
 	t->cmd = gtk_entry_new();
+	g_signal_connect(G_OBJECT(t->cmd), "focus-in-event",
+	    G_CALLBACK(entry_focus_cb), t);
 	gtk_entry_set_inner_border(GTK_ENTRY(t->cmd), NULL);
 	gtk_entry_set_has_frame(GTK_ENTRY(t->cmd), FALSE);
 	gtk_box_pack_end(GTK_BOX(t->vbox), t->cmd, FALSE, FALSE, 0);
@@ -7765,6 +7828,7 @@ create_new_tab(char *title, struct undo *u, int focus, int position)
 	    "signal::focus-out-event", G_CALLBACK(cmd_focusout_cb), t,
 	    "signal::activate", G_CALLBACK(cmd_activate_cb), t,
 	    "signal::populate-popup", G_CALLBACK(cmd_popup_cb), t,
+	    "signal::hide", G_CALLBACK(cmd_hide_cb), t,
 	    (char *)NULL);
 
 	/* reuse wv_button_cb to hide oops */
@@ -7828,10 +7892,7 @@ create_new_tab(char *title, struct undo *u, int focus, int position)
 	} else
 		webkit_web_back_forward_list_clear(t->bfl);
 
-	/* hide stuff */
-	hide_cmd(t);
-	hide_oops(t);
-	hide_buffers(t);
+	/* check and show url and statusbar */
 	url_set_visibility();
 	statusbar_set_visibility();
 
@@ -7882,6 +7943,7 @@ notebook_switchpage_cb(GtkNotebook *nb, GtkWidget *nbp, guint pn,
 
 			hide_cmd(t);
 			hide_oops(t);
+			hide_buffers(t);
 
 			if (t->focus_wv) {
 				/* can't use focus_webview here */
@@ -7922,6 +7984,13 @@ menuitem_response(struct tab *t)
 	gtk_notebook_set_current_page(notebook, t->tab_id);
 }
 
+int
+destroy_menu(GtkWidget *w, GdkEventFocus *e, void *notused)
+{
+	gtk_widget_destroy(w);
+	return (XT_CB_PASSTHROUGH);
+}
+
 gboolean
 arrow_cb(GtkWidget *w, GdkEventButton *event, gpointer user_data)
 {
@@ -7956,12 +8025,9 @@ arrow_cb(GtkWidget *w, GdkEventButton *event, gpointer user_data)
 		gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
 		    bevent->button, bevent->time);
 
-		/* unref object so it'll free itself when popped down */
-#if !GTK_CHECK_VERSION(3, 0, 0)
-		/* XXX does not need unref with gtk+3? */
-		g_object_ref_sink(menu);
-		g_object_unref(menu);
-#endif
+		g_object_connect(G_OBJECT(menu),
+		    "signal::hide", G_CALLBACK(destroy_menu), NULL,
+		    (char *)NULL);
 
 		return (TRUE /* eat event */);
 	}