Skip to content

Commit 6c5b66c

Browse files
twinn1013ansgarbecker
authored andcommitted
fix: hang and wrong check states in data grid column selection on macOS
Fixes the reported hang (issue 2554): closing the column selection popup with OK could run FormClose twice on macOS, freeing FCheckedColumns two times. The resulting access violation raised the crash dialog inside a paint cycle, freezing the application. FCheckedColumns is now freed in FormDestroy, which runs exactly once. While verifying that fix, a second bug in the same popup showed up: checked columns were not applied correctly to the grid. The click handler used ItemIndex to detect the toggled item, but on Cocoa the check event fires before the list selection is updated, so the wrong item was added or removed. The handler now syncs the check states of all displayed items instead.
1 parent 4555274 commit 6c5b66c

1 file changed

Lines changed: 14 additions & 12 deletions

File tree

source/column_selection.pas

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -150,20 +150,20 @@ procedure TfrmColumnSelection.editFilterButtonClick(Sender: TObject);
150150
}
151151
procedure TfrmColumnSelection.chklistColumnsClickCheck(Sender: TObject);
152152
var
153-
i : Integer;
153+
i, CheckedIndex : Integer;
154154
AllSelected, NoneSelected : Boolean;
155-
FocusedItem: String;
156-
FocusedItemIndex: Integer;
157155
begin
158-
// Add or remove clicked item from list
159-
if chklistColumns.ItemIndex > -1 then begin
160-
FocusedItem := chklistColumns.Items[chklistColumns.ItemIndex];
161-
if chklistColumns.Checked[chklistColumns.ItemIndex] then begin
162-
FCheckedColumns.Add(FocusedItem)
156+
// Sync check states of all displayed items into FCheckedColumns. Using
157+
// ItemIndex to detect the clicked item would be wrong on macOS, where the
158+
// check event fires before the list selection is updated. See issue 2554.
159+
for i:=0 to chklistColumns.Items.Count-1 do begin
160+
CheckedIndex := FCheckedColumns.IndexOf(chklistColumns.Items[i]);
161+
if chklistColumns.Checked[i] then begin
162+
if CheckedIndex = -1 then
163+
FCheckedColumns.Add(chklistColumns.Items[i]);
163164
end else begin
164-
FocusedItemIndex := FCheckedColumns.IndexOf(FocusedItem);
165-
if FocusedItemIndex > -1 then
166-
FCheckedColumns.Delete(FocusedItemIndex);
165+
if CheckedIndex > -1 then
166+
FCheckedColumns.Delete(CheckedIndex);
167167
end;
168168
end;
169169

@@ -225,6 +225,7 @@ procedure TfrmColumnSelection.FormDestroy(Sender: TObject);
225225
begin
226226
AppSettings.WriteInt(asColumnSelectorWidth, ScaleFormToDesign(Width));
227227
AppSettings.WriteInt(asColumnSelectorHeight, ScaleFormToDesign(Height));
228+
FCheckedColumns.Free;
228229
end;
229230

230231

@@ -243,8 +244,9 @@ procedure TfrmColumnSelection.FormDeactivate(Sender: TObject);
243244
procedure TfrmColumnSelection.FormClose(Sender: TObject; var Action:
244245
TCloseAction);
245246
begin
247+
// FormClose can run twice when the form is closed by OK and afterwards
248+
// deactivated - free FCheckedColumns in FormDestroy only. See issue 2554.
246249
Action := caFree;
247-
FCheckedColumns.Free;
248250
end;
249251

250252

0 commit comments

Comments
 (0)