@@ -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