diff --git a/resources/compiled_coffeescript.zip b/resources/compiled_coffeescript.zip index 05e40b1bb4..31540747f5 100644 Binary files a/resources/compiled_coffeescript.zip and b/resources/compiled_coffeescript.zip differ diff --git a/src/calibre/ebooks/oeb/display/paged.coffee b/src/calibre/ebooks/oeb/display/paged.coffee index 094d137adc..74cc7873b9 100644 --- a/src/calibre/ebooks/oeb/display/paged.coffee +++ b/src/calibre/ebooks/oeb/display/paged.coffee @@ -530,7 +530,7 @@ class PagedDisplay # selection this.scroll_to_xpos(left+5) - jump_to_cfi: (cfi) -> + jump_to_cfi: (cfi, job_id=-1) -> # Jump to the position indicated by the specified conformal fragment # indicator (requires the cfi.coffee library). When in paged mode, the # scroll is performed so that the column containing the position @@ -540,6 +540,8 @@ class PagedDisplay this.scroll_to_xpos(x) else window.scrollTo(0, y) + if window.py_bridge + window.py_bridge.jump_to_cfi_finished(job_id) ) current_cfi: () -> diff --git a/src/calibre/gui2/viewer/documentview.py b/src/calibre/gui2/viewer/documentview.py index dbac9c7b97..1fd474c2bb 100644 --- a/src/calibre/gui2/viewer/documentview.py +++ b/src/calibre/gui2/viewer/documentview.py @@ -93,6 +93,7 @@ class Document(QWebPage): # {{{ # javascript, get/set the value as: py_bridge.value self.bridge_value = None self.first_load = True + self.jump_to_cfi_listeners = set() self.debug_javascript = debug_javascript self.anchor_positions = {} @@ -336,6 +337,11 @@ class Document(QWebPage): # {{{ def debug(self, msg): prints(unicode(msg)) + @pyqtSlot(int) + def jump_to_cfi_finished(self, job_id): + for l in self.jump_to_cfi_listeners: + l(job_id) + def reference_mode(self, enable): self.javascript(('enter' if enable else 'leave')+'_reference_mode()') diff --git a/src/calibre/gui2/viewer/main.py b/src/calibre/gui2/viewer/main.py index 6d1afa8bef..41e3dc343c 100644 --- a/src/calibre/gui2/viewer/main.py +++ b/src/calibre/gui2/viewer/main.py @@ -722,23 +722,16 @@ class EbookViewer(MainWindow): if self.isFullScreen(): self.relayout_fullscreen_labels() self.view.document.after_resize() - # For some reason scroll_fraction returns incorrect results in paged - # mode for some time after a resize is finished. No way of knowing - # exactly how long, so we update it in a second, in the hopes that it - # will be enough *most* of the time. - QTimer.singleShot(1000, self.scroll_after_resize_done) if not wmc: pre_footnote_pos = self.pre_footnote_toggle_position() if pre_footnote_pos is not None: self.view.document.page_number = pre_footnote_pos else: self.view.document.page_position.restore() - - def scroll_after_resize_done(self): - self.update_page_number() - if len(self.page_position_on_footnote_toggle) % 2 == 1: - self.page_position_on_footnote_toggle[-1] = self.page_position_on_footnote_toggle[-1]._replace( - after_resize_page_number=self.view.document.page_number) + self.update_page_number() + if len(self.page_position_on_footnote_toggle) % 2 == 1: + self.page_position_on_footnote_toggle[-1] = self.page_position_on_footnote_toggle[-1]._replace( + after_resize_page_number=self.view.document.page_number) def update_page_number(self): self.set_page_number(self.view.document.scroll_fraction) diff --git a/src/calibre/gui2/viewer/position.py b/src/calibre/gui2/viewer/position.py index 2bcc849821..d97348fc28 100644 --- a/src/calibre/gui2/viewer/position.py +++ b/src/calibre/gui2/viewer/position.py @@ -7,12 +7,19 @@ __license__ = 'GPL v3' __copyright__ = '2012, Kovid Goyal ' __docformat__ = 'restructuredtext en' -import json +import json, time + +from PyQt5.Qt import QApplication, QEventLoop + +from calibre.constants import DEBUG class PagePosition(object): def __init__(self, document): self.document = document + document.jump_to_cfi_listeners.add(self) + self.cfi_job_id = 0 + self.pending_scrolls = set() @property def viewport_cfi(self): @@ -30,9 +37,22 @@ class PagePosition(object): def scroll_to_cfi(self, cfi): if cfi: + jid = self.cfi_job_id + self.cfi_job_id += 1 cfi = json.dumps(cfi) + self.pending_scrolls.add(jid) self.document.mainFrame().evaluateJavaScript( - 'paged_display.jump_to_cfi(%s)'%cfi) + 'paged_display.jump_to_cfi(%s, %d)' % (cfi, jid)) + # jump_to_cfi is async, so we wait for it to complete + st = time.time() + WAIT = 1 # seconds + while jid in self.pending_scrolls and time.time() - st < WAIT: + QApplication.processEvents(QEventLoop.ExcludeUserInputEvents | QEventLoop.ExcludeSocketNotifiers) + time.sleep(0.01) + if jid in self.pending_scrolls: + self.pending_scrolls.discard(jid) + if DEBUG: + print ('jump_to_cfi() failed to complete after %s seconds' % WAIT) @property def current_pos(self): @@ -47,6 +67,9 @@ class PagePosition(object): def __exit__(self, *args): self.restore() + def __call__(self, cfi_job_id): + self.pending_scrolls.discard(cfi_job_id) + def save(self, overwrite=True): if not overwrite and self._cpos is not None: return @@ -66,5 +89,3 @@ class PagePosition(object): def set_pos(self, pos): self._cpos = pos - -