Show a fat iOS-Style Insertion Point in NSTextView
I have no clue why my previous attempts at customizing drawInsertionPoint(in:color:turnedOn:)
always produced visual glitches. I really tried a lot of different ways.
But it turns out you don’t have to do that much, really:
class MyTextView: NSTextView {
var caretSize: CGFloat = 4
open override func drawInsertionPoint(in rect: NSRect, color: NSColor, turnedOn flag: Bool) {
var rect = rect
rect.size.width = caretSize
super.drawInsertionPoint(in: rect, color: color, turnedOn: flag)
}
open override func setNeedsDisplay(_ rect: NSRect, avoidAdditionalLayout flag: Bool) {
var rect = rect
let width = rect.size.width + insertionPointWidth - 1
rect.size.width = max(rect.size.width, width) // Updated 2022-08-29
super.setNeedsDisplay(rect, avoidAdditionalLayout: flag)
}
}
Adapted to Swift from a Gist by koenbok.
That’s all it takes. Marvelous!
Update: So it turns out that the drawing works just fine in a test project, but I end up with 1px-wide insertion points/carets/I-beams when I click with the mouse or press up/down arrow keys. Left and right work fine. I wonder what’s wrong with this.
Update 2022-08-29: I should’ve added more context to my last update because I eventually shipped more or less this exact approach without trouble, though I’m limiting rect.size.width
in production. Maybe that was it? Users of The Archive enjoy fat carets for more than 4 years now without trouble. – Note that Ryan posted a link to a Gist with similar code in the comments.