diff --git a/src/pyj/read_book/flow_mode.pyj b/src/pyj/read_book/flow_mode.pyj index 1354c44b5e..ab955abbba 100644 --- a/src/pyj/read_book/flow_mode.pyj +++ b/src/pyj/read_book/flow_mode.pyj @@ -23,6 +23,7 @@ from __python__ import bound_methods, hash_literals from dom import set_css from range_utils import wrap_range, unwrap from read_book.cfi import scroll_to as cfi_scroll_to +from read_book.touch import GESTURE from read_book.globals import current_spine_item, get_boss, rtl_page_progression, ltr_page_progression from read_book.settings import opts from read_book.viewport import line_height, rem_size, scroll_viewport @@ -536,7 +537,9 @@ def start_drag_scroll(delta): def handle_gesture(gesture): flick_animator.stop() - if gesture.type is 'swipe': + if gesture.type is GESTURE.flick_block_forward or gesture.type is GESTURE.flick_block_backward: + flick_animator.start(gesture) + elif gesture.type.startsWith('swipe_') and gesture.type.endsWith('_in_progress'): if gesture.points.length > 1 and not gesture.is_held: delta = gesture.points[-2] - gesture.points[-1] if Math.abs(delta) >= 1: @@ -556,13 +559,11 @@ def handle_gesture(gesture): # In horizontal modes, just move by the delta. else: scroll_viewport.scroll_by(delta, 0) - if not gesture.active and not gesture.is_held: - flick_animator.start(gesture) - elif gesture.type is 'prev-page': + elif gesture.type is GESTURE.back_zone_tap: # should flip = False - previous is previous whether RTL or LTR. # flipping of this command is handled higher up scroll_by_page(-1, False) - elif gesture.type is 'next-page': + elif gesture.type is GESTURE.forward_zone_tap: # should flip = False - next is next whether RTL or LTR. # flipping of this command is handled higher up scroll_by_page(1, False) diff --git a/src/pyj/read_book/iframe.pyj b/src/pyj/read_book/iframe.pyj index 9eaf9f5ff4..f19ba47dfb 100644 --- a/src/pyj/read_book/iframe.pyj +++ b/src/pyj/read_book/iframe.pyj @@ -9,6 +9,7 @@ from range_utils import ( all_annots_in_selection, highlight_associated_with_selection, last_span_for_crw, reset_highlight_counter, select_crw, unwrap_all_crw, unwrap_crw, wrap_text_in_range ) +from read_book.touch import GESTURE from read_book.cfi import cfi_for_selection, range_from_cfi from read_book.extract import get_elements from read_book.find import ( @@ -315,13 +316,13 @@ class IframeBoss: self.auto_scroll_action('toggle') def handle_gesture(self, gesture): - if gesture.type is 'show-chrome': + if gesture.type is GESTURE.control_zone_tap or gesture.type is GESTURE.two_finger_tap: self.send_message('show_chrome') - elif gesture.type is 'two-finger-tap': - self.send_message('show_chrome') - elif gesture.type is 'pinch': - self.send_message('bump_font_size', increase=gesture.direction is 'out') - elif gesture.type is 'long-tap': + elif gesture.type is GESTURE.pinch_in: + self.send_message('bump_font_size', increase=False) + elif gesture.type is GESTURE.pinch_out: + self.send_message('bump_font_size', increase=True) + elif gesture.type is GESTURE.long_tap: self.handle_long_tap(gesture) else: self._handle_gesture(gesture) diff --git a/src/pyj/read_book/paged_mode.pyj b/src/pyj/read_book/paged_mode.pyj index 23ecb1ee65..42c816ded1 100644 --- a/src/pyj/read_book/paged_mode.pyj +++ b/src/pyj/read_book/paged_mode.pyj @@ -32,6 +32,7 @@ from read_book.cfi import ( scroll_to as cfi_scroll_to ) from read_book.globals import current_spine_item, get_boss, rtl_page_progression +from read_book.touch import GESTURE from read_book.settings import opts from read_book.viewport import scroll_viewport, line_height, rem_size, get_unit_size_in_pixels from utils import ( @@ -808,19 +809,20 @@ def handle_shortcut(sc_name, evt): def handle_gesture(gesture): - if gesture.type is 'swipe': - if gesture.axis is 'vertical': - if not gesture.active: - get_boss().send_message('next_section', forward=gesture.direction is 'up') - else: - if not gesture.active or gesture.is_held: - scroll_by_page(gesture.direction is 'right', True, flip_if_rtl_page_progression=True) # Gesture progression direction is determined in the gesture code, # don't set flip_if_rtl_page_progression=True here. - elif gesture.type is 'prev-page': - scroll_by_page(True, opts.paged_taps_scroll_by_screen, flip_if_rtl_page_progression=False) - elif gesture.type is 'next-page': - scroll_by_page(False, opts.paged_taps_scroll_by_screen, flip_if_rtl_page_progression=False) + if gesture.type is GESTURE.flick_block_forward: + get_boss().send_message('next_section', forward=True) + elif gesture.type is GESTURE.flick_block_backward: + get_boss().send_message('next_section', forward=False) + elif gesture.type is GESTURE.flick_inline_forward or gesture.type is GESTURE.swipe_inline_forward_hold: + scroll_by_page(False, True) + elif gesture.type is GESTURE.flick_inline_backward or gesture.type is GESTURE.swipe_inline_backward_hold: + scroll_by_page(True, True) + elif gesture.type is GESTURE.back_zone_tap: + scroll_by_page(True, opts.paged_taps_scroll_by_screen) + elif gesture.type is GESTURE.forward_zone_tap: + scroll_by_page(False, opts.paged_taps_scroll_by_screen) anchor_funcs = { diff --git a/src/pyj/read_book/touch.pyj b/src/pyj/read_book/touch.pyj index be642b166e..14952656dd 100644 --- a/src/pyj/read_book/touch.pyj +++ b/src/pyj/read_book/touch.pyj @@ -2,6 +2,7 @@ # License: GPL v3 Copyright: 2016, Kovid Goyal from __python__ import bound_methods, hash_literals +from gettext import gettext as _ from read_book.globals import get_boss, ltr_page_progression, ui_operations from read_book.settings import opts from read_book.viewport import get_unit_size_in_pixels, scroll_viewport @@ -11,6 +12,31 @@ TAP_THRESHOLD = 8 # pixels SWIPE_THRESHOLD = 64 # pixels TAP_LINK_THRESHOLD = 5 # pixels PINCH_THRESHOLD = 20 # pixels +GESTURE_NAMES = { + 'back_zone_tap': _('Tap on back zone'), + 'forward_zone_tap': _('Tap on forward zone'), + 'control_zone_tap': _('Tap in the controls zone'), + 'long_tap': _('Long tap'), + 'two_finger_tap': _('Two finger tap'), + 'pinch_in': _('Pinch in'), + 'pinch_out': _('Pinch out'), + 'flick_inline_backward': _('Flick in writing direction, backwards'), + 'flick_inline_forward': _('Flick in writing direction, forwards'), + 'flick_block_backward': _('Flick perpendicular to writing direction, backwards'), + 'flick_block_forward': _('Flick perpendicular to writing direction, forwards'), + 'swipe_inline_backward_in_progress': _('Swipe in writing direction, backwards, in-progress'), + 'swipe_inline_forward_in_progress': _('Swipe in writing direction, forwards, in-progress'), + 'swipe_block_backward_in_progress': _('Swipe perpendicular to writing direction, backwards, in-progress'), + 'swipe_block_forward_in_progress': _('Swipe perpendicular to writing direction, forwards, in-progress'), + 'swipe_inline_backward_hold': _('Swipe in writing direction, backwards and hold'), + 'swipe_inline_forward_hold': _('Swipe in writing direction, forwards and hold'), + 'swipe_block_backward_hold': _('Swipe perpendicular to writing direction, backwards and hold'), + 'swipe_block_forward_hold': _('Swipe perpendicular to writing direction, forwards and hold'), +} +GESTURE = {k:k for k in Object.keys(GESTURE_NAMES)} +GESTURE.tap = 'tap' +GESTURE.swipe = 'swipe' +GESTURE.pinch = 'pinch' gesture_id = 0 @@ -50,7 +76,7 @@ def interpret_single_gesture(touch, gesture_id): max_y_displacement = max_displacement(touch.viewport_y) ans = {'active':touch.active, 'is_held':touch.is_held, 'id':gesture_id, 'start_time': touch.ctime} if max(max_x_displacement, max_y_displacement) < TAP_THRESHOLD: - ans.type = 'tap' + ans.type = GESTURE.tap ans.viewport_x = touch.viewport_x[0] ans.viewport_y = touch.viewport_y[0] return ans @@ -60,7 +86,7 @@ def interpret_single_gesture(touch, gesture_id): delta_y = abs(touch.viewport_y[-1] - touch.viewport_y[0]) max_disp = max(delta_y, delta_x) if max_disp > SWIPE_THRESHOLD and min(delta_x, delta_y)/max_disp < 0.35: - ans.type = 'swipe' + ans.type = GESTURE.swipe ans.axis = 'vertical' if delta_y > delta_x else 'horizontal' ans.points = pts = touch.viewport_y if ans.axis is 'vertical' else touch.viewport_x ans.times = touch.mtimes @@ -82,7 +108,7 @@ def interpret_double_gesture(touch1, touch2, gesture_id): max_y_displacement1 = max_displacement(touch1.viewport_y) max_y_displacement2 = max_displacement(touch2.viewport_y) if max(max_x_displacement1, max_y_displacement1) < TAP_THRESHOLD and max(max_x_displacement2, max_y_displacement2) < TAP_THRESHOLD: - ans.type = 'two-finger-tap' + ans.type = GESTURE.two_finger_tap ans.viewport_x1 = touch1.viewport_x[0] ans.viewport_y1 = touch1.viewport_y[0] ans.viewport_x2 = touch2.viewport_x[0] @@ -92,7 +118,7 @@ def interpret_double_gesture(touch1, touch2, gesture_id): final_distance = Math.sqrt((touch1.viewport_x[-1] - touch2.viewport_x[-1])**2 + (touch1.viewport_y[-1] - touch2.viewport_y[-1])**2) distance = abs(final_distance - initial_distance) if distance > PINCH_THRESHOLD: - ans.type = 'pinch' + ans.type = GESTURE.pinch ans.direction = 'in' if final_distance < initial_distance else 'out' ans.distance = distance return ans @@ -255,42 +281,51 @@ class BookTouchHandler(TouchHandler): TouchHandler.__init__(self) def handle_gesture(self, gesture): - gesture.from_side_margin = self.for_side_margin - if gesture.type is 'tap': + if gesture.type is GESTURE.tap: if gesture.is_held: if not self.for_side_margin and not self.handled_tap_hold and window.performance.now() - gesture.start_time >= HOLD_THRESHOLD: self.handled_tap_hold = True - gesture.type = 'long-tap' + gesture.type = GESTURE.long_tap get_boss().handle_gesture(gesture) return if not gesture.active: if self.for_side_margin or not tap_on_link(gesture): inch = inch_in_pixels() if gesture.viewport_y < min(100, scroll_viewport.height() / 4): - gesture.type = 'show-chrome' + gesture.type = GESTURE.control_zone_tap else: limit = inch # default, books that go left to right. if ltr_page_progression() and not opts.reverse_page_turn_zones: if gesture.viewport_x < min(limit, scroll_viewport.width() / 4): - gesture.type = 'prev-page' + gesture.type = GESTURE.back_zone_tap else: - gesture.type = 'next-page' + gesture.type = GESTURE.forward_zone_tap # We swap the sizes in RTL mode, so that going to the next page is always the bigger touch region. else: # The "going back" area should not be more than limit units big, # even if 1/4 of the scroll viewport is more than limit units. # Checking against the larger of the width minus the limit units and 3/4 of the width will accomplish that. if gesture.viewport_x > max(scroll_viewport.width() - limit, scroll_viewport.width() * (3/4)): - gesture.type = 'prev-page' + gesture.type = GESTURE.back_zone_tap else: - gesture.type = 'next-page' - if gesture.type is 'pinch': + gesture.type = GESTURE.forward_zone_tap + elif gesture.type is GESTURE.pinch: if gesture.active: return - if gesture.type is 'two-finger-tap': + gesture.type = GESTURE.pinch_in if gesture.direction is 'in' else GESTURE.pinch_out + elif gesture.type is GESTURE.two_finger_tap: if gesture.active: return + elif gesture.type is 'swipe': + backward_dir = 'down' if gesture.axis is 'vertical' else ('right' if ltr_page_progression() else 'left') + direction = 'backward' if gesture.direction is backward_dir else 'forward' + inline_dir = 'vertical' if scroll_viewport.vertical_writing_mode else 'horizontal' + axis = 'inline' if gesture.axis is inline_dir else 'block' + if gesture.active: + gesture.type = GESTURE[f'swipe_{axis}_{direction}' + ('_hold' if gesture.is_held else '_in_progress')] + elif not gesture.is_held: + gesture.type = GESTURE[f'flick_{axis}_{direction}'] if self.for_side_margin: ui_operations.forward_gesture(gesture) else: