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.
github/fork/yochananmarqos/patch-1
Gonçalo Silva 2019-05-08 04:11:35 +01:00
parent 16382d9574
commit c5abc531e0
1 changed files with 10 additions and 4 deletions

View File

@ -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