From 83490b316ff1ef1bf9a51b6e2d676fd450b6fc55 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 4 Aug 2020 18:21:41 +0530 Subject: [PATCH] Implement scrolling keyboard shortcuts when selection bar is showing Also remove unused code --- src/pyj/range_utils.pyj | 15 ------------ src/pyj/read_book/iframe.pyj | 36 ++++------------------------- src/pyj/read_book/selection_bar.pyj | 17 +++++++++++++- src/pyj/select.pyj | 32 ------------------------- 4 files changed, 20 insertions(+), 80 deletions(-) diff --git a/src/pyj/range_utils.pyj b/src/pyj/range_utils.pyj index d4ffd48131..ad25f5e2df 100644 --- a/src/pyj/range_utils.pyj +++ b/src/pyj/range_utils.pyj @@ -153,21 +153,6 @@ def reset_highlight_counter(): wrapper_counter = 0 -def set_selection_to_highlight(): - sel = window.getSelection() - if not sel or not sel.rangeCount: - return - r = sel.getRangeAt(0) - crw = None - for node in text_nodes_in_range(r): - crw = node.parentNode.dataset.calibreRangeWrapper - if crw: - break - if crw: - select_crw(crw) - return crw or None - - def get_annot_id_for(node, offset, annot_id_uuid_map): if not node: diff --git a/src/pyj/read_book/iframe.pyj b/src/pyj/read_book/iframe.pyj index 94740352e6..8b8e53aac3 100644 --- a/src/pyj/read_book/iframe.pyj +++ b/src/pyj/read_book/iframe.pyj @@ -4,16 +4,13 @@ from __python__ import bound_methods, hash_literals import traceback from gettext import gettext as _ -from select import ( - extend_selection_to_limit, selection_extents, selection_extents_at_point, - set_selections_extents_to, word_at_point -) +from select import selection_extents, set_selections_extents_to, word_at_point from fs_images import fix_fullscreen_svg_images from iframe_comm import IframeClient from range_utils import ( highlight_associated_with_selection, reset_highlight_counter, select_crw, - set_selection_to_highlight, unwrap_all_crw, unwrap_crw, wrap_text_in_range + unwrap_all_crw, unwrap_crw, wrap_text_in_range ) from read_book.cfi import ( cfi_for_selection, range_from_cfi, scroll_to as scroll_to_cfi @@ -711,37 +708,12 @@ class IframeBoss: end_reference_mode() def annotations_msg_received(self, data): - in_flow_mode = current_layout_mode() is 'flow' if data.type is 'set-selection': set_selections_extents_to(data.extents) - elif data.type is 'position-handles-at-point': - extents = selection_extents_at_point(data.x, data.y, in_flow_mode) - annot_id = set_selection_to_highlight() - if annot_id: - extents = selection_extents(in_flow_mode) - self.send_message( - 'annotations', type='position-handles', extents=extents, existing=annot_id_uuid_map[annot_id]) - elif data.type is 'drag-scroll': - if self.scroll_to_extend_annotation(data.backwards): - if data.extend_selection: - extend_selection_to_limit(data.handle is 'left', data.backwards) - extents = selection_extents(in_flow_mode) - self.send_message( - 'annotations', type='scrolled', - backwards=data.backwards, handle=data.handle, extents=extents, extended=data.extend_selection - ) - elif data.type is 'paged-scroll': - if self.scroll_to_extend_annotation(data.backwards, False, True): - extents = selection_extents(in_flow_mode) - self.send_message( - 'annotations', type='scrolled', backwards=data.backwards, handle=None, - extents=extents, extended=False - ) - elif data.type is 'perp-scroll': - if in_flow_mode and flow_annotation_scroll(data.backwards, True): - self.send_message('annotations', type='update-handles', extents=selection_extents(in_flow_mode)) elif data.type is 'set-highlight-style': set_selection_style(data.style) + elif data.type is 'trigger-shortcut': + self.on_handle_navigation_shortcut(data) elif data.type is 'edit-highlight': crw_ = {v: k for k, v in Object.entries(annot_id_uuid_map)}[data.uuid] if crw_ and select_crw(crw_): diff --git a/src/pyj/read_book/selection_bar.pyj b/src/pyj/read_book/selection_bar.pyj index d8e1b3f9eb..c89483f5fe 100644 --- a/src/pyj/read_book/selection_bar.pyj +++ b/src/pyj/read_book/selection_bar.pyj @@ -12,6 +12,7 @@ from dom import clear, svgicon, unique_id from modals import error_dialog, question_dialog from read_book.globals import runtime, ui_operations from read_book.highlights import ICON_SIZE, EditNotesAndColors, HighlightStyle +from read_book.shortcuts import shortcut_for_key_event DRAG_SCROLL_ZONE_MIN_HEIGHT = 10 @@ -223,7 +224,8 @@ class SelectionBar: container.addEventListener('touchmove', self.touchmove_on_container, {'passive': False}) container.addEventListener('touchend', self.touchend_on_container, {'passive': False}) container.addEventListener('touchcancel', self.touchend_on_container, {'passive': False}) - container.addEventListener('keydown', self.on_keydown, {'passive': False}) # TODO: Implement this + container.addEventListener('keydown', self.on_keydown, {'passive': False}) + container.setAttribute('tabindex', '0') self.dragging_handle = None self.position_in_handle = {'x': 0, 'y': 0} @@ -462,6 +464,17 @@ class SelectionBar: self.active_touch = None self.end_handle_drag() return + + def on_keydown(self, ev): + ev.stopPropagation(), ev.preventDefault() + if ev.key is 'Escape': + self.clear_selection() + return + sc_name = shortcut_for_key_event(ev, self.view.keyboard_shortcut_map) + if sc_name is 'show_chrome': + self.clear_selection() + elif sc_name in ('up', 'down', 'pageup', 'pagedown', 'left', 'right'): + self.send_message('trigger-shortcut', name=sc_name) # }}} # drag scroll {{{ @@ -499,6 +512,7 @@ class SelectionBar: def hide(self): self.state = HIDDEN self.container.style.display = 'none' + self.view.focus_iframe() def show(self): sd = get_session_data() @@ -506,6 +520,7 @@ class SelectionBar: if sd.get('show_selection_bar'): self.container.style.display = 'block' self.state = WAITING + self.container.focus() @property def is_visible(self): diff --git a/src/pyj/select.pyj b/src/pyj/select.pyj index 1c62daaadc..1ef6ade734 100644 --- a/src/pyj/select.pyj +++ b/src/pyj/select.pyj @@ -107,23 +107,6 @@ def selection_extents(in_flow_mode, end_must_be_focus): return range_extents(start, end, in_flow_mode) -def selection_extents_at_point(x, y, in_flow_mode): - r = word_at_point(x, y) - if r: - sel = window.getSelection() - sel.removeAllRanges() - sel.addRange(r) - return selection_extents(r, r) - ans = empty_range_extents() - ans.start.y = ans.end.y = y - ans.start.height = ans.end.height = parseInt(window.getComputedStyle(document.body).fontSize) + 4 - ans.start.x = x - ans.end.x = x + ans.start.height * 3 - ans.start.onscreen = ans.end.onscreen = True - ans.start.is_empty = ans.end.is_empty = False - return ans - - def range_at_limit(invert_x, invert_y): step = 10 for y in range(0, window.innerHeight + step, step): @@ -137,21 +120,6 @@ def range_at_limit(invert_x, invert_y): return r -def extend_selection_to_limit(left, top): - sel = window.getSelection() - if not sel or not sel.rangeCount or sel.isCollapsed: - return False - new_limit = range_at_limit(not left, not top) - if not new_limit: - return False - r = sel.getRangeAt(0) - if left: - r.setStart(new_limit.startContainer, new_limit.startOffset) - else: - r.setEnd(new_limit.startContainer, new_limit.startOffset) - return True - - def set_selections_extents_to(extents): if extents.start.onscreen and extents.end.onscreen: start = range_from_point(extents.start.x, extents.start.y)