From 4f04afc17684416735ca74172462570aa7d55dc6 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 27 May 2017 20:50:36 +0530 Subject: [PATCH] Start abstracting the scroll viewport --- src/pyj/read_book/cfi.pyj | 4 ++-- src/pyj/read_book/flow_mode.pyj | 12 +++++----- src/pyj/read_book/globals.pyj | 40 +++++++++++++++++++++++--------- src/pyj/read_book/paged_mode.pyj | 28 +++++++++++----------- src/pyj/read_book/toc.pyj | 6 ++--- src/pyj/read_book/touch.pyj | 6 ++--- 6 files changed, 57 insertions(+), 39 deletions(-) diff --git a/src/pyj/read_book/cfi.pyj b/src/pyj/read_book/cfi.pyj index 9d65db752b..4b4bfb5f5b 100644 --- a/src/pyj/read_book/cfi.pyj +++ b/src/pyj/read_book/cfi.pyj @@ -21,7 +21,7 @@ from __python__ import hash_literals # scroll_to(cfi): which scrolls the browser to a point corresponding to the # given cfi, and returns the x and y co-ordinates of the point. -from read_book.globals import window_width, window_height +from read_book.globals import scroll_viewport # CFI escaping {{{ escape_pat = /[\[\],^();~@!-]/g @@ -540,7 +540,7 @@ def at_point(ox, oy): # {{{ def at_current(): # {{{ winx, winy = window_scroll_pos() - winw, winh = window_width(), window_height() + winw, winh = scroll_viewport.width(), scroll_viewport.height() winw = max(winw, 400) winh = max(winh, 600) deltay = Math.floor(winh/50) diff --git a/src/pyj/read_book/flow_mode.pyj b/src/pyj/read_book/flow_mode.pyj index bdd2605750..cd51ea5c3c 100644 --- a/src/pyj/read_book/flow_mode.pyj +++ b/src/pyj/read_book/flow_mode.pyj @@ -3,7 +3,7 @@ from __python__ import hash_literals, bound_methods from dom import set_css -from read_book.globals import get_boss, window_width, window_height +from read_book.globals import get_boss, scroll_viewport from keycodes import get_key from utils import document_height, document_width, viewport_to_document @@ -31,14 +31,14 @@ def flow_onwheel(evt): elif evt.deltaMode is evt.DOM_DELTA_LINE: dy = 15 * evt.deltaY if evt.deltaMode is evt.DOM_DELTA_PAGE: - dy = (window_height() - 30) * evt.deltaY + dy = (scroll_viewport.height() - 30) * evt.deltaY if evt.deltaX: if evt.deltaMode is evt.DOM_DELTA_PIXEL: dx = evt.deltaX elif evt.deltaMode is evt.DOM_DELTA_LINE: dx = 15 * evt.deltaX else: - dx = (window_width() - 30) * evt.deltaX + dx = (scroll_viewport.width() - 30) * evt.deltaX if dx: window.scrollBy(dx, 0) elif dy: @@ -63,7 +63,7 @@ def goto_boundary(y): @check_for_scroll_end def scroll_by_page(backward): - h = window_height() - 10 + h = scroll_viewport.height() - 10 window.scrollBy(0, -h if backward else h) def flow_onkeydown(evt): @@ -175,10 +175,10 @@ anchor_funcs = { y, x = pos if y < window.pageYOffset: return -1 - if y < window.pageYOffset + window_height(): + if y < window.pageYOffset + scroll_viewport.height(): if x < window.pageXOffset: return -1 - if x < window.pageXOffset + window_width(): + if x < window.pageXOffset + scroll_viewport.width(): return 0 return 1 , diff --git a/src/pyj/read_book/globals.pyj b/src/pyj/read_book/globals.pyj index a6788f9682..33050ff22f 100644 --- a/src/pyj/read_book/globals.pyj +++ b/src/pyj/read_book/globals.pyj @@ -39,6 +39,35 @@ class Messenger: messenger = Messenger() iframe_id = 'read-book-iframe' uid = 'calibre-' + hexlify(random_bytes(12)) +scroll_viewport = {} + +def flow_viewport_x(): + return window.pageXOffset + +def flow_viewport_y(): + return window.pageYOffset + +def flow_viewport_scroll_to(x, y): + window.scrollTo(x, y) + +scroll_viewport.x = flow_viewport_x +scroll_viewport.y = flow_viewport_y +scroll_viewport.scroll_to = flow_viewport_scroll_to + +if is_ios: + window_width = def (): + return window_width.from_parent or window.innerWidth + window_height = def(): + return window_height.from_parent or window.innerHeight +else: + window_width = def(): + return window.innerWidth + window_height = def(): + return window.innerHeight + +scroll_viewport.width = window_width +scroll_viewport.height = window_height + def current_layout_mode(): return current_layout_mode.value @@ -73,14 +102,3 @@ register_callback(def(): scheme = default_color_schemes[key] scheme.name = gt(scheme.name) ) - -if is_ios: - window_width = def (): - return window_width.from_parent or window.innerWidth - window_height = def(): - return window_height.from_parent or window.innerHeight -else: - window_width = def(): - return window.innerWidth - window_height = def(): - return window.innerHeight diff --git a/src/pyj/read_book/paged_mode.pyj b/src/pyj/read_book/paged_mode.pyj index d2438fb09a..e6aa5dc165 100644 --- a/src/pyj/read_book/paged_mode.pyj +++ b/src/pyj/read_book/paged_mode.pyj @@ -6,7 +6,7 @@ from dom import set_css from elementmaker import E from keycodes import get_key from read_book.cfi import scroll_to as cfi_scroll_to, at_point as cfi_at_point, at_current as cfi_at_current -from read_book.globals import get_boss, window_width, window_height +from read_book.globals import get_boss, scroll_viewport from read_book.settings import opts import traceback from utils import get_elem_data, set_elem_data, viewport_to_document, document_width @@ -112,19 +112,19 @@ def layout(is_single_page): body_style = window.getComputedStyle(document.body) first_layout = not _in_paged_mode cps = opts.columns_per_screen or {} - cps = cps.landscape if window_width() > window_height() else cps.portrait + cps = cps.landscape if scroll_viewport.width() > scroll_viewport.height() else cps.portrait try: cps = int(cps) except: cps = 0 if not cps: - cps = int(Math.floor(window_width() / 500.0)) + cps = int(Math.floor(scroll_viewport.width() / 500.0)) cps = max(1, min(cps or 1, 20)) if first_layout: handle_rtl_body(body_style) # Check if the current document is a full screen layout like # cover, if so we treat it specially. - single_screen = (document.body.scrollHeight < window_height() + 75) + single_screen = (document.body.scrollHeight < scroll_viewport.height() + 75) first_layout = True has_svg = document.getElementsByTagName('svg').length > 0 imgs = document.getElementsByTagName('img') @@ -149,7 +149,7 @@ def layout(is_single_page): n = cols_per_screen = cps # Calculate the column width so that cols_per_screen columns fit exactly in # the window width, with their separator margins - ww = col_width = screen_width = window_width() + ww = col_width = screen_width = scroll_viewport.width() gap = 0 if n > 1: # Adjust the side margin so that the window width satisfies @@ -158,7 +158,7 @@ def layout(is_single_page): gap = sm + ((ww + sm) % n) # Ensure ww + gap is a multiple of n col_width = ((ww + gap) // n) - gap - screen_height = window_height() + screen_height = scroll_viewport.height() col_and_gap = col_width + gap set_css(document.body, column_gap=gap + 'px', column_width=col_width + 'px', column_rule='0px inset blue', @@ -272,8 +272,8 @@ def column_location(elem): c = column_at(left) width = min(br.right, (c+1)*col_and_gap) - br.left if br.bottom < br.top: - br.bottom = window_height() - height = min(br.bottom, window_height()) - br.top + br.bottom = scroll_viewport.height() + height = min(br.bottom, scroll_viewport.height()) - br.top left -= c * col_and_gap return {'column':c, 'left':left, 'top':top, 'width':width, 'height':height} @@ -304,7 +304,7 @@ def next_screen_location(): cols_left = ncols - (current_col + cols_per_screen) if cols_left < cols_per_screen: return -1 # Only blank, dummy pages left - limit = document.body.scrollWidth - window_width() + limit = document.body.scrollWidth - scroll_viewport.width() if limit < col_and_gap: return -1 if ans > limit: @@ -332,7 +332,7 @@ def next_col_location(): return -1 cc = current_column_location() ans = cc + col_and_gap - limit = document.body.scrollWidth - window_width() + limit = document.body.scrollWidth - scroll_viewport.width() if ans > limit: ans = limit if current_scroll_offset() < limit else -1 return ans @@ -421,9 +421,9 @@ def current_cfi(): if left < 0 or right > document.body.scrollWidth: continue deltax = col_and_gap // 25 - deltay = window_height() // 25 + deltay = scroll_viewport.height() // 25 cury = 0 - while cury < window_height(): + while cury < scroll_viewport.height(): curx = left while curx < right - gap: cfi = cfi_at_point(curx-current_scroll_offset(), cury-window.pageYOffset) @@ -445,11 +445,11 @@ def current_cfi(): def progress_frac(frac): # The current scroll position as a fraction between 0 and 1 if in_paged_mode: - limit = document.body.scrollWidth - window_width() + limit = document.body.scrollWidth - scroll_viewport.width() if limit <= 0: return 0.0 return current_scroll_offset() / limit - limit = document.body.scrollHeight - window_height() + limit = document.body.scrollHeight - scroll_viewport.height() if limit <= 0: return 0.0 return window.pageYOffset / limit diff --git a/src/pyj/read_book/toc.pyj b/src/pyj/read_book/toc.pyj index e40dd331d1..c3ce7058bd 100644 --- a/src/pyj/read_book/toc.pyj +++ b/src/pyj/read_book/toc.pyj @@ -8,7 +8,7 @@ from elementmaker import E from gettext import gettext as _ from modals import error_dialog from widgets import create_tree, find_text_in_tree, scroll_tree_item_into_view -from read_book.globals import toc_anchor_map, set_toc_anchor_map, current_spine_item, current_layout_mode, current_book, window_width, window_height +from read_book.globals import toc_anchor_map, set_toc_anchor_map, current_spine_item, current_layout_mode, current_book, scroll_viewport def update_visible_toc_nodes(visible_anchors): @@ -137,7 +137,7 @@ def create_toc_panel(book, container, onclick): def current_toc_anchor_map(tam, anchor_funcs): current_map = toc_anchor_map() - if not (current_map and current_map.layout_mode is current_layout_mode() and current_map.width is window_width() and current_map.height is window_height()): + if not (current_map and current_map.layout_mode is current_layout_mode() and current_map.width is scroll_viewport.width() and current_map.height is scroll_viewport.height()): name = current_spine_item().name am = {} anchors = v'[]' @@ -154,7 +154,7 @@ def current_toc_anchor_map(tam, anchor_funcs): # stable sort by position in document anchors.sort(def (a, b): return anchor_funcs.cmp(am[a], am[b]) or (pos_map[a] - pos_map[b]);) - current_map = {'layout_mode': current_layout_mode, 'width': window_width(), 'height': window_height(), 'pos_map': am, 'sorted_anchors':anchors} + current_map = {'layout_mode': current_layout_mode, 'width': scroll_viewport.width(), 'height': scroll_viewport.height(), 'pos_map': am, 'sorted_anchors':anchors} set_toc_anchor_map(current_map) return current_map diff --git a/src/pyj/read_book/touch.pyj b/src/pyj/read_book/touch.pyj index b44650b17c..793282c7a9 100644 --- a/src/pyj/read_book/touch.pyj +++ b/src/pyj/read_book/touch.pyj @@ -2,7 +2,7 @@ # License: GPL v3 Copyright: 2016, Kovid Goyal from __python__ import hash_literals, bound_methods -from read_book.globals import get_boss, window_width, window_height +from read_book.globals import get_boss, scroll_viewport from book_list.globals import get_read_ui HOLD_THRESHOLD = 750 # milliseconds @@ -240,10 +240,10 @@ class BookTouchHandler(TouchHandler): return if not gesture.active: if self.for_side_margin or not tap_on_link(gesture): - if gesture.viewport_y < min(100, window_height() / 4): + if gesture.viewport_y < min(100, scroll_viewport.height() / 4): gesture.type = 'show-chrome' else: - if gesture.viewport_x < min(100, window_width() / 4): + if gesture.viewport_x < min(100, scroll_viewport.width() / 4): gesture.type = 'prev-page' else: gesture.type = 'next-page'