mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Clean up gesture handling
All the gnarly direction detection for swipes is moved into touch.pyj and the handlers just need to check the event type (except for flow mode where we really want to match finger movement).
This commit is contained in:
parent
fdb68a1613
commit
dcfc477c28
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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 = {
|
||||
|
@ -2,6 +2,7 @@
|
||||
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user