From d0d7033f6384384c59f0be9ad4ceb9a8cbd3591e Mon Sep 17 00:00:00 2001 From: daboe01 Date: Sat, 7 Mar 2026 14:53:44 +0100 Subject: [PATCH 1/2] Fixed: timing of CPControlTextDidBeginEditingNotification (#1941) --- AppKit/CPTextField.j | 6 ++++++ AppKit/CPTokenField.j | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j index 03416af31..741863b6d 100644 --- a/AppKit/CPTextField.j +++ b/AppKit/CPTextField.j @@ -1131,6 +1131,12 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); if (![self isEnabled] || !([self isEditable] || [self isSelectable])) return; + if ([self isEditable] && !_isEditing) + { + _isEditing = YES; + [self textDidBeginEditing:[CPNotification notificationWithName:CPControlTextDidBeginEditingNotification object:self userInfo:nil]]; + } + // CPTextField uses an HTML input element to take the input so we need to // propagate the dom event so the element is updated. This has to be done // before interpretKeyEvents: though so individual commands have a chance diff --git a/AppKit/CPTokenField.j b/AppKit/CPTokenField.j index 61ed7d3dd..1de22bebd 100644 --- a/AppKit/CPTokenField.j +++ b/AppKit/CPTokenField.j @@ -453,8 +453,8 @@ CPTokenFieldDeleteButtonType = 1; { [_tokenScrollView documentView]._DOMElement.appendChild(element); - //post CPControlTextDidBeginEditingNotification - [self textDidBeginEditing:[CPNotification notificationWithName:CPControlTextDidBeginEditingNotification object:self userInfo:nil]]; + // Removed so CPTokenField doesn't fire the notification the moment it becomes the first responder, but instead defers to the first keystroke, just like Cocoa (see keyDown: in CPTextField). + // [self textDidBeginEditing:[CPNotification notificationWithName:CPControlTextDidBeginEditingNotification object:self userInfo:nil]]; [[CPRunLoop mainRunLoop] performBlock:function() { From 4fd99d2c52b377fc74ff047d7a019e390882c439 Mon Sep 17 00:00:00 2001 From: daboe01 Date: Sat, 14 Mar 2026 19:25:50 +0100 Subject: [PATCH 2/2] fixed: tokenfield CPControlTextDidBeginEditingNotification notification --- AppKit/CPTokenField.j | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/AppKit/CPTokenField.j b/AppKit/CPTokenField.j index 1de22bebd..71fcdde9a 100644 --- a/AppKit/CPTokenField.j +++ b/AppKit/CPTokenField.j @@ -349,6 +349,12 @@ CPTokenFieldDeleteButtonType = 1; if (theBinding) [theBinding reverseSetValueFor:@"objectValue"]; + if (!_isEditing) + { + _isEditing = YES; + [self textDidBeginEditing:[CPNotification notificationWithName:CPControlTextDidBeginEditingNotification object:self userInfo:nil]]; + } + [self textDidChange:[CPNotification notificationWithName:CPControlTextDidChangeNotification object:self userInfo:nil]]; _shouldNotifyTarget = YES; @@ -498,6 +504,8 @@ CPTokenFieldDeleteButtonType = 1; [self _resignFirstKeyResponder]; + _isEditing = NO; + if (_shouldNotifyTarget) { _shouldNotifyTarget = NO; @@ -1032,6 +1040,16 @@ CPTokenFieldDeleteButtonType = 1; CPTokenFieldTextDidChangeValue = [self stringValue]; #endif + // Has to be enabled, and it also has to be editable or selectable. + if (![self isEnabled] || !([self isEditable] || [self isSelectable])) + return; + + if ([self isEditable] && !_isEditing) + { + _isEditing = YES; + [self textDidBeginEditing:[CPNotification notificationWithName:CPControlTextDidBeginEditingNotification object:self userInfo:nil]]; + } + // Leave the default _propagateCurrentDOMEvent setting in place. This might be YES or NO depending // on if something that could be a browser shortcut was pressed or not, such as Cmd-R to reload. // If it was NO we want to leave it at NO however and only enable it in insertText:. This is what