-
Notifications
You must be signed in to change notification settings - Fork 191
Description
Describe the bug
We are having our own framework which can render swt/jface user interfaces based on EMF models.
We are using databinding everywhere, also for table and tree viewers.
Additionally we interfere in table manipulation, like remove.
And I guess the following bug can only happen in due to our framework
The bug seems to only occur on MacOS, but not on every Mac machine. For example a colleague of mine get's the issue, while I cannot reproduce it on my machine.
What happens?
If a row from a tableviewer is removed, the table viewer is corrupted afterwards (refer to the first corrupted line):
This is the error in the console:
org.eclipse.swt.SWTException: Widget is disposed at org.eclipse.swt.SWT.error(SWT.java:4950) at org.eclipse.swt.SWT.error(SWT.java:4865) at org.eclipse.swt.SWT.error(SWT.java:4836) at org.eclipse.swt.widgets.Widget.error(Widget.java:854) at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:633) at org.eclipse.swt.widgets.Widget.getData(Widget.java:920) at org.eclipse.jface.viewers.AbstractTableViewer.setSelectionToWidget(AbstractTableViewer.java:930) at org.eclipse.jface.viewers.StructuredViewer.setSelectionToWidget(StructuredViewer.java:1709) at org.eclipse.jface.viewers.StructuredViewer.preservingSelection(StructuredViewer.java:1402) at org.eclipse.jface.viewers.StructuredViewer.preservingSelection(StructuredViewer.java:1356) at org.eclipse.jface.viewers.AbstractTableViewer.remove(AbstractTableViewer.java:839) at org.eclipse.jface.viewers.TableViewer.remove(TableViewer.java:440) at org.eclipse.jface.viewers.AbstractTableViewer.remove(AbstractTableViewer.java:859) at org.eclipse.jface.internal.databinding.viewers.TableViewerUpdater.remove(TableViewerUpdater.java:43) at org.eclipse.jface.databinding.viewers.ObservableListContentProvider$Impl$2.handleRemove(ObservableListContentProvider.java:134) at org.eclipse.core.databinding.observable.list.ListDiff.accept(ListDiff.java:152) at org.eclipse.jface.databinding.viewers.ObservableListContentProvider$Impl.handleListChange(ObservableListContentProvider.java:126) at org.eclipse.core.databinding.observable.list.ListChangeEvent.dispatch(ListChangeEvent.java:75) at org.eclipse.core.databinding.observable.ChangeManager.fireEvent(ChangeManager.java:122) at org.eclipse.core.databinding.observable.list.ObservableList.fireListChange(ObservableList.java:84) at org.eclipse.core.databinding.observable.list.WritableList.remove(WritableList.java:174) at table.bug.DataboundTableViewerDialog.remove(DataboundTableViewerDialog.java:149) at org.eclipse.swt.events.SelectionListener$1.widgetSelected(SelectionListener.java:83) at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:290) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:91) at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4671) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1657) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1680) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1665) at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:1394) at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4438) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:4014) at org.eclipse.jface.window.Window.runEventLoop(Window.java:819) at org.eclipse.jface.window.Window.open(Window.java:799) at table.bug.DataboundTableViewerDialog.main(DataboundTableViewerDialog.java:45)
The table item seems to be disposed.
What I found out:
The actual error is occurring here but the error could only be seen in the debugger, not in the error log or console:
Thread [main] (Suspended (breakpoint at line 854 in Widget))
TableItem(Widget).error(int) line: 854
36 collapsed frames
TableItem(Widget).checkWidget() line: 633
TableItem(Widget).getData() line: 920
TableViewerRow.getElement() line: 172
TableViewerRow(ViewerRow).getCell(int) line: 212
TableViewerFocusCellManager.getFocusCell() line: 107
SWTFocusCellManager$1.getName(AccessibleEvent) line: 160
Accessible.getTitleAttribute(int) line: 1919
Accessible.internal_accessibilityIsIgnored(int) line: 1417
Table(Composite).accessibilityIsIgnored(long, long) line: 194
Display.windowProc(long, long) line: 6177
OS.objc_msgSendSuper(objc_super, long, long, boolean) line: not available [native method]
Table(Widget).selectRowIndexes_byExtendingSelection(long, long, long, boolean) line: 1634
Table.selectRowIndexes_byExtendingSelection(long, long, long, boolean) line: 3323
Display.windowProc(long, long, long, long) line: 6757
OS.objc_msgSend(long, long, long, boolean) line: not available [native method]
SWTTableView(NSTableView).selectRowIndexes(NSIndexSet, boolean) line: 158
Table.select(int[], int, boolean) line: 2549
Table.fixSelection(int, boolean) line: 1321
Table.remove(int[]) line: 2340
TableViewer.doRemove(int[]) line: 295
TableViewer(AbstractTableViewer).internalRemove(Object[]) line: 784
TableViewer(AbstractTableViewer).lambda$1(Object[]) line: 839
Lambda.run() line: not available
TableViewer(StructuredViewer).preservingSelection(Runnable, boolean) line: 1395
TableViewer(StructuredViewer).preservingSelection(Runnable) line: 1356
TableViewer(AbstractTableViewer).remove(Object[]) line: 839
TableViewer.remove(Object[]) line: 440
TableViewer(AbstractTableViewer).remove(Object) line: 859
TableViewerUpdater<E>.remove(E, int) line: 43
ObservableListContentProvider$Impl$2.handleRemove(int, E) line: 134
Diffs$8(ListDiff<E>).accept(ListDiffVisitor<? super E>) line: 152
ObservableListContentProvider$Impl<E>.handleListChange(ListChangeEvent<? extends E>) line: 126
ListChangeEvent<E>.dispatch(IObservablesListener) line: 75
WritableList<E>(ChangeManager).fireEvent(ObservableEvent) line: 122
WritableList<E>(ObservableList<E>).fireListChange(ListDiff<E>) line: 84
WritableList<E>.remove(int) line: 174
DataboundTableViewerDialog.remove(SelectionEvent) line: 148
Lambda.accept(Object) line: not available
12 collapsed frames
DataboundTableViewerDialog.main(String...) line: 45```
The `Accessible` class calls `SWTFocusCellManager` to get a name, unfortunately on the disposed table item which causes an SWT.error. That's why `org.eclipse.swt.Table` class cannot remove the item from the `items` attribute in its `remove(int[] indices)` method.
<img width="813" height="698" alt="Image" src="https://github.com/user-attachments/assets/e10165f1-0048-425a-ac2f-28b68895bb07" />
During removal of a table object we call `Display.asyncExec` and I have the impression that on my colleagues machine the `Accessible` class reacts too early. Additionally some accessibility settings on her Mac might have influence as on my machine `SWTFocusCellManager` is not called during deletion.
I have a PDE plugin project attached. Simply run `DataboundTableViewerDialog` as main application. The databinding is done similar as in our framework.
The removal is done by deleting all entries from the model and afterwards re-add the whole list except the removed. During this call, we do some `Display.asyncExec`.
If you execute the example and the viewer looks like in the screenshot above and you get an error in the console, you are "lucky" and can reproduce the issue.
If not, it works like on my machine.
I know this is really complicated and may be hard to reproduce. But I wonder if SWTFocusCellManager should be able to handle disposed table items if it is called too early.
This is exactly the workaround in our framework. We have overwritten `SWTFocusCellManager.getName` and only call super of the table item is not disposed.