cocoa: restore readonly functionality (#34696). Adding the code preventing the application from locking up on read-only mode change.

git-svn-id: trunk@59919 -
This commit is contained in:
dmitry 2018-12-28 03:36:54 +00:00
parent c0ff23d982
commit 92e510d650
2 changed files with 58 additions and 1 deletions

View File

@ -141,7 +141,12 @@ type
TCocoaFieldEditor = objcclass(NSTextView)
public
// This flag is used to hack an infinite loop
// when switching "editable" (readonly) mode of NSTextField
// see TCocoaWSCustomEdit.SetReadOnly
goingReadOnly: Boolean;
function lclGetCallback: ICommonCallback; override;
function becomeFirstResponder: Boolean; override;
// mouse
procedure keyDown(event: NSEvent); override;
procedure mouseDown(event: NSEvent); override;
@ -593,6 +598,12 @@ begin
else Result := nil;
end;
function TCocoaFieldEditor.becomeFirstResponder: Boolean;
begin
if goingReadOnly then Result := false
else Result:=inherited becomeFirstResponder;
end;
procedure TCocoaFieldEditor.keyDown(event: NSEvent);
begin
if event.keyCode = kVK_Return then

View File

@ -977,8 +977,54 @@ end;
class procedure TCocoaWSCustomEdit.SetReadOnly(const ACustomEdit: TCustomEdit; NewReadOnly: boolean);
var
lHandle: TCocoaTextField;
w : NSWindow;
t : NSText;
isFocused: Boolean;
r : Boolean;
b : Boolean;
rsp : NSResponder;
ed : TCocoaFieldEditor;
begin
// NSTextField(ACustomEdit.Handle).setEditable(not NewReadOnly);
lHandle := GetTextField(ACustomEdit);
if not Assigned(lHandle) then Exit;
ed := nil; //if lHandle is "focused" then ed would be <> nil
w := lHandle.window;
if not Assigned(w) then t := nil
else begin
rsp := w.firstResponder;
if (Assigned(rsp)) and (rsp.isKindOfClass(TCocoaFieldEditor)) then
begin
ed := TCocoaFieldEditor(rsp);
if (NSObject(ed.delegate) = lHandle) then
begin
ed.retain;
// the hack is needed to prevent infinite loop
// on switching editable (ReadOnly) status.
// without prevention of Editor focusing, AppKit goes into an infinite loop:
// AppKit`-[_NSKeyboardFocusClipView removeFromSuperview] + 55
// AppKit`-[NSWindow endEditingFor:] + 429
// AppKit`-[NSView removeFromSuperview] + 78
// AppKit`-[_NSKeyboardFocusClipView removeFromSuperview] + 55
// AppKit`-[NSWindow endEditingFor:] + 429
// AppKit`-[NSView removeFromSuperview] + 78
// AppKit`-[_NSKeyboardFocusClipView removeFromSuperview] + 55
ed.goingReadOnly := true;
end
else
ed := nil; // someone else is focused
end;
end;
lHandle.setEditable_(ObjCBool(not NewReadOnly));
lHandle.setSelectable_(1); // allow to select read-only text (LCL compatible)
if Assigned(ed) then begin
ed.goingReadOnly := false;
ed.release;
end;
end;
class procedure TCocoaWSCustomEdit.SetSelStart(const ACustomEdit: TCustomEdit; NewStart: integer);