mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 10:44:09 -04:00
Map gestures to configurable actions
This commit is contained in:
parent
dcfc477c28
commit
80702e5a72
@ -23,7 +23,6 @@ from __python__ import bound_methods, hash_literals
|
|||||||
from dom import set_css
|
from dom import set_css
|
||||||
from range_utils import wrap_range, unwrap
|
from range_utils import wrap_range, unwrap
|
||||||
from read_book.cfi import scroll_to as cfi_scroll_to
|
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.globals import current_spine_item, get_boss, rtl_page_progression, ltr_page_progression
|
||||||
from read_book.settings import opts
|
from read_book.settings import opts
|
||||||
from read_book.viewport import line_height, rem_size, scroll_viewport
|
from read_book.viewport import line_height, rem_size, scroll_viewport
|
||||||
@ -537,9 +536,9 @@ def start_drag_scroll(delta):
|
|||||||
|
|
||||||
def handle_gesture(gesture):
|
def handle_gesture(gesture):
|
||||||
flick_animator.stop()
|
flick_animator.stop()
|
||||||
if gesture.type is GESTURE.flick_block_forward or gesture.type is GESTURE.flick_block_backward:
|
if gesture.resolved_action is 'animated_scroll':
|
||||||
flick_animator.start(gesture)
|
flick_animator.start(gesture)
|
||||||
elif gesture.type.startsWith('swipe_') and gesture.type.endsWith('_in_progress'):
|
elif gesture.resolved_action is 'pan':
|
||||||
if gesture.points.length > 1 and not gesture.is_held:
|
if gesture.points.length > 1 and not gesture.is_held:
|
||||||
delta = gesture.points[-2] - gesture.points[-1]
|
delta = gesture.points[-2] - gesture.points[-1]
|
||||||
if Math.abs(delta) >= 1:
|
if Math.abs(delta) >= 1:
|
||||||
@ -559,11 +558,11 @@ def handle_gesture(gesture):
|
|||||||
# In horizontal modes, just move by the delta.
|
# In horizontal modes, just move by the delta.
|
||||||
else:
|
else:
|
||||||
scroll_viewport.scroll_by(delta, 0)
|
scroll_viewport.scroll_by(delta, 0)
|
||||||
elif gesture.type is GESTURE.back_zone_tap:
|
elif gesture.resolved_action is 'prev_page' or gesture.resolved_action is 'prev_screen':
|
||||||
# should flip = False - previous is previous whether RTL or LTR.
|
# should flip = False - previous is previous whether RTL or LTR.
|
||||||
# flipping of this command is handled higher up
|
# flipping of this command is handled higher up
|
||||||
scroll_by_page(-1, False)
|
scroll_by_page(-1, False)
|
||||||
elif gesture.type is GESTURE.forward_zone_tap:
|
elif gesture.resolved_action is 'next_page' or gesture.resolved_action is 'next_screen':
|
||||||
# should flip = False - next is next whether RTL or LTR.
|
# should flip = False - next is next whether RTL or LTR.
|
||||||
# flipping of this command is handled higher up
|
# flipping of this command is handled higher up
|
||||||
scroll_by_page(1, False)
|
scroll_by_page(1, False)
|
||||||
|
49
src/pyj/read_book/gestures.pyj
Normal file
49
src/pyj/read_book/gestures.pyj
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# vim:fileencoding=utf-8
|
||||||
|
# License: GPL v3 Copyright: 2023, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
from __python__ import bound_methods, hash_literals
|
||||||
|
|
||||||
|
from read_book.touch import GESTURE
|
||||||
|
from read_book.settings import opts
|
||||||
|
|
||||||
|
default_actions_for_gesture = {
|
||||||
|
'common': {
|
||||||
|
GESTURE.back_zone_tap: 'prev_page',
|
||||||
|
GESTURE.forward_zone_tap: 'next_page',
|
||||||
|
GESTURE.control_zone_tap: 'show_chrome',
|
||||||
|
GESTURE.two_finger_tap: 'show_chrome',
|
||||||
|
GESTURE.long_tap: 'highlight_or_inspect',
|
||||||
|
GESTURE.pinch_in: 'decrease_font_size',
|
||||||
|
GESTURE.pinch_out: 'increase_font_size',
|
||||||
|
},
|
||||||
|
'flow_mode': {
|
||||||
|
GESTURE.swipe_inline_backward_in_progress: 'pan',
|
||||||
|
GESTURE.swipe_inline_forward_in_progress: 'pan',
|
||||||
|
GESTURE.swipe_block_backward_in_progress: 'pan',
|
||||||
|
GESTURE.swipe_block_forward_in_progress: 'pan',
|
||||||
|
GESTURE.flick_block_forward: 'animated_scroll',
|
||||||
|
GESTURE.flick_block_backward: 'animated_scroll',
|
||||||
|
GESTURE.flick_inline_forward: 'animated_scroll',
|
||||||
|
GESTURE.flick_inline_backward: 'animated_scroll',
|
||||||
|
},
|
||||||
|
'paged_mode': {
|
||||||
|
GESTURE.flick_block_forward: 'next_section',
|
||||||
|
GESTURE.flick_block_backward: 'prev_section',
|
||||||
|
GESTURE.flick_inline_forward: 'next_screen',
|
||||||
|
GESTURE.flick_inline_backward: 'prev_screen',
|
||||||
|
GESTURE.swipe_inline_forward_hold: 'next_screen',
|
||||||
|
GESTURE.swipe_inline_backward_hold: 'prev_screen',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
def action_for_gesture(gesture, in_flow_mode):
|
||||||
|
overrides = opts.gesture_overrides
|
||||||
|
mode = 'flow_mode' if in_flow_mode else 'paged_mode'
|
||||||
|
mode_overrides = overrides[mode] or {}
|
||||||
|
if mode_overrides[gesture.type]:
|
||||||
|
return mode_overrides[gesture.type]
|
||||||
|
common_overrides = overrides.common or {}
|
||||||
|
if common_overrides[gesture.type]:
|
||||||
|
return common_overrides[gesture.type]
|
||||||
|
if default_actions_for_gesture[mode][gesture.type]:
|
||||||
|
return default_actions_for_gesture[mode][gesture.type]
|
||||||
|
return default_actions_for_gesture.common[gesture.type] or 'none'
|
@ -9,7 +9,6 @@ from range_utils import (
|
|||||||
all_annots_in_selection, highlight_associated_with_selection, last_span_for_crw,
|
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
|
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.cfi import cfi_for_selection, range_from_cfi
|
||||||
from read_book.extract import get_elements
|
from read_book.extract import get_elements
|
||||||
from read_book.find import (
|
from read_book.find import (
|
||||||
@ -27,6 +26,7 @@ from read_book.flow_mode import (
|
|||||||
start_drag_scroll as start_drag_scroll_flow
|
start_drag_scroll as start_drag_scroll_flow
|
||||||
)
|
)
|
||||||
from read_book.footnotes import is_footnote_link
|
from read_book.footnotes import is_footnote_link
|
||||||
|
from read_book.gestures import action_for_gesture
|
||||||
from read_book.globals import (
|
from read_book.globals import (
|
||||||
annot_id_uuid_map, clear_annot_id_uuid_map, current_book, current_layout_mode,
|
annot_id_uuid_map, clear_annot_id_uuid_map, current_book, current_layout_mode,
|
||||||
current_spine_item, runtime, set_boss, set_current_spine_item, set_layout_mode,
|
current_spine_item, runtime, set_boss, set_current_spine_item, set_layout_mode,
|
||||||
@ -316,13 +316,14 @@ class IframeBoss:
|
|||||||
self.auto_scroll_action('toggle')
|
self.auto_scroll_action('toggle')
|
||||||
|
|
||||||
def handle_gesture(self, gesture):
|
def handle_gesture(self, gesture):
|
||||||
if gesture.type is GESTURE.control_zone_tap or gesture.type is GESTURE.two_finger_tap:
|
gesture.resolved_action = action_for_gesture(gesture, current_layout_mode() is 'flow')
|
||||||
|
if gesture.resolved_action is 'show_chrome':
|
||||||
self.send_message('show_chrome')
|
self.send_message('show_chrome')
|
||||||
elif gesture.type is GESTURE.pinch_in:
|
elif gesture.resolved_action is 'decrease_font_size':
|
||||||
self.send_message('bump_font_size', increase=False)
|
self.send_message('bump_font_size', increase=False)
|
||||||
elif gesture.type is GESTURE.pinch_out:
|
elif gesture.resolved_action is 'increase_font_size':
|
||||||
self.send_message('bump_font_size', increase=True)
|
self.send_message('bump_font_size', increase=True)
|
||||||
elif gesture.type is GESTURE.long_tap:
|
elif gesture.resolved_action is 'highlight_or_inspect':
|
||||||
self.handle_long_tap(gesture)
|
self.handle_long_tap(gesture)
|
||||||
else:
|
else:
|
||||||
self._handle_gesture(gesture)
|
self._handle_gesture(gesture)
|
||||||
|
@ -32,7 +32,6 @@ from read_book.cfi import (
|
|||||||
scroll_to as cfi_scroll_to
|
scroll_to as cfi_scroll_to
|
||||||
)
|
)
|
||||||
from read_book.globals import current_spine_item, get_boss, rtl_page_progression
|
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.settings import opts
|
||||||
from read_book.viewport import scroll_viewport, line_height, rem_size, get_unit_size_in_pixels
|
from read_book.viewport import scroll_viewport, line_height, rem_size, get_unit_size_in_pixels
|
||||||
from utils import (
|
from utils import (
|
||||||
@ -811,18 +810,18 @@ def handle_shortcut(sc_name, evt):
|
|||||||
def handle_gesture(gesture):
|
def handle_gesture(gesture):
|
||||||
# Gesture progression direction is determined in the gesture code,
|
# Gesture progression direction is determined in the gesture code,
|
||||||
# don't set flip_if_rtl_page_progression=True here.
|
# don't set flip_if_rtl_page_progression=True here.
|
||||||
if gesture.type is GESTURE.flick_block_forward:
|
if gesture.resolved_action is 'next_section':
|
||||||
get_boss().send_message('next_section', forward=True)
|
get_boss().send_message('next_section', forward=True)
|
||||||
elif gesture.type is GESTURE.flick_block_backward:
|
elif gesture.resolved_action is 'prev_section':
|
||||||
get_boss().send_message('next_section', forward=False)
|
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:
|
elif gesture.resolved_action is 'next_screen':
|
||||||
scroll_by_page(False, True)
|
scroll_by_page(False, True)
|
||||||
elif gesture.type is GESTURE.flick_inline_backward or gesture.type is GESTURE.swipe_inline_backward_hold:
|
elif gesture.resolved_action is 'prev_screen':
|
||||||
scroll_by_page(True, True)
|
scroll_by_page(True, True)
|
||||||
elif gesture.type is GESTURE.back_zone_tap:
|
elif gesture.resolved_action is 'prev_page':
|
||||||
scroll_by_page(True, opts.paged_taps_scroll_by_screen)
|
scroll_by_page(True, False)
|
||||||
elif gesture.type is GESTURE.forward_zone_tap:
|
elif gesture.resolved_action is 'next_page':
|
||||||
scroll_by_page(False, opts.paged_taps_scroll_by_screen)
|
scroll_by_page(False, False)
|
||||||
|
|
||||||
|
|
||||||
anchor_funcs = {
|
anchor_funcs = {
|
||||||
|
@ -69,8 +69,6 @@ def create_scrolling_panel(container, apply_func, cancel_func):
|
|||||||
'paged_wheel_scrolls_by_screen', _('Mouse wheel scrolls by screen fulls instead of pages')))
|
'paged_wheel_scrolls_by_screen', _('Mouse wheel scrolls by screen fulls instead of pages')))
|
||||||
container.lastChild.appendChild(cb(
|
container.lastChild.appendChild(cb(
|
||||||
'paged_margin_clicks_scroll_by_screen', _('Clicking on the margins scrolls by screen fulls instead of pages')))
|
'paged_margin_clicks_scroll_by_screen', _('Clicking on the margins scrolls by screen fulls instead of pages')))
|
||||||
container.lastChild.appendChild(cb(
|
|
||||||
'paged_taps_scroll_by_screen', _('Tapping scrolls by screen fulls instead of pages')))
|
|
||||||
container.lastChild.appendChild(
|
container.lastChild.appendChild(
|
||||||
E.div(style='display:grid;margin-top:1ex;align-items:center;grid-template-columns:auto min-content;grid-gap:1ex; max-width: 30em',
|
E.div(style='display:grid;margin-top:1ex;align-items:center;grid-template-columns:auto min-content;grid-gap:1ex; max-width: 30em',
|
||||||
*spinner(
|
*spinner(
|
||||||
|
@ -27,11 +27,11 @@ def update_settings(settings):
|
|||||||
opts.override_book_colors = settings.override_book_colors
|
opts.override_book_colors = settings.override_book_colors
|
||||||
opts.paged_wheel_scrolls_by_screen = v'!!settings.paged_wheel_scrolls_by_screen'
|
opts.paged_wheel_scrolls_by_screen = v'!!settings.paged_wheel_scrolls_by_screen'
|
||||||
opts.paged_pixel_scroll_threshold = settings.paged_pixel_scroll_threshold
|
opts.paged_pixel_scroll_threshold = settings.paged_pixel_scroll_threshold
|
||||||
opts.paged_taps_scroll_by_screen = v'!!settings.paged_taps_scroll_by_screen'
|
|
||||||
opts.scroll_auto_boundary_delay = settings.scroll_auto_boundary_delay
|
opts.scroll_auto_boundary_delay = settings.scroll_auto_boundary_delay
|
||||||
opts.scroll_stop_boundaries = v'!!settings.scroll_stop_boundaries'
|
opts.scroll_stop_boundaries = v'!!settings.scroll_stop_boundaries'
|
||||||
opts.reverse_page_turn_zones = v'!!settings.reverse_page_turn_zones'
|
opts.reverse_page_turn_zones = v'!!settings.reverse_page_turn_zones'
|
||||||
opts.user_stylesheet = settings.user_stylesheet
|
opts.user_stylesheet = settings.user_stylesheet
|
||||||
|
opts.gesture_overrides = settings.gesture_overrides
|
||||||
|
|
||||||
update_settings()
|
update_settings()
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ GESTURE_NAMES = {
|
|||||||
'two_finger_tap': _('Two finger tap'),
|
'two_finger_tap': _('Two finger tap'),
|
||||||
'pinch_in': _('Pinch in'),
|
'pinch_in': _('Pinch in'),
|
||||||
'pinch_out': _('Pinch out'),
|
'pinch_out': _('Pinch out'),
|
||||||
|
|
||||||
'flick_inline_backward': _('Flick in writing direction, backwards'),
|
'flick_inline_backward': _('Flick in writing direction, backwards'),
|
||||||
'flick_inline_forward': _('Flick in writing direction, forwards'),
|
'flick_inline_forward': _('Flick in writing direction, forwards'),
|
||||||
'flick_block_backward': _('Flick perpendicular to writing direction, backwards'),
|
'flick_block_backward': _('Flick perpendicular to writing direction, backwards'),
|
||||||
|
@ -1017,12 +1017,12 @@ class View:
|
|||||||
'cover_preserve_aspect_ratio': sd.get('cover_preserve_aspect_ratio'),
|
'cover_preserve_aspect_ratio': sd.get('cover_preserve_aspect_ratio'),
|
||||||
'paged_wheel_scrolls_by_screen': sd.get('paged_wheel_scrolls_by_screen'),
|
'paged_wheel_scrolls_by_screen': sd.get('paged_wheel_scrolls_by_screen'),
|
||||||
'paged_pixel_scroll_threshold': sd.get('paged_pixel_scroll_threshold'),
|
'paged_pixel_scroll_threshold': sd.get('paged_pixel_scroll_threshold'),
|
||||||
'paged_taps_scroll_by_screen': sd.get('paged_taps_scroll_by_screen'),
|
|
||||||
'lines_per_sec_auto': sd.get('lines_per_sec_auto'),
|
'lines_per_sec_auto': sd.get('lines_per_sec_auto'),
|
||||||
'lines_per_sec_smooth': sd.get('lines_per_sec_smooth'),
|
'lines_per_sec_smooth': sd.get('lines_per_sec_smooth'),
|
||||||
'scroll_auto_boundary_delay': sd.get('scroll_auto_boundary_delay'),
|
'scroll_auto_boundary_delay': sd.get('scroll_auto_boundary_delay'),
|
||||||
'scroll_stop_boundaries': sd.get('scroll_stop_boundaries'),
|
'scroll_stop_boundaries': sd.get('scroll_stop_boundaries'),
|
||||||
'reverse_page_turn_zones': sd.get('reverse_page_turn_zones'),
|
'reverse_page_turn_zones': sd.get('reverse_page_turn_zones'),
|
||||||
|
'gesture_overrides': sd.get('gesture_overrides'),
|
||||||
}
|
}
|
||||||
|
|
||||||
def show_name(self, name, initial_position=None):
|
def show_name(self, name, initial_position=None):
|
||||||
|
@ -53,7 +53,6 @@ defaults = {
|
|||||||
'override_book_colors': 'never',
|
'override_book_colors': 'never',
|
||||||
'paged_margin_clicks_scroll_by_screen': True,
|
'paged_margin_clicks_scroll_by_screen': True,
|
||||||
'paged_wheel_scrolls_by_screen': False,
|
'paged_wheel_scrolls_by_screen': False,
|
||||||
'paged_taps_scroll_by_screen': False,
|
|
||||||
'paged_pixel_scroll_threshold': 60,
|
'paged_pixel_scroll_threshold': 60,
|
||||||
'read_mode': 'paged',
|
'read_mode': 'paged',
|
||||||
'scroll_auto_boundary_delay': 5,
|
'scroll_auto_boundary_delay': 5,
|
||||||
@ -78,6 +77,7 @@ defaults = {
|
|||||||
'book_search_mode': 'contains',
|
'book_search_mode': 'contains',
|
||||||
'book_search_case_sensitive': False,
|
'book_search_case_sensitive': False,
|
||||||
'reverse_page_turn_zones': False,
|
'reverse_page_turn_zones': False,
|
||||||
|
'gesture_overrides': {},
|
||||||
}
|
}
|
||||||
|
|
||||||
is_local_setting = {
|
is_local_setting = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user