Skip to content

Fix hang and wrong check states in data grid column selection on macOS - #2559

Merged
ansgarbecker merged 1 commit into
HeidiSQL:lazarusfrom
twinn1013:fix-column-selection-macos
Jul 23, 2026
Merged

Fix hang and wrong check states in data grid column selection on macOS#2559
ansgarbecker merged 1 commit into
HeidiSQL:lazarusfrom
twinn1013:fix-column-selection-macos

Conversation

@twinn1013

Copy link
Copy Markdown
Collaborator

Fixes #2554

Debugged with lldb on an M-series Mac. There were two separate bugs in the column selection popup, both fixed here:

1. The reported hang (double-free of FCheckedColumns)

Clicking OK closes the popup, which frees FCheckedColumns in FormClose. But the form itself is only released deferred (caFree), and the grid reload triggered by OK makes the main window key again while the popup object still exists. The LCL then sends CM_DEACTIVATE to the popup → FormDeactivatebtnCancelClickClose runs a second time → FCheckedColumns.Free on the already freed list. The resulting access violation raises the crash dialog with ShowModal inside the data grid's paint cycle, where nothing can be drawn anymore - the app freezes with an invisible modal dialog.

Backtrace of the crash (captured with lldb, trimmed):
frame #1: SYSTEM$$TOBJECT$$$FREE
frame #2: TFRMCOLUMNSELECTION$$$FORMCLOSE ← 2nd time
frame #5: TFRMCOLUMNSELECTION$$$BTNCANCELCLICK
frame #6: TFRMCOLUMNSELECTION$$$FORMDEACTIVATE
frame #14: TSCREEN$$$SETFOCUSEDFORM
frame #23: -[TCocoaWindow windowDidBecomeKey:]
frame #31: -[NSWindow makeKeyWindow]
frame #38: APPHELPERS$$$TRYSETFOCUS
frame #39: TMAINFORM$__$$_DATAGRIDBEFOREPAINT ← grid reload after OK

Fix: free FCheckedColumns in FormDestroy, which runs exactly once. TApplication.ReleaseComponent already tolerates the duplicate Release, so the second close pass is harmless otherwise.

2. Checked columns were applied wrongly (stale ItemIndex)

After fixing the hang, selecting e.g. 3 columns still showed only 1 in the grid. chklistColumnsClickCheck used chklistColumns.ItemIndex to detect the toggled item. On Cocoa the checkbox is an NSButton inside the table row, and its action fires before the table selection is updated - so ItemIndex still points at the previously clicked row, or is -1. Verified with lldb: clicking checkboxes of rows 0, 2, 1 delivered LM_CHANGED for rows 0, 2, 1 while selectedRow was -1, 0, 4 at those moments - the internal list diverged from the visible check marks on every click.

Fix: sync the check states of all currently displayed items into FCheckedColumns instead of guessing via ItemIndex. Items hidden by the filter box are not touched, so filtering still works, and behavior on Windows is unchanged (no ifdefs).

Tested on macOS 15 (Apple Silicon): the reported hang scenario, multiple checkbox clicks without/with row selection changes in between, select/deselect all, sorting and filtering.

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.
@twinn1013 twinn1013 self-assigned this Jul 23, 2026
@ansgarbecker
ansgarbecker merged commit 6c5b66c into HeidiSQL:lazarus Jul 23, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants