apply method

void apply(
  1. GridUpdate u
)

Implementation

void apply(GridUpdate u) {
  final oldCursorRow = _cursorRow;
  final oldCursorCol = _cursorCol;
  final oldCursorVisible = _cursorVisible;
  final oldCursorShape = _cursorShape;
  final oldCursorBlinking = _cursorBlinking;
  final oldCursorColor = _cursorColor;
  final oldDefaultFg = _defaultFg;
  final oldDefaultBg = _defaultBg;

  _defaultFg = u.defaultFg;
  _defaultBg = u.defaultBg;
  _cursorColor = u.cursorColor;
  // Partial damage only names changed lines; rows/columns on GridUpdate are not
  // viewport size (see FrbEngineBinding._toGridUpdate). Resize on full only.
  if (u.full) {
    _ensureSize(u.rows, u.columns);
    _markAllRowsDirty();
  }
  final delta = u.scrollLineDelta;
  if (delta != 0 && _rows > 0) {
    _rotateRows(delta);
    _scrollLineDeltaForPaint = delta;
    // Only the rows revealed by the scroll need a fresh paint when the
    // painter can blit the retained frame; if retain is unavailable the
    // painter falls back to paintAll.
    final d = delta.abs() > _rows ? _rows : delta.abs();
    if (delta > 0) {
      for (var i = 0; i < d; i++) {
        _dirtyRows.add(i);
      }
    } else {
      for (var i = _rows - d; i < _rows; i++) {
        _dirtyRows.add(i);
      }
    }
  }
  for (final l in u.lines) {
    if (l.line < 0) continue;
    if (l.line >= _rows) {
      _applyOverscanLine(l);
      continue;
    }
    if (!u.full) {
      _dirtyRows.add(l.line);
    }
    // Partial damage can arrive with engine cols > mirror cols when resize races
    // the async drain (LayoutBuilder grew before post-frame resize ran).
    final copy = l.codepoints.length < _columns ? l.codepoints.length : _columns;
    if (copy == 0) continue;
    _codepoints[l.line].setRange(0, copy, l.codepoints);
    _fg[l.line].setRange(0, copy, l.fg);
    _bg[l.line].setRange(0, copy, l.bg);
    _flags[l.line].setRange(0, copy, l.flags);
    _hyperlinkId[l.line].setRange(0, copy, l.hyperlinkId);
    if (copy < _columns) {
      _codepoints[l.line].fillRange(copy, _columns, 32);
      _fg[l.line].fillRange(copy, _columns, _defaultFg);
      _bg[l.line].fillRange(copy, _columns, _defaultBg);
      _flags[l.line].fillRange(copy, _columns, 0);
      _hyperlinkId[l.line].fillRange(copy, _columns, 0);
    }
  }
  // Overscan from explicit field (full updates) or sentinel line index (scroll).
  final o = u.overscan;
  if (o != null) {
    _applyOverscanLine(o);
  }
  _scrollFraction = u.scrollFraction;
  _cursorRow = u.cursorRow;
  _cursorCol = u.cursorCol;
  _cursorVisible = u.cursorVisible;
  _cursorShape = u.cursorShape;
  _cursorBlinking = u.cursorBlinking;
  _modeFlags = u.modeFlags;
  _displayOffset = u.displayOffset;
  if (u.full || u.historySize > 0) {
    _historySize = u.historySize;
  }

  // Metadata-only (or mixed) damage: default colors repaint the whole grid;
  // cursor field changes need the old and new cursor rows at minimum.
  if (!u.full && delta == 0) {
    if (u.defaultFg != oldDefaultFg || u.defaultBg != oldDefaultBg) {
      _markAllRowsDirty();
    } else {
      final cursorChanged = u.cursorRow != oldCursorRow ||
          u.cursorCol != oldCursorCol ||
          u.cursorVisible != oldCursorVisible ||
          u.cursorShape != oldCursorShape ||
          u.cursorBlinking != oldCursorBlinking ||
          u.cursorColor != oldCursorColor;
      if (cursorChanged) {
        _markRowDirtyIfInRange(oldCursorRow);
        _markRowDirtyIfInRange(u.cursorRow);
      }
    }
  }

  _generation++;
  TerminalScrollLatency.markGridOrTextureUpdated(_generation);
  _notifyRepaint();
}