From 8271fcff30edae94a9c29fe95d784ce5d67fcee6 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 1 Sep 2023 15:03:55 +0530 Subject: [PATCH] E-book viewer: Add a new option under scrolling behavior to control horizontal mouse wheel events jumping to next section --- src/pyj/read_book/paged_mode.pyj | 71 +++++++++++++++++---------- src/pyj/read_book/prefs/scrolling.pyj | 2 + src/pyj/read_book/settings.pyj | 1 + src/pyj/read_book/view.pyj | 1 + src/pyj/session.pyj | 1 + 5 files changed, 50 insertions(+), 26 deletions(-) diff --git a/src/pyj/read_book/paged_mode.pyj b/src/pyj/read_book/paged_mode.pyj index 4610c835e4..38c41bcc8f 100644 --- a/src/pyj/read_book/paged_mode.pyj +++ b/src/pyj/read_book/paged_mode.pyj @@ -679,43 +679,63 @@ 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 -class HandleWheel: - - def __init__(self): - self.reset() +class WheelState: + last_event_mode = 'page' + last_event_at = -10000 + last_event_backwards = False + accumulated_scroll = 0 def reset(self): - self.last_event_mode = 'page' - self.last_event_at = -10000 - self.last_event_backwards = False - self.accumulated_scroll = 0 + self.last_event_mode = WheelState.last_event_mode + self.last_event_at = WheelState.last_event_at + self.last_event_backwards = WheelState.last_event_backwards + self.accumulated_scroll = WheelState.accumulated_scroll - def onwheel(self, evt): - if not (evt.deltaY or evt.deltaX): - return - if evt.deltaY: - backward = evt.deltaY < 0 - if evt.deltaMode is window.WheelEvent.DOM_DELTA_PIXEL: - self.add_pixel_scroll(backward, Math.abs(evt.deltaY)) - else: - self.do_scroll(backward) - if evt.deltaX: - backward = evt.deltaX < 0 - self.do_section_jump(backward) - - def add_pixel_scroll(self, backward, deltaY): + def add_pixel_scroll(self, backward, delta, scroll_func): 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 'pixel': self.accumulated_scroll = 0 self.last_event_mode = 'pixel' self.last_event_at = now self.last_event_backwards = backward - self.accumulated_scroll += deltaY + self.accumulated_scroll += delta if self.accumulated_scroll > opts.paged_pixel_scroll_threshold: - self.do_scroll(backward) + self.reset() + scroll_func(backward) + + +class HandleWheel: + + def __init__(self): + self.vertical_state = WheelState() + self.horizontal_state = WheelState() + + def onwheel(self, evt): + if not (evt.deltaY or evt.deltaX): + return + major_axis_vertical = True + if evt.deltaY: + if evt.deltaX: + major_axis_vertical = Math.abs(evt.deltaY) >= Math.abs(evt.deltaX) + else: + major_axis_vertical = False + if major_axis_vertical: + backward = evt.deltaY < 0 + if evt.deltaMode is window.WheelEvent.DOM_DELTA_PIXEL: + self.vertical_state.add_pixel_scroll(backward, Math.abs(evt.deltaY), self.do_scroll) + else: + self.vertical_state.reset() + self.do_scroll(backward) + else: + if opts.paged_wheel_section_jumps: + backward = evt.deltaX < 0 + if evt.deltaMode is window.WheelEvent.DOM_DELTA_PIXEL: + self.horizontal_state.add_pixel_scroll(backward, Math.abs(evt.deltaX), self.do_section_jump) + else: + self.horizontal_state.reset() + self.do_section_jump(backward) def do_scroll(self, backward): - self.reset() if opts.paged_wheel_scrolls_by_screen: pos = previous_screen_location() if backward else next_screen_location() else: @@ -726,7 +746,6 @@ class HandleWheel: scroll_to_pos(pos) def do_section_jump(self, backward): - self.reset() get_boss().send_message('next_section', forward=not backward) wheel_handler = HandleWheel() diff --git a/src/pyj/read_book/prefs/scrolling.pyj b/src/pyj/read_book/prefs/scrolling.pyj index f3ccf67be3..122e82b6c7 100644 --- a/src/pyj/read_book/prefs/scrolling.pyj +++ b/src/pyj/read_book/prefs/scrolling.pyj @@ -67,6 +67,8 @@ def create_scrolling_panel(container, apply_func, cancel_func): container.appendChild(E.div(style='margin-left: 1rem')) container.lastChild.appendChild(cb( 'paged_wheel_scrolls_by_screen', _('Mouse wheel scrolls by screen fulls instead of pages'))) + container.lastChild.appendChild(cb( + 'paged_wheel_section_jumps', _('Horizontal mouse wheel jumps to next/previous section'))) container.lastChild.appendChild(cb( 'paged_margin_clicks_scroll_by_screen', _('Clicking on the margins scrolls by screen fulls instead of pages'))) container.lastChild.appendChild( diff --git a/src/pyj/read_book/settings.pyj b/src/pyj/read_book/settings.pyj index 7b5cc894bb..228d2fa5a4 100644 --- a/src/pyj/read_book/settings.pyj +++ b/src/pyj/read_book/settings.pyj @@ -26,6 +26,7 @@ def update_settings(settings): opts.margin_bottom = max(0, settings.margin_bottom) opts.override_book_colors = settings.override_book_colors opts.paged_wheel_scrolls_by_screen = v'!!settings.paged_wheel_scrolls_by_screen' + opts.paged_wheel_section_jumps = v'!!settings.paged_wheel_section_jumps' opts.paged_pixel_scroll_threshold = settings.paged_pixel_scroll_threshold opts.scroll_auto_boundary_delay = settings.scroll_auto_boundary_delay opts.scroll_stop_boundaries = v'!!settings.scroll_stop_boundaries' diff --git a/src/pyj/read_book/view.pyj b/src/pyj/read_book/view.pyj index 26c355a99f..c10dd731db 100644 --- a/src/pyj/read_book/view.pyj +++ b/src/pyj/read_book/view.pyj @@ -1018,6 +1018,7 @@ class View: 'hide_tooltips': sd.get('hide_tooltips'), 'cover_preserve_aspect_ratio': sd.get('cover_preserve_aspect_ratio'), 'paged_wheel_scrolls_by_screen': sd.get('paged_wheel_scrolls_by_screen'), + 'paged_wheel_section_jumps': sd.get('paged_wheel_section_jumps'), 'paged_pixel_scroll_threshold': sd.get('paged_pixel_scroll_threshold'), 'lines_per_sec_auto': sd.get('lines_per_sec_auto'), 'lines_per_sec_smooth': sd.get('lines_per_sec_smooth'), diff --git a/src/pyj/session.pyj b/src/pyj/session.pyj index 0812a7c427..7b1cabd521 100644 --- a/src/pyj/session.pyj +++ b/src/pyj/session.pyj @@ -53,6 +53,7 @@ defaults = { 'override_book_colors': 'never', 'paged_margin_clicks_scroll_by_screen': True, 'paged_wheel_scrolls_by_screen': False, + 'paged_wheel_section_jumps': True, 'paged_pixel_scroll_threshold': 60, 'read_mode': 'paged', 'scroll_auto_boundary_delay': 5,