Skip to content

Commit 37f6283

Browse files
committed
Attempt at fixing a display issue on 10.14 by replacing a hack with another hack (#3214)
1 parent d78907b commit 37f6283

File tree

1 file changed

+47
-11
lines changed

1 file changed

+47
-11
lines changed

Source/SPTableView.m

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ - (BOOL)cancelRowEditing;
4040

4141
@end
4242

43+
@interface NSTableView (ApplePrivate)
44+
- (BOOL)_allowTabbingIntoCells;
45+
@end
46+
4347
@interface SPTableView ()
4448

4549
- (void)_doubleClickAction;
@@ -154,19 +158,51 @@ - (BOOL)acceptsFirstResponder
154158
}
155159

156160
/**
157-
* On becomeFirstResponder, if editing is disabled, override the super and just
158-
* display instead; this prevents the selected cell from automatically editing
159-
* if the table is backtabbed to.
161+
* THIS IS A HACK!
162+
*
163+
* When you do the following steps:
164+
*
165+
* b.1) Have "Tab all controls" enabled in System Prefs
166+
* b.2) Click on a row in the table view
167+
* b.3) Set the focus to the next responder after the table view (e.g. by pressing "tab")
168+
* b.4) Set the focus back to the table view by pressing "shift"+"tab"
169+
*
170+
* Cocoa would automatically start editing the table cell, which is not always desirable.
171+
*
172+
* Previously we overrode -becomeFirstResponder, which is the call ultimately triggering the
173+
* edit. However, when looking at the implementation of -becomeFirstResponder it becomes clear
174+
* that Apple has not intended for developers to override this method or provided any other way
175+
* to influence the behaviour and since our overridden method would omit some internal method calls
176+
* this caused other issues (#3214).
177+
*
178+
* We could still solve this by overriding it and hooking another of the three public API
179+
* calls it makes:
180+
* a) -[NSTableView acceptsFirstResponder]
181+
* b) -[NSTableColumn isEditable]
182+
* c) -[NSTableView editColumn:row:withEvent:select:]
183+
*
184+
* But this would still be a hack as we would be relying on implementation internals and
185+
* each methods has some problem:
186+
*
187+
* We can't use a) because it is called too early and won't trigger a necessary
188+
* drawing update, leaving us with the same issue that we tried to solve here.
189+
*
190+
* While c) looks to be the better method to cancel an edit, it actually is too
191+
* late and will cause erratic behaviour with the focus ring.
192+
*
193+
* Which leaves b), which luckily is a primitive ivar setter
194+
* and not an observable property and doesn't trigger any side effects like
195+
* rerendering (tested with 10.9 and 10.14). BUT: Up to getting to the point where this
196+
* method is called, a lot of decision making is involved to determine the column to call
197+
* this on and it won't be called for view-based table views and group rows (full width cells)
198+
* anyway.
199+
*
200+
* So if we have to use a hack anyway, let's just go with the easiest thing and override
201+
* the internal method call that can cancel the edit right where we want it to (at least in 10.9 - 10.4).
160202
*/
161-
- (BOOL)becomeFirstResponder
203+
- (BOOL)_allowTabbingIntoCells
162204
{
163-
if (tabEditingDisabled) {
164-
[self display];
165-
166-
return YES;
167-
}
168-
169-
return [super becomeFirstResponder];
205+
return (tabEditingDisabled ? NO : [super _allowTabbingIntoCells]);
170206
}
171207

172208
- (void)keyDown:(NSEvent *)theEvent

0 commit comments

Comments
 (0)