Simplify the change tracker implementation a little

Since the cursor is always redrawn there is no need to track its
attributes and position separately. Also no need to use a callback for
dirtied status.
This commit is contained in:
Kovid Goyal 2016-11-11 18:18:09 +05:30
parent 1b252be434
commit c7b87f9174
4 changed files with 23 additions and 30 deletions

View File

@ -53,7 +53,7 @@ class Boss(Thread):
self.queue_action(self.initialize)
self.profile = args.profile
self.window, self.opts = window, opts
self.tracker = ChangeTracker(self.mark_dirtied)
self.tracker = ChangeTracker()
self.screen = Screen(self.opts, self.tracker, self)
self.char_grid = CharGrid(self.screen, opts, window_width, window_height)
sclass = DebugStream if args.dump_commands else Stream
@ -179,6 +179,8 @@ class Boss(Thread):
dispatch[r]()
if writers:
self.write_ready()
if self.tracker.dirty:
self.mark_dirtied()
if self.pending_update_screen is not None and monotonic() > self.pending_update_screen:
self.apply_update_screen()

View File

@ -246,7 +246,8 @@ class CharGrid:
rd.cell_data = copy(self.sprite_map)
rd.sprite_layout = self.sprites.layout
c = changes.get('cursor')
if c is not None:
if c:
c = self.screen.cursor
rd.cursor = Cursor(c.x, c.y, c.hidden, c.shape, c.color, c.blink)
self.render_queue.put(rd)

View File

@ -52,7 +52,7 @@ class Screen:
for a description of the presentational component, implemented by ``Screen``.
"""
tracker_callbacks = 'cursor_changed cursor_position_changed update_screen update_line_range update_cell_range line_added_to_history'.split()
tracker_callbacks = 'cursor_changed update_screen update_line_range update_cell_range line_added_to_history'.split()
_notify_cursor_position = True
def __init__(self, opts, tracker, callbacks=None, columns: int=80, lines: int=24):
@ -86,7 +86,7 @@ class Screen:
def notify_cursor_position(self):
if self._notify_cursor_position:
self.cursor_position_changed(self.cursor)
self.cursor_changed()
@property
def display(self) -> Sequence[str]:
@ -136,7 +136,7 @@ class Screen:
self.normal_keypad_mode()
self.cursor = Cursor(0, 0)
self.cursor_changed(self.cursor)
self.cursor_changed()
self.cursor_position()
self.change_default_color('fg', None)
self.change_default_color('bg', None)
@ -235,7 +235,7 @@ class Screen:
# Show/hide the cursor.
previous, self.cursor.hidden = self.cursor.hidden, mo.DECTCEM not in self.mode
if previous != self.cursor.hidden:
self.cursor_changed(self.cursor)
self.cursor_changed()
if mo.ALTERNATE_SCREEN in self.mode and self.linebuf is self.main_linebuf:
self.toggle_screen_buffer()
@ -279,7 +279,7 @@ class Screen:
# Show/hide the cursor.
previous, self.cursor.hidden = self.cursor.hidden, mo.DECTCEM not in self.mode
if previous != self.cursor.hidden:
self.cursor_changed(self.cursor)
self.cursor_changed()
if mo.ALTERNATE_SCREEN not in self.mode and self.linebuf is not self.main_linebuf:
self.toggle_screen_buffer()
@ -543,7 +543,7 @@ class Screen:
self.set_mode(mo.DECAWM)
self.cursor = savepoint.cursor
self.cursor_changed(self.cursor)
self.cursor_changed()
self.ensure_bounds(use_margins=True)
else:
# If nothing was saved, the cursor moves to home position;
@ -976,7 +976,7 @@ class Screen:
shape = 'block' if mode < 3 else 'underline' if mode < 5 else 'beam' if mode < 7 else None
if shape != self.cursor.shape or blink != self.cursor.blink:
self.cursor.shape, self.cursor.blink = shape, blink
self.cursor_changed(self.cursor)
self.cursor_changed()
elif secondary == '"': # DECSCA
pass
else: # DECLL
@ -998,7 +998,7 @@ class Screen:
elif val == 12: # cursor color
old, self.cursor.color = self.cursor.color, param
if old != self.cursor.color:
self.cursor_changed(self.cursor)
self.cursor_changed()
if color_names:
for i, cn in enumerate(filter(None, color_names.split(';'))):

View File

@ -25,46 +25,36 @@ def merge_ranges(ranges: Set[Tuple[int]]) -> Iterator[Tuple[int]]:
class ChangeTracker:
def __init__(self, mark_dirtied=lambda: None):
def __init__(self):
self.reset()
self.mark_dirtied = mark_dirtied
def reset(self):
self._dirty = False
self.changed_cursor = None
self.dirty = False
self.changed_cursor = False
self.changed_cells = defaultdict(set)
self.changed_lines = set()
self.screen_changed = False
self.history_line_added_count = 0
def dirty(self):
if not self._dirty:
self._dirty = True
self.mark_dirtied()
def cursor_changed(self, cursor) -> None:
self.changed_cursor = cursor
self.dirty()
def cursor_position_changed(self, cursor) -> None:
self.changed_cursor = cursor
self.dirty()
def cursor_changed(self) -> None:
self.changed_cursor = True
self.dirty = True
def update_screen(self):
self.screen_changed = True
self.dirty()
self.dirty = True
def update_line_range(self, first_line, last_line):
self.changed_lines |= set(range(first_line, last_line + 1))
self.dirty()
self.dirty = True
def update_cell_range(self, y, first_cell, last_cell):
self.changed_cells[y].add((first_cell, last_cell))
self.dirty()
self.dirty = True
def line_added_to_history(self):
self.history_line_added_count += 1
self.dirty()
self.dirty = True
def consolidate_changes(self):
if self.screen_changed: