As of OSX 10.7, Apple suggests using drawFocusRingMask
and focusRingMaskBounds
methods as the way to draw a focus ring around NSView based objects instead of how it was done previously in 10.6 (using NSSetFocusRingStyle()
in drawRect:
). (see release notes).
Tested on OSX 10.10 :
I have an NSTextView descendent which implements basic focus ring drawing as suggested:
- (void)drawFocusRingMask {
NSRectFill([self bounds]);
}
- (NSRect)focusRingMaskBounds {
return [self bounds];
}
This NSTextView is programmatically added directly to the content view (without any scroll views).
This works well for the most part, however, when using scaleUnitSquareToSize: to scale the NSTextView, the focus ring drawn is completely incorrect.
So calling:
[textView scaleUnitSquareToSize:NSMakeSize(1.5, 1.5)];
Looks like this:
Scaling it further up or down results in even more skew of the focus ring rect. Reseting the scale of the NSTextView back to {1.0, 1.0} causes the focus ring to draw correctly again.
I assume this is some sort of a bug in the focus ring code. It seems to preform transformations on the graphics context used for drawing the focus ring before calling drawFocusRingMask
/ focusRingMaskBounds
(internal class _NSAutomaticFocusRing
is responsible for this).
Any idea how to fix this? Should I find a way to transform the context to the proper coordinates (so far without success)? Or is there any other way to force the focus ring to behave properly?
I have struggled with this bug for a long time. Here's a solution that seems to work:
Sub-class the
NSTextField
orNSTextView
so that you are instantiating, e.g., aZoomableTextField
. Override itsdrawFocusRingMask:
method, so that the override does nothing:Then in the zoomable superview in which a
ZoomableTextField
is embedded, inside the superview'sdrawRect:
method, call a new method of theZoomableTextField
,drawPossibleFocus
, which looks like this: