From c5abc531e097c45c4ec4d97bf5aaafc9686ef937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Wed, 8 May 2019 04:11:35 +0100 Subject: [PATCH] Fix scrolling glitch during preview Typing while in preview mode would occasionally lead to a scrolling glitch, where scroll would briefly be at 0, before jumping to the location it was supposed to be in in the first case. This happened due to the async nature of JS calls, in the following scenario: 1. Load 2. Read started 3. Read finished 4. Read started 5. Load 6. Read finished The results from op 4 would be invalid due to loading in-between, and handling the result in 6 would set the wrong scroll value. This change ensures results are discarded whenever we are waiting for them and a new load starts. --- uberwriter/web_view.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/uberwriter/web_view.py b/uberwriter/web_view.py index 46130e8..d4bc6ae 100644 --- a/uberwriter/web_view.py +++ b/uberwriter/web_view.py @@ -42,6 +42,7 @@ e.scrollTop = (e.scrollHeight - e.clientHeight) * scale; self.state_loaded = False self.state_load_failed = False + self.state_discard_result = False self.state_waiting = False self.timeout_id = None @@ -56,6 +57,7 @@ e.scrollTop = (e.scrollHeight - e.clientHeight) * scale; def on_load_changed(self, _web_view, event): self.state_loaded = event >= WebKit2.LoadEvent.COMMITTED and not self.state_load_failed self.state_load_failed = False + self.state_discard_result = event == WebKit2.LoadEvent.STARTED and self.state_waiting self.pending_scroll_scale = self.scroll_scale self.state_loop() @@ -74,16 +76,20 @@ e.scrollTop = (e.scrollHeight - e.clientHeight) * scale; def read_scroll_scale(self): self.state_waiting = True self.run_javascript( - self.GET_SCROLL_SCALE_JS, None, self.sync_scroll_scale) + self.GET_SCROLL_SCALE_JS, None, self.finish_read_scroll_scale) def write_scroll_scale(self, scroll_scale): self.run_javascript( self.SET_SCROLL_SCALE_JS.format(scroll_scale), None, None) - def sync_scroll_scale(self, _web_view, result): + def finish_read_scroll_scale(self, _web_view, result): self.state_waiting = False - result = self.run_javascript_finish(result) - self.state_loop(result.get_js_value().to_double()) + if not self.state_discard_result: + result = self.run_javascript_finish(result) + self.state_loop(result.get_js_value().to_double()) + else: + self.state_discard_result = False + self.state_loop() def state_loop(self, scroll_scale=None, delay=16): # 16ms ~ 60hz # Remove any pending callbacks