Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion source/apphelpers.pas
Original file line number Diff line number Diff line change
Expand Up @@ -3528,7 +3528,11 @@ procedure TClipboardHelper.SetTryAsText(AValue: String);
procedure TWinControlHelper.TrySetFocus;
begin
try
if Enabled and CanFocus then
// CanSetFocus - unlike CanFocus - also tests the parent form itself, so
// this avoids the "[TCustomForm.SetFocus] ... Can not focus" exception
// which SetFocus raises on a hidden or disabled form, e.g. while a modal
// form is closing. See issue 2433.
if CanSetFocus then
SetFocus
else
MainForm.LogSQL(Self.Name + ': either disabled or cannot focus', lcDebug);
Expand Down
6 changes: 6 additions & 0 deletions source/connections.pas
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,12 @@ procedure Tconnform.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
// Modifications? Ask if they should be saved.
FinalizeModifications(CanClose);
// End a pending inline rename while the form is still visible and active.
// Otherwise the edit link tries to restore the focus during form teardown,
// which raises "[TCustomForm.SetFocus] ... Can not focus" on macOS.
// See issue #2433.
if CanClose and ListSessions.IsEditing then
ListSessions.CancelEditNode;
end;


Expand Down
5 changes: 5 additions & 0 deletions source/grideditlinks.pas
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,11 @@ destructor TBaseGridEditorLink.Destroy;
NewNode: PVirtualNode;
DoPrev: Boolean;
begin
// Drop end/cancel calls which are still queued via DoEndEdit/DoCancelEdit.
// They would fire after this link - and possibly the tree or its form - is
// already destroyed, e.g. when the session manager is cancelled while a
// session rename is active. See issue #2433.
Application.RemoveAsyncCalls(Self);
ActiveGridEditor := nil;
if Assigned(FMainControl) then begin
FMainControl.WindowProc := FOldWindowProc;
Expand Down
18 changes: 18 additions & 0 deletions source/main.pas
Original file line number Diff line number Diff line change
Expand Up @@ -1776,11 +1776,29 @@ procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
CanClose := not (ActiveObjectEditor.DeInit in [mrAbort, mrCancel]);
end;

{$IFDEF DARWIN}
type
// Grants access to the protected DestroyHandle, see workaround in FormDestroy
TWinControlAccess = class(TWinControl);
{$ENDIF}

procedure TMainForm.FormDestroy(Sender: TObject);
begin
// Discard a possibly queued AsyncRepaintGrid call
Application.RemoveAsyncCalls(Self);

{$IFDEF DARWIN}
// Work around a SynEdit bug which crashes the app on every shutdown on Cocoa:
// TSynBaseCompletionForm.Destroy first frees its SizeDrag panel and then
// destroys the window handle. The Cocoa widgetset queries Focused while
// destroying the handle, and the Focused override dereferences the already
// freed SizeDrag ("EObjectCheck: Object reference is Nil"). Destroying the
// handle here, while the form is still intact, makes the destructor skip
// that path. See issue 2433.
if SynCompletionProposal.TheForm.HandleAllocated then
TWinControlAccess(SynCompletionProposal.TheForm).DestroyHandle;
{$ENDIF}

// Destroy dialogs
FreeAndNil(FSearchReplaceDialog);

Expand Down
Loading