The attached patch seems to fix the worst parts of the positioning problem.
It adds the margin width to the ‘VisibleOriginInMain’ then subtracts it when horizontally scrolling. The setting of the margin width is moved earlier to ensure it is consistent - it may be better to make the margin read the ViewStyle::fixedColumnWidth instead of caching the value. I am still confused about what is occurring.
There is a problem with the patch that cursoring off the right doesn’t scroll at the correct point - the margin width likely needs to be taken into account there as well.
The attached patch seems to fix the worst parts of the positioning problem.I can confirm it works on my fresh 10.14 box.

scrollView.contentView.automaticallyAdjustsContentInsets = NO;
scrollView.contentView.contentInsets = NSEdgeInsetsZero;
NSRect frame = scrollView.contentView.frame;
frame.origin.x = 1. + (scrollView.rulersVisible ? scrollView.verticalRulerView.requiredThickness : 0.);
scrollView.contentView.frame = frame;
- (void) setMarginWidth: (int) width
{
if (marginView.ruleThickness != width)
{
marginView.marginWidth = width;
[marginView setRuleThickness:[marginView requiredThickness]];
NSRect frame = [[scrollView contentView] frame];
frame.origin.x = [scrollView rulersVisible] ? width : 0.;
[[scrollView contentView] setFrame:frame];
}
}
> Then whenever I made the ruler view visible, I repositioned the contentView like the pre-Mojave scroll view does:
>
> NSRect frame = scrollView.contentView.frame;
> frame.origin.x = 1. + (scrollView.rulersVisible ? scrollView.verticalRulerView.requiredThickness : 0.);
> scrollView.contentView.frame = frame;
The 1 above appears to be wrong - with dark mode there is a single dark pixel on the left.
NSScrollView is now automatically adjusting the contentInsets to allow the documentView to scroll under the ruler. So yes the problem is that origin of the clipView has moved to under the ruler.
This isn't exactly new to Mojave. If you used a full content window so your scrollView document could bleed into the titlebar, you run into the same kind of problem.
The solution is to use scrollRectToVisible when you click your button, or at any other time.
[self.scrollView.documentView scrollRectToVisible: NSZeroRect];
This method takes contentInsets into consideration and will do what you want.
Scintilla::Point ScintillaCocoa::GetVisibleOriginInMain() const
{
NSScrollView *scrollView = ScrollContainer();
NSRect contentRect = [[scrollView contentView] bounds];
return Point(static_cast<XYPOSITION>(contentRect.origin.x+scrollView.contentView.contentInsets.left),
static_cast<XYPOSITION>(contentRect.origin.y));
}
[clipView scrollToPoint: NSMakePoint(xOffset-clipView.contentInsets.left, contentRect.origin.y)];
This issue behaves as intended based on the following: For apps linked on macOS 10.14, the document of an NSScrollView can scroll under the associated horizontal and vertical NSRulerView or findBarView. This means that the NSClipView is sized and positioned under those accessories and that will be reflected in the clip view’s contentInsets. If you’re writing a document view class that observes the containing clip view’s size to determine its own size, take these contentInsets into account when you’re determining the document size to avoid being larger than the inset document area.
Since scrollToPoint does both x and y, the scrollToPoint call in SetVerticalScrollPos should be the same:
[clipView scrollToPoint: NSMakePoint(contentRect.origin.x-clipView.contentInsets.left, topLine * vs.lineHeight)];
void ScintillaCocoa::SetVerticalScrollPos()
{
NSScrollView *scrollView = ScrollContainer();
if (scrollView) {
NSRect visibleRect = [[scrollView documentView] visibleRect];
visibleRect.origin.y = topLine * vs.lineHeight;
[[scrollView documentView] scrollRectToVisible:visibleRect];
}
}
void ScintillaCocoa::SetHorizontalScrollPos()
{
PRectangle textRect = GetTextRectangle();
int maxXOffset = scrollWidth - static_cast<int>(textRect.Width());
if (maxXOffset < 0)
maxXOffset = 0;
if (xOffset > maxXOffset)
xOffset = maxXOffset;
NSScrollView *scrollView = ScrollContainer();
if (scrollView) {
NSClipView * clipView = [scrollView contentView];
NSRect visibleRect = [[scrollView documentView] visibleRect];
visibleRect.origin.x = xOffset - clipView.contentInsets.left;
[[scrollView documentView] scrollRectToVisible:visibleRect];
}
MoveFindIndicatorWithBounce(NO);
}
property CGFloat reservedThicknessForAccessoryView;
// This indicates to the ruler how much room it should leave for the accessory view. Default is 0.0. If you expect that a view in your document view will put an accessory view in the ruler, you can set this to make room fror it from the start. If an accessory view is ever set for the ruler, and space was not reserved for it or it is bigger than the space reserved, the ruler grows the reserved space to be big enough and retiles the scroll view. If you know that several different accessory views will be used it is best to set this to the height of the tallest one for horizontal rulers or the width of the widest one for vertical rulers. If the reserved thickness is larger than an actual accessory view set into the ruler, the accessory view is centered in the thickness.
I might be wrong, but the behavior change in macOS 10.14, that shows a bouncing effect of the contentView from left to right, contrary to macOS 10.13 or lower, is constricted to a small bounce offset, suggesting the RulerView has somehow a limited width.
Alfred van Hoek:
> I think that the problem relates to not define an accessoryView to the RulerView: I quote:
Accessory views are optional and not every ruler view has one. Scintilla never defines an accessory view so the thickness of the accessory view is always 0. The accessory view area seems to be treated just the same as the rest of the ruler so its probably not worthwhile trying variants like a 0-width ruler with an accessory view showing the margins. Looking at other apps, the accessory view doesn’t scroll with the ruler.
> I might be wrong, but the behavior change in macOS 10.14, that shows a bouncing effect of the contentView from left to right, contrary to macOS 10.13 or lower, is constricted to a small bounce offset, suggesting the RulerView has somehow a limited width.
I’m not seeing that - the left-right bounce seems as large as before and doesn’t depend on the margins that are visible.
- (void)tile
{
[super tile];
NSRect frame = self.contentView.frame;
frame.origin.x = self.verticalRulerView.requiredThickness;
frame.size.width -= frame.origin.x;
self.contentView.frame = frame;
}- (id) initWithFrame: (NSRect) frame
{
self = [super initWithFrame:frame];
if (self)
{
mContent = [[[[[self class] contentViewClass] alloc] initWithFrame:NSZeroRect] autorelease];
mContent.owner = self;
// Initialize the scrollers but don't show them yet.
// Pick an arbitrary size, just to make NSScroller selecting the proper scroller direction
// (horizontal or vertical).
NSRect scrollerRect = NSMakeRect(0, 0, 100, 10);
scrollView = (NSScrollView *)[[[SciScrollView alloc] initWithFrame: scrollerRect] autorelease];
scrollView.contentView.automaticallyAdjustsContentInsets = NO;
scrollView.contentView.contentInsets = NSEdgeInsetsMake(0., 0., 0., 0.);
[scrollView setDocumentView: mContent];That seems reasonable. Can you please post a diff/patch to make it easy to add.
Xcode 10 was released recently and there were some warnings when building Scintilla.
One warning that appears is “Enable Base Internationalization”. This refers to a particular way of doing localization but currently Scintilla doesn’t do any localization or even have the .xib or .storyboard files that are the focus of Base Internationalization. A .xib file could be added and the “Use Base Internationalization” check box ticked. There are some literal strings provided for accessibility (“Scintilla”, “Scintilla Margin”, “source code editor”) that could potentially be localized into other languages.
knownRegions = ( English, Japanese, French, German, Base, );