From cbd1c42865cc0ba2464622ecb58557e7a242821b Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 10 Mar 2021 13:19:35 +0530 Subject: [PATCH] E-book viewer: Allow using shift+click to extend selections. Fixes #1918251 [E-book viewer selection broken](https://bugs.launchpad.net/calibre/+bug/1918251) --- manual/viewer.rst | 2 ++ src/pyj/read_book/iframe.pyj | 2 ++ src/pyj/read_book/selection_bar.pyj | 5 +++++ src/pyj/select.pyj | 10 ++++++++++ 4 files changed, 19 insertions(+) diff --git a/manual/viewer.rst b/manual/viewer.rst index afd82fd4b9..f641cdabf5 100644 --- a/manual/viewer.rst +++ b/manual/viewer.rst @@ -111,6 +111,8 @@ highlight. You can add notes and change the color of the highlight. On a touch screen, long tap a word to select it and show the popup bar. Once in highlight mode you can change what text is selected, using touch screen friendly selection handles. Drag the handles to the top or bottom margins to scroll while selecting. +You can also hold the :kbd:`Shift` key and click to extend the selection, +particularly useful for multi-page selections. You can use the :guilabel:`Highlights` button in the viewer controls to show a separate panel with a list of all highlights in the book, diff --git a/src/pyj/read_book/iframe.pyj b/src/pyj/read_book/iframe.pyj index cc8472166d..c7ff0879b8 100644 --- a/src/pyj/read_book/iframe.pyj +++ b/src/pyj/read_book/iframe.pyj @@ -810,6 +810,8 @@ class IframeBoss: sel.setBaseAndExtent(sel.focusNode, sel.focusOffset, end_node, end_offset) except: (console.error or console.log)('Failed to extend selection to paragraph') + elif dtype is 'extend-to-point': + move_end_of_selection(data.pos, None) elif dtype is 'drag-scroll': self.scroll_to_extend_annotation(data.backwards) elif dtype is 'edit-highlight': diff --git a/src/pyj/read_book/selection_bar.pyj b/src/pyj/read_book/selection_bar.pyj index d3a5ad3c12..df8273bd8e 100644 --- a/src/pyj/read_book/selection_bar.pyj +++ b/src/pyj/read_book/selection_bar.pyj @@ -480,6 +480,11 @@ class SelectionBar: self.hide_editor(True) if self.state is WAITING: now = window.performance.now() + if ev.shiftKey: + pos = {'x': ev.clientX, 'y': ev.clientY} + map_to_iframe_coords(pos, get_margins()) + self.send_message('extend-to-point', pos=pos) + return if self.last_double_click_at and now - self.last_double_click_at < 500: self.send_message('extend-to-paragraph') return diff --git a/src/pyj/select.pyj b/src/pyj/select.pyj index 3faa901c08..37352870dc 100644 --- a/src/pyj/select.pyj +++ b/src/pyj/select.pyj @@ -197,6 +197,16 @@ def move_end_of_selection(pos, start): p = caret_position_from_point(pos.x, pos.y) if p: r = sel.getRangeAt(0) + if start is None: + q = document.createRange() + q.setStart(p.offsetNode, p.offset) + q.setEnd(p.offsetNode, p.offset) + if r.compareBoundaryPoints(window.Range.START_TO_START, q) >= 0: + start = True + elif r.compareBoundaryPoints(window.Range.END_TO_END, q) <= 0: + start = False + else: + return if start: if r.startContainer is not p.offsetNode or r.startOffset is not p.offset: r.setStart(p.offsetNode, p.offset)