From f9c9af6463705f66bac86d0a83939fb5166ac711 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 30 Jun 2020 09:50:15 +0530 Subject: [PATCH] Viewer: Fix turning pages in paged mode with a high precision touchpad to generate scroll events too fast --- src/pyj/read_book/flow_mode.pyj | 19 ++----------- src/pyj/read_book/paged_mode.pyj | 47 ++++++++++++++++++++++++++++++-- src/pyj/read_book/viewport.pyj | 18 ++++++++++++ 3 files changed, 64 insertions(+), 20 deletions(-) diff --git a/src/pyj/read_book/flow_mode.pyj b/src/pyj/read_book/flow_mode.pyj index c625b910d7..05fa8402c9 100644 --- a/src/pyj/read_book/flow_mode.pyj +++ b/src/pyj/read_book/flow_mode.pyj @@ -5,25 +5,10 @@ from __python__ import bound_methods, hash_literals from dom import set_css from read_book.globals import current_spine_item, get_boss from read_book.settings import opts -from read_book.viewport import scroll_viewport +from read_book.viewport import line_height, scroll_viewport from utils import document_height, viewport_to_document -def line_height(): - if not line_height.ans: - ds = window.getComputedStyle(document.body) - try: - # will fail if line-height = "normal" - lh = float(ds.lineHeight) - except: - try: - lh = 1.2 * float(ds.fontSize) - except: - lh = 15 - line_height.ans = max(5, lh) - return line_height.ans - - def flow_to_scroll_fraction(frac, on_initial_load): scroll_viewport.scroll_to(0, document_height() * frac) @@ -209,7 +194,7 @@ def handle_shortcut(sc_name, evt): def layout(is_single_page): - line_height.ans = None + line_height(True) set_css(document.body, margin='0', border_width='0', padding='0') diff --git a/src/pyj/read_book/paged_mode.pyj b/src/pyj/read_book/paged_mode.pyj index d03accde4a..efa3490376 100644 --- a/src/pyj/read_book/paged_mode.pyj +++ b/src/pyj/read_book/paged_mode.pyj @@ -14,7 +14,7 @@ from read_book.cfi import ( ) from read_book.globals import current_spine_item, get_boss from read_book.settings import opts -from read_book.viewport import scroll_viewport +from read_book.viewport import scroll_viewport, line_height from utils import ( document_height, document_width, get_elem_data, set_elem_data, viewport_to_document @@ -170,6 +170,7 @@ def current_page_width(): def layout(is_single_page, on_resize): nonlocal _in_paged_mode, col_width, col_and_gap, screen_height, gap, screen_width, is_full_screen_layout, cols_per_screen, number_of_cols + line_height(True) body_style = window.getComputedStyle(document.body) first_layout = not _in_paged_mode cps = calc_columns_per_screen() @@ -293,6 +294,7 @@ def scroll_to_column(number, notify=False, duration=1000): pos = min(pos, limit) scroll_to_offset(pos) + def scroll_to_xpos(xpos, notify=False, duration=1000): nonlocal last_scrolled_to_column # Scroll so that the column containing xpos is the left most column in @@ -537,9 +539,43 @@ def is_return(): return fsd and fsd.cols_per_screen is cols_per_screen and fsd.spine_index is csi.index and fsd.spine_name is csi.name -def onwheel(evt): - if evt.deltaY: +class HandleWheel: + + def __init__(self): + self.reset() + + def reset(self): + self.last_event_mode = 'page' + self.last_event_at = -10000 + self.last_event_backwards = False + self.accumlated_scroll = 0 + + def onwheel(self, evt): + if not evt.deltaY: + return backward = evt.deltaY < 0 + WheelEvent = window.WheelEvent + if evt.deltaMode is WheelEvent.DOM_DELTA_PAGE: + self.do_scroll(backward) + else: + self.add_event(backward, Math.abs(evt.deltaY), 'line' if evt.deltaMode is WheelEvent.DOM_DELTA_LINE else 'pixel') + + def add_event(self, backward, deltaY, mode): + now = window.performance.now() + if now - self.last_event_at > 1000 or self.last_event_backwards is not backward or self.last_event_mode is not mode: + self.accumlated_scroll = 0 + self.last_event_mode = mode + self.last_event_at = now + self.last_event_backwards = backward + lh = line_height() + if mode is 'line': + deltaY *= lh + self.accumlated_scroll += deltaY + if self.accumlated_scroll > 5 * lh: + self.do_scroll(backward) + + def do_scroll(self, backward): + self.reset() if opts.paged_wheel_scrolls_by_screen: x = previous_screen_location() if backward else next_screen_location() else: @@ -549,6 +585,11 @@ def onwheel(evt): else: scroll_to_xpos(x) + +wheel_handler = HandleWheel() +onwheel = wheel_handler.onwheel.bind(wheel_handler) + + def scroll_by_page(backward, by_screen): if by_screen: pos = previous_screen_location() if backward else next_screen_location() diff --git a/src/pyj/read_book/viewport.pyj b/src/pyj/read_book/viewport.pyj index 7ef476d0e8..cdad564a30 100644 --- a/src/pyj/read_book/viewport.pyj +++ b/src/pyj/read_book/viewport.pyj @@ -113,3 +113,21 @@ for attr in FUNCTIONS: if not scroll_viewport['paged_' + attr]: scroll_viewport['paged_' + attr] = scroll_viewport[attr] viewport_mode_changer(scroll_viewport.set_mode) + + +def line_height(reset): + if reset: + line_height.ans = None + return + if not line_height.ans: + ds = window.getComputedStyle(document.body) + try: + # will fail if line-height = "normal" + lh = float(ds.lineHeight) + except: + try: + lh = 1.2 * float(ds.fontSize) + except: + lh = 15 + line_height.ans = max(5, lh) + return line_height.ans