[evince] libview: Cycle through form fields with tab button
- From: Carlos Garcia Campos <carlosgc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evince] libview: Cycle through form fields with tab button
- Date: Tue, 24 Jun 2014 17:35:03 +0000 (UTC)
commit e3e3f7740a5b5d8ce0d78b6de098a10acfcee853
Author: Andrey Pustovalov <AndreiPustovalov ya ru>
Date: Thu Mar 13 03:59:24 2014 -0700
libview: Cycle through form fields with tab button
https://bugzilla.gnome.org/show_bug.cgi?id=503706
libview/ev-view-private.h | 1 +
libview/ev-view.c | 158 ++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 158 insertions(+), 1 deletions(-)
---
diff --git a/libview/ev-view-private.h b/libview/ev-view-private.h
index 0ff7412..7727bbb 100644
--- a/libview/ev-view-private.h
+++ b/libview/ev-view-private.h
@@ -206,6 +206,7 @@ struct _EvView {
/* Focus */
EvMapping *focused_element;
guint focused_element_page;
+ guint child_focus_idle_id;
/* Synctex */
EvMapping *synctex_result;
diff --git a/libview/ev-view.c b/libview/ev-view.c
index d33c4a1..51ecd3a 100644
--- a/libview/ev-view.c
+++ b/libview/ev-view.c
@@ -2648,8 +2648,11 @@ _ev_view_focus_form_field (EvView *view,
}
/* Form field doesn't require a widget */
- if (!field_widget)
+ if (!field_widget) {
+ if (!gtk_widget_has_focus (GTK_WIDGET (view)))
+ gtk_widget_grab_focus (GTK_WIDGET (view));
return;
+ }
g_object_set_data_full (G_OBJECT (field_widget), "form-field",
g_object_ref (field),
@@ -2658,6 +2661,7 @@ _ev_view_focus_form_field (EvView *view,
form_field_mapping = ev_page_cache_get_form_field_mapping (view->page_cache,
field->page->index);
mapping = ev_mapping_list_find (form_field_mapping, field);
+ _ev_view_set_focused_element (view, mapping, field->page->index);
ev_view_put_to_doc_rect (view, field_widget, field->page->index, &mapping->area);
gtk_widget_show (field_widget);
gtk_widget_grab_focus (field_widget);
@@ -6256,6 +6260,11 @@ ev_view_dispose (GObject *object)
view->cursor_blink_timeout_id = 0;
}
+ if (view->child_focus_idle_id) {
+ g_source_remove (view->child_focus_idle_id);
+ view->child_focus_idle_id = 0;
+ }
+
gtk_scrollable_set_hadjustment (GTK_SCROLLABLE (view), NULL);
gtk_scrollable_set_vadjustment (GTK_SCROLLABLE (view), NULL);
@@ -6466,6 +6475,152 @@ add_move_binding_keypad (GtkBindingSet *binding_set,
G_TYPE_BOOLEAN, TRUE);
}
+static gint
+ev_view_mapping_compare (const EvMapping *a,
+ const EvMapping *b,
+ gpointer user_data)
+{
+ GtkTextDirection text_direction = GPOINTER_TO_INT (user_data);
+ gint y1 = a->area.y1 + (a->area.y2 - a->area.y1) / 2;
+ gint y2 = b->area.y1 + (b->area.y2 - b->area.y1) / 2;
+
+ if (y1 == y2) {
+ gint x1 = a->area.x1 + (a->area.x2 - a->area.x1) / 2;
+ gint x2 = b->area.x1 + (b->area.x2 - b->area.x1) / 2;
+
+ if (text_direction == GTK_TEXT_DIR_RTL)
+ return (x1 < x2) ? 1 : ((x1 == x2) ? 0 : -1);
+
+ return (x1 < x2) ? -1 : ((x1 == x2) ? 0 : 1);
+ }
+
+ return (y1 < y2) ? -1 : 1;
+}
+
+static GList *
+ev_view_get_sorted_mapping_list (EvView *view,
+ GtkDirectionType direction,
+ gint page)
+{
+ GList *mapping_list = NULL, *l;
+ EvMappingList *forms_mapping;
+
+ forms_mapping = ev_page_cache_get_form_field_mapping (view->page_cache, page);
+
+ for (l = ev_mapping_list_get_list (forms_mapping); l; l = g_list_next (l)) {
+ EvMapping *mapping = (EvMapping *)l->data;
+ EvFormField *field = (EvFormField *)mapping->data;
+
+ if (field->is_read_only || EV_IS_FORM_FIELD_SIGNATURE (field))
+ continue;
+
+ mapping_list = g_list_prepend (mapping_list, mapping);
+ }
+
+ if (!mapping_list)
+ return NULL;
+
+ mapping_list = g_list_sort_with_data (g_list_reverse (mapping_list),
+ (GCompareDataFunc)ev_view_mapping_compare,
+ GINT_TO_POINTER (gtk_widget_get_direction (GTK_WIDGET (view))));
+
+ if (direction == GTK_DIR_TAB_BACKWARD)
+ mapping_list = g_list_reverse (mapping_list);
+ return mapping_list;
+}
+
+static gboolean
+child_focus_forward_idle_cb (gpointer user_data)
+{
+ EvView *view = EV_VIEW (user_data);
+
+ view->child_focus_idle_id = 0;
+ gtk_widget_child_focus (GTK_WIDGET (view), GTK_DIR_TAB_FORWARD);
+
+ return G_SOURCE_REMOVE;
+}
+
+static gboolean
+child_focus_backward_idle_cb (gpointer user_data)
+{
+ EvView *view = EV_VIEW (user_data);
+
+ view->child_focus_idle_id = 0;
+ gtk_widget_child_focus (GTK_WIDGET (view), GTK_DIR_TAB_BACKWARD);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+schedule_child_focus_in_idle (EvView *view,
+ GtkDirectionType direction)
+{
+ if (view->child_focus_idle_id)
+ g_source_remove (view->child_focus_idle_id);
+ view->child_focus_idle_id =
+ g_idle_add (direction == GTK_DIR_TAB_FORWARD ? child_focus_forward_idle_cb :
child_focus_backward_idle_cb,
+ view);
+}
+
+static gboolean
+ev_view_focus_next (EvView *view,
+ GtkDirectionType direction)
+{
+ EvMapping *focus_element;
+ GList *elements;
+
+ if (view->focused_element) {
+ GList *l;
+
+ elements = ev_view_get_sorted_mapping_list (view, direction, view->focused_element_page);
+ l = g_list_find (elements, view->focused_element);
+ l = g_list_next (l);
+ focus_element = l ? l->data : NULL;
+ } else {
+ elements = ev_view_get_sorted_mapping_list (view, direction, view->current_page);
+ focus_element = elements ? elements->data : NULL;
+ }
+
+ g_list_free (elements);
+
+ if (focus_element) {
+ ev_view_remove_all (view);
+ _ev_view_focus_form_field (view, EV_FORM_FIELD (focus_element->data));
+
+ return TRUE;
+ }
+
+ ev_view_remove_all (view);
+ _ev_view_set_focused_element (view, NULL, -1);
+
+ /* FIXME: this doesn't work if the next/previous page doesn't have form fields */
+ if (direction == GTK_DIR_TAB_FORWARD) {
+ if (ev_view_next_page (view)) {
+ schedule_child_focus_in_idle (view, direction);
+ return TRUE;
+ }
+ } else if (direction == GTK_DIR_TAB_BACKWARD) {
+ if (ev_view_previous_page (view)) {
+ schedule_child_focus_in_idle (view, direction);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static gboolean
+ev_view_focus (GtkWidget *widget,
+ GtkDirectionType direction)
+{
+ EvView *view = EV_VIEW (widget);
+
+ if (direction == GTK_DIR_TAB_FORWARD || direction == GTK_DIR_TAB_BACKWARD)
+ return ev_view_focus_next (view, direction);
+
+ return GTK_WIDGET_CLASS (ev_view_parent_class)->focus (widget, direction);
+}
+
static void
ev_view_class_init (EvViewClass *class)
{
@@ -6500,6 +6655,7 @@ ev_view_class_init (EvViewClass *class)
widget_class->popup_menu = ev_view_popup_menu;
widget_class->query_tooltip = ev_view_query_tooltip;
widget_class->screen_changed = ev_view_screen_changed;
+ widget_class->focus = ev_view_focus;
container_class->remove = ev_view_remove;
container_class->forall = ev_view_forall;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]