summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libview/ev-view-marshal.list1
-rw-r--r--libview/ev-view-private.h40
-rw-r--r--libview/ev-view.c120
3 files changed, 114 insertions, 47 deletions
diff --git a/libview/ev-view-marshal.list b/libview/ev-view-marshal.list
index fad49248..0ead4025 100644
--- a/libview/ev-view-marshal.list
+++ b/libview/ev-view-marshal.list
@@ -1,2 +1,3 @@
VOID:ENUM,ENUM
VOID:INT,INT
+BOOLEAN:ENUM,INT
diff --git a/libview/ev-view-private.h b/libview/ev-view-private.h
index 14221175..696a043f 100644
--- a/libview/ev-view-private.h
+++ b/libview/ev-view-private.h
@@ -178,6 +178,9 @@ struct _EvView {
/* Common for button press handling */
int pressed_button;
+ /* Key bindings propagation */
+ gboolean key_binding_handled;
+
/* Information for middle clicking and dragging around. */
DragInfo drag_info;
@@ -236,23 +239,26 @@ struct _EvView {
struct _EvViewClass {
GtkContainerClass parent_class;
- void (*scroll) (EvView *view,
- GtkScrollType scroll,
- GtkOrientation orientation);
- void (*handle_link) (EvView *view,
- EvLink *link);
- void (*external_link) (EvView *view,
- EvLinkAction *action);
- void (*popup_menu) (EvView *view,
- GList *items);
- void (*selection_changed) (EvView *view);
- void (*sync_source) (EvView *view,
- EvSourceLink *link);
- void (*annot_added) (EvView *view,
- EvAnnotation *annot);
- void (*annot_removed) (EvView *view,
- EvAnnotation *annot);
- void (*layers_changed) (EvView *view);
+ void (*scroll) (EvView *view,
+ GtkScrollType scroll,
+ GtkOrientation orientation);
+ void (*handle_link) (EvView *view,
+ EvLink *link);
+ void (*external_link) (EvView *view,
+ EvLinkAction *action);
+ void (*popup_menu) (EvView *view,
+ GList *items);
+ void (*selection_changed) (EvView *view);
+ void (*sync_source) (EvView *view,
+ EvSourceLink *link);
+ void (*annot_added) (EvView *view,
+ EvAnnotation *annot);
+ void (*annot_removed) (EvView *view,
+ EvAnnotation *annot);
+ void (*layers_changed) (EvView *view);
+ gboolean (*move_cursor) (EvView *view,
+ GtkMovementStep step,
+ gint count);
};
void _get_page_size_for_scale_and_rotation (EvDocument *document,
diff --git a/libview/ev-view.c b/libview/ev-view.c
index 84ee1487..4f32136a 100644
--- a/libview/ev-view.c
+++ b/libview/ev-view.c
@@ -59,6 +59,7 @@ enum {
SIGNAL_ANNOT_ADDED,
SIGNAL_ANNOT_REMOVED,
SIGNAL_LAYERS_CHANGED,
+ SIGNAL_MOVE_CURSOR,
N_SIGNALS
};
@@ -945,6 +946,9 @@ ev_view_scroll (EvView *view,
gboolean first_page = FALSE;
gboolean last_page = FALSE;
+ if (view->key_binding_handled)
+ return;
+
view->jump_to_find_result = FALSE;
if ((!horizontal && ev_view_page_fits (view, GTK_ORIENTATION_VERTICAL)) ||
@@ -5187,48 +5191,61 @@ cursor_forward_line (EvView *view)
}
static gboolean
-caret_key_press_event (EvView *view,
- GdkEventKey *event)
+ev_view_move_cursor (EvView *view,
+ GtkMovementStep step,
+ gint count)
{
gint prev_offset;
gint prev_page;
- /* Disable caret navigation on rotated pages */
- if (view->rotation != 0)
+ if (!view->caret_enabled || view->rotation != 0)
return FALSE;
+ view->key_binding_handled = TRUE;
view->cursor_blink_time = 0;
prev_offset = view->cursor_offset;
prev_page = view->cursor_page;
- switch (event->keyval) {
- case GDK_KEY_Left:
- if (event->state & GDK_CONTROL_MASK)
- cursor_backward_word_start (view);
- else
+ switch (step) {
+ case GTK_MOVEMENT_VISUAL_POSITIONS:
+ while (count > 0) {
+ cursor_forward_char (view);
+ count--;
+ }
+ while (count < 0) {
cursor_backward_char (view);
+ count++;
+ }
break;
- case GDK_KEY_Right:
- if (event->state & GDK_CONTROL_MASK)
+ case GTK_MOVEMENT_WORDS:
+ while (count > 0) {
cursor_forward_word_end (view);
- else
- cursor_forward_char (view);
- break;
- case GDK_KEY_Up:
- cursor_backward_line (view);
- break;
- case GDK_KEY_Down:
- cursor_forward_line (view);
+ count--;
+ }
+ while (count < 0) {
+ cursor_backward_word_start (view);
+ count++;
+ }
break;
- case GDK_KEY_Home:
- cursor_go_to_line_start (view);
+ case GTK_MOVEMENT_DISPLAY_LINES:
+ while (count > 0) {
+ cursor_forward_line (view);
+ count--;
+ }
+ while (count < 0) {
+ cursor_backward_line (view);
+ count++;
+ }
break;
- case GDK_KEY_End:
- cursor_go_to_line_end (view);
+ case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
+ if (count > 0)
+ cursor_go_to_line_end (view);
+ else if (count < 0)
+ cursor_go_to_line_start (view);
break;
default:
- return FALSE;
+ g_assert_not_reached ();
}
ev_view_pend_cursor_blink (view);
@@ -5237,7 +5254,7 @@ caret_key_press_event (EvView *view,
if (prev_offset != view->cursor_offset || prev_page != view->cursor_page) {
GdkRectangle view_rect;
- /* scroll to view the text caret */
+ /* scroll to view the caret cursor */
if (!get_caret_cursor_rect_from_offset (view, view->cursor_offset, view->cursor_page, &view_rect))
return TRUE;
@@ -5253,18 +5270,23 @@ static gboolean
ev_view_key_press_event (GtkWidget *widget,
GdkEventKey *event)
{
- EvView *view = EV_VIEW (widget);
+ EvView *view = EV_VIEW (widget);
+ gboolean retval;
if (!view->document)
return FALSE;
- if (view->caret_enabled && caret_key_press_event (view, event))
- return TRUE;
-
if (!gtk_widget_has_focus (widget))
return ev_view_forward_key_event_to_focused_child (view, event);
- return gtk_bindings_activate_event (G_OBJECT (widget), event);
+ /* I expected GTK+ do this for me, but it doesn't cancel
+ * the propagation of bindings handled for the same binding set
+ */
+ view->key_binding_handled = FALSE;
+ retval = gtk_bindings_activate_event (G_OBJECT (widget), event);
+ view->key_binding_handled = FALSE;
+
+ return retval;
}
static gint
@@ -5943,6 +5965,25 @@ ev_view_parent_set (GtkWidget *widget,
}
static void
+add_move_binding_keypad (GtkBindingSet *binding_set,
+ guint keyval,
+ GdkModifierType modifiers,
+ GtkMovementStep step,
+ gint count)
+{
+ guint keypad_keyval = keyval - GDK_KEY_Left + GDK_KEY_KP_Left;
+
+ gtk_binding_entry_add_signal (binding_set, keyval, modifiers,
+ "move-cursor", 2,
+ GTK_TYPE_MOVEMENT_STEP, step,
+ G_TYPE_INT, count);
+ gtk_binding_entry_add_signal (binding_set, keypad_keyval, modifiers,
+ "move-cursor", 2,
+ GTK_TYPE_MOVEMENT_STEP, step,
+ G_TYPE_INT, count);
+}
+
+static void
ev_view_class_init (EvViewClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
@@ -5987,6 +6028,7 @@ ev_view_class_init (EvViewClass *class)
container_class->forall = ev_view_forall;
class->scroll = ev_view_scroll_internal;
+ class->move_cursor = ev_view_move_cursor;
/* Scrollable interface */
g_object_class_override_property (object_class, PROP_HADJUSTMENT, "hadjustment");
@@ -6067,9 +6109,27 @@ ev_view_class_init (EvViewClass *class)
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0,
G_TYPE_NONE);
+ signals[SIGNAL_MOVE_CURSOR] = g_signal_new ("move-cursor",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (EvViewClass, move_cursor),
+ NULL, NULL,
+ ev_view_marshal_BOOLEAN__ENUM_INT,
+ G_TYPE_BOOLEAN, 2,
+ GTK_TYPE_MOVEMENT_STEP,
+ G_TYPE_INT);
binding_set = gtk_binding_set_by_class (class);
+ add_move_binding_keypad (binding_set, GDK_KEY_Left, 0, GTK_MOVEMENT_VISUAL_POSITIONS, -1);
+ add_move_binding_keypad (binding_set, GDK_KEY_Right, 0, GTK_MOVEMENT_VISUAL_POSITIONS, 1);
+ add_move_binding_keypad (binding_set, GDK_KEY_Left, GDK_CONTROL_MASK, GTK_MOVEMENT_WORDS, -1);
+ add_move_binding_keypad (binding_set, GDK_KEY_Right, GDK_CONTROL_MASK, GTK_MOVEMENT_WORDS, 1);
+ add_move_binding_keypad (binding_set, GDK_KEY_Up, 0, GTK_MOVEMENT_DISPLAY_LINES, -1);
+ add_move_binding_keypad (binding_set, GDK_KEY_Down, 0, GTK_MOVEMENT_DISPLAY_LINES, 1);
+ add_move_binding_keypad (binding_set, GDK_KEY_Home, 0, GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
+ add_move_binding_keypad (binding_set, GDK_KEY_End, 0, GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
+
add_scroll_binding_keypad (binding_set, GDK_KEY_Left, 0, GTK_SCROLL_STEP_BACKWARD, GTK_ORIENTATION_HORIZONTAL);
add_scroll_binding_keypad (binding_set, GDK_KEY_Right, 0, GTK_SCROLL_STEP_FORWARD, GTK_ORIENTATION_HORIZONTAL);
add_scroll_binding_keypad (binding_set, GDK_KEY_Left, GDK_MOD1_MASK, GTK_SCROLL_STEP_DOWN, GTK_ORIENTATION_HORIZONTAL);