1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-12-29 16:56:40 +03:00

Refactor cursor drawing

- draw only when flushed and use the normal position from goto
This commit is contained in:
Tae Won Ha 2017-06-05 14:22:12 +02:00
parent 93b9366a66
commit 5d3aca696d
No known key found for this signature in database
GPG Key ID: E40743465B5B8B44
5 changed files with 43 additions and 79 deletions

View File

@ -91,8 +91,7 @@ class Grid: CustomStringConvertible {
fileprivate(set) var region = Region.zero fileprivate(set) var region = Region.zero
fileprivate(set) var size = Size.zero fileprivate(set) var size = Size.zero
fileprivate(set) var putPosition = Position.zero fileprivate(set) var position = Position.zero
fileprivate(set) var screenCursor = Position.zero
var foreground = defaultForeground var foreground = defaultForeground
var background = defaultBackground var background = defaultBackground
@ -116,7 +115,7 @@ class Grid: CustomStringConvertible {
func resize(_ size: Size) { func resize(_ size: Size) {
self.region = Region(top: 0, bottom: size.height - 1, left: 0, right: size.width - 1) self.region = Region(top: 0, bottom: size.height - 1, left: 0, right: size.width - 1)
self.size = size self.size = size
self.putPosition = Position.zero self.position = Position.zero
let emptyCellAttrs = CellAttributes(fontTrait: .none, let emptyCellAttrs = CellAttributes(fontTrait: .none,
foreground: self.foreground, background: self.background, special: self.special) foreground: self.foreground, background: self.background, special: self.special)
@ -131,8 +130,8 @@ class Grid: CustomStringConvertible {
func eolClear() { func eolClear() {
self.clearRegion( self.clearRegion(
Region(top: self.putPosition.row, bottom: self.putPosition.row, Region(top: self.position.row, bottom: self.position.row,
left: self.putPosition.column, right: self.region.right) left: self.position.column, right: self.region.right)
) )
} }
@ -171,11 +170,7 @@ class Grid: CustomStringConvertible {
} }
func goto(_ position: Position) { func goto(_ position: Position) {
self.putPosition = position self.position = position
}
func moveCursor(_ position: Position) {
self.screenCursor = position
} }
func put(_ string: String) { func put(_ string: String) {
@ -184,17 +179,17 @@ class Grid: CustomStringConvertible {
// => // =>
// |abcde>| <- ">" at the end of the line is wrong -> the XPC could tell the main app whether the string occupies // |abcde>| <- ">" at the end of the line is wrong -> the XPC could tell the main app whether the string occupies
// | | two cells using vim_strwidth() // | | two cells using vim_strwidth()
self.cells[self.putPosition.row][self.putPosition.column] = Cell(string: string, attrs: self.attrs) self.cells[self.position.row][self.position.column] = Cell(string: string, attrs: self.attrs)
// Increment the column of the put position because neovim calls sets the position only once when drawing // Increment the column of the put position because neovim calls sets the position only once when drawing
// consecutive cells in the same line // consecutive cells in the same line
self.putPosition.column += 1 self.advancePosition()
} }
func putMarkedText(_ string: String) { func putMarkedText(_ string: String) {
// NOTE: Maybe there's a better way to indicate marked text than inverting... // NOTE: Maybe there's a better way to indicate marked text than inverting...
self.cells[self.putPosition.row][self.putPosition.column] = Cell(string: string, attrs: self.attrs, marked: true) self.cells[self.position.row][self.position.column] = Cell(string: string, attrs: self.attrs, marked: true)
self.putPosition.column += 1 self.advancePosition()
} }
func unmarkCell(_ position: Position) { func unmarkCell(_ position: Position) {
@ -302,4 +297,11 @@ class Grid: CustomStringConvertible {
return true return true
} }
fileprivate func advancePosition() {
self.position.column += 1
if self.position.column >= self.size.width {
self.position.column -= 1
}
}
} }

View File

@ -79,14 +79,7 @@ extension NeoVimView {
} }
fileprivate func cursorRegion() -> Region { fileprivate func cursorRegion() -> Region {
let cursorPosition: Position let cursorPosition = self.grid.position
if self.mode == .cmdline
|| self.mode == .cmdlineInsert
|| self.mode == .cmdlineReplace {
cursorPosition = self.grid.putPosition
} else {
cursorPosition = self.grid.screenCursor
}
let saneRow = max(0, min(cursorPosition.row, self.grid.size.height - 1)) let saneRow = max(0, min(cursorPosition.row, self.grid.size.height - 1))
let saneColumn = max(0, min(cursorPosition.column, self.grid.size.width - 1)) let saneColumn = max(0, min(cursorPosition.column, self.grid.size.width - 1))
@ -104,6 +97,10 @@ extension NeoVimView {
} }
fileprivate func drawCursor(context: CGContext) { fileprivate func drawCursor(context: CGContext) {
guard self.shouldDrawCursor else {
return
}
context.saveGState() context.saveGState()
defer { context.restoreGState() } defer { context.restoreGState() }
@ -129,6 +126,8 @@ extension NeoVimView {
// FIXME: take ligatures into account (is it a good idea to do this?) // FIXME: take ligatures into account (is it a good idea to do this?)
let rowRun = RowRun(row: cursorRegion.top, range: cursorRegion.columnRange, attrs: attrs) let rowRun = RowRun(row: cursorRegion.top, range: cursorRegion.columnRange, attrs: attrs)
self.draw(rowRun: rowRun, in: context) self.draw(rowRun: rowRun, in: context)
self.shouldDrawCursor = false
} }
fileprivate func drawBackground(positions: [CGPoint], background: Int, in context: CGContext) { fileprivate func drawBackground(positions: [CGPoint], background: Int, in context: CGContext) {

View File

@ -82,7 +82,7 @@ extension NeoVimView {
public func setMarkedText(_ aString: Any, selectedRange: NSRange, replacementRange: NSRange) { public func setMarkedText(_ aString: Any, selectedRange: NSRange, replacementRange: NSRange) {
if self.markedText == nil { if self.markedText == nil {
self.markedPosition = self.grid.putPosition self.markedPosition = self.grid.position
} }
// eg -> hanja popup, cf comment for self.lastMarkedText // eg -> hanja popup, cf comment for self.lastMarkedText
@ -112,7 +112,7 @@ extension NeoVimView {
self.keyDownDone = true self.keyDownDone = true
// TODO: necessary? // TODO: necessary?
self.markForRender(row: self.grid.putPosition.row, column: self.grid.putPosition.column) self.markForRender(row: self.grid.position.row, column: self.grid.position.column)
} }
/// Return the current selection (or the position of the cursor with empty-length range). /// Return the current selection (or the position of the cursor with empty-length range).
@ -126,7 +126,7 @@ extension NeoVimView {
return NSRange(location: NSNotFound, length: 0) return NSRange(location: NSNotFound, length: 0)
} }
let result = NSRange(location: self.grid.singleIndexFrom(self.grid.putPosition), length: 0) let result = NSRange(location: self.grid.singleIndexFrom(self.grid.position), length: 0)
// self.logger.debug("\(#function): \(result)") // self.logger.debug("\(#function): \(result)")
return result return result
} }

View File

@ -31,7 +31,7 @@ extension NeoVimView {
self.grid.eolClear() self.grid.eolClear()
let putPosition = self.grid.putPosition let putPosition = self.grid.position
let region = Region(top: putPosition.row, let region = Region(top: putPosition.row,
bottom: putPosition.row, bottom: putPosition.row,
left: putPosition.column, left: putPosition.column,
@ -48,32 +48,8 @@ extension NeoVimView {
self.bridgeLogger.debug("pos: \(position), screen: \(screenCursor), " + self.bridgeLogger.debug("pos: \(position), screen: \(screenCursor), " +
"current-pos: \(currentPosition)") "current-pos: \(currentPosition)")
self.currentPosition = currentPosition self.markForRender(cellPosition: self.grid.position)
let curScreenCursor = self.grid.screenCursor
// Because neovim fills blank space with "Space" and when we enter "Space"
// we don't get the puts, thus we have to redraw the put position.
if self.usesLigatures {
self.markForRender(region: self.grid.regionOfWord(at: self.grid.putPosition))
self.markForRender(region: self.grid.regionOfWord(at: curScreenCursor))
self.markForRender(region: self.grid.regionOfWord(at: position))
self.markForRender(region: self.grid.regionOfWord(at: screenCursor))
} else {
self.markForRender(cellPosition: self.grid.putPosition)
// Redraw where the cursor has been till now, ie remove the current cursor.
self.markForRender(cellPosition: curScreenCursor)
if self.grid.isPreviousCellEmpty(curScreenCursor) {
self.markForRender(cellPosition: self.grid.previousCellPosition(curScreenCursor))
}
if self.grid.isNextCellEmpty(curScreenCursor) {
self.markForRender(cellPosition: self.grid.nextCellPosition(curScreenCursor))
}
self.markForRender(cellPosition: position)
self.markForRender(cellPosition: screenCursor)
}
self.grid.goto(position) self.grid.goto(position)
self.grid.moveCursor(screenCursor)
} }
gui.async { gui.async {
self.delegate?.cursor(to: currentPosition) self.delegate?.cursor(to: currentPosition)
@ -84,7 +60,6 @@ extension NeoVimView {
gui.async { gui.async {
self.bridgeLogger.debug(cursorModeShapeName(mode)) self.bridgeLogger.debug(cursorModeShapeName(mode))
self.mode = mode self.mode = mode
self.updateCursorWhenPutting(currentPosition: .zero, screenCursor: .zero)
} }
} }
@ -119,7 +94,7 @@ extension NeoVimView {
public func put(_ string: String, screenCursor: Position) { public func put(_ string: String, screenCursor: Position) {
gui.async { gui.async {
let curPos = self.grid.putPosition let curPos = self.grid.position
self.bridgeLogger.debug("\(curPos) -> \(string) <- screen: \(screenCursor)") self.bridgeLogger.debug("\(curPos) -> \(string) <- screen: \(screenCursor)")
self.grid.put(string) self.grid.put(string)
@ -133,8 +108,6 @@ extension NeoVimView {
} else { } else {
self.markForRender(cellPosition: curPos) self.markForRender(cellPosition: curPos)
} }
self.updateCursorWhenPutting(currentPosition: curPos, screenCursor: screenCursor)
} }
} }
@ -142,7 +115,7 @@ extension NeoVimView {
gui.async { gui.async {
self.bridgeLogger.debug("'\(markedText)' <- screen: \(screenCursor)") self.bridgeLogger.debug("'\(markedText)' <- screen: \(screenCursor)")
let curPos = self.grid.putPosition let curPos = self.grid.position
self.grid.putMarkedText(markedText) self.grid.putMarkedText(markedText)
self.markForRender(position: curPos) self.markForRender(position: curPos)
@ -151,8 +124,6 @@ extension NeoVimView {
if markedText.characters.count == 0 { if markedText.characters.count == 0 {
self.markForRender(position: self.grid.previousCellPosition(curPos)) self.markForRender(position: self.grid.previousCellPosition(curPos))
} }
self.updateCursorWhenPutting(currentPosition: curPos, screenCursor: screenCursor)
} }
} }
@ -164,14 +135,20 @@ extension NeoVimView {
self.grid.unmarkCell(position) self.grid.unmarkCell(position)
self.markForRender(position: position) self.markForRender(position: position)
self.markForRender(screenCursor: self.grid.screenCursor)
} }
} }
public func flush() { public func flush() {
gui.async { gui.async {
self.bridgeLogger.debug("-----------------------------") self.bridgeLogger.hr()
self.shouldDrawCursor = true
if self.usesLigatures {
self.markForRender(region: self.grid.regionOfWord(at: self.grid.position))
} else {
self.markForRender(cellPosition: self.grid.position)
}
} }
} }
@ -219,7 +196,7 @@ extension NeoVimView {
public func autoCommandEvent(_ event: NeoVimAutoCommandEvent, bufferHandle: Int) { public func autoCommandEvent(_ event: NeoVimAutoCommandEvent, bufferHandle: Int) {
gui.async { gui.async {
// self.bridgeLogger.debug("\(neoVimAutoCommandEventName(event)) -> \(bufferHandle)") self.bridgeLogger.debug("\(neoVimAutoCommandEventName(event)) -> \(bufferHandle)")
if event == .BUFWINENTER || event == .BUFWINLEAVE { if event == .BUFWINENTER || event == .BUFWINLEAVE {
self.bufferListChanged() self.bufferListChanged()
@ -386,21 +363,6 @@ extension NeoVimView {
fileprivate func bufferListChanged() { fileprivate func bufferListChanged() {
self.delegate?.bufferListChanged() self.delegate?.bufferListChanged()
} }
fileprivate func updateCursorWhenPutting(currentPosition curPos: Position,
screenCursor: Position) {
if self.mode == .cmdline {
// When the cursor is in the command line, then we need this...
self.markForRender(cellPosition: self.grid.previousCellPosition(curPos))
self.markForRender(cellPosition: self.grid.nextCellPosition(curPos))
self.markForRender(screenCursor: self.grid.putPosition)
}
self.markForRender(screenCursor: screenCursor)
self.markForRender(cellPosition: self.grid.screenCursor)
self.grid.moveCursor(screenCursor)
}
} }
fileprivate let gui = DispatchQueue.main fileprivate let gui = DispatchQueue.main

View File

@ -184,6 +184,7 @@ public class NeoVimView: NSView,
var currentEmoji = "😎" var currentEmoji = "😎"
var _font = NeoVimView.defaultFont var _font = NeoVimView.defaultFont
var shouldDrawCursor = false
// MARK: - Private // MARK: - Private
fileprivate var _linespacing = NeoVimView.defaultLinespacing fileprivate var _linespacing = NeoVimView.defaultLinespacing