Skip to content

Commit 09cfb68

Browse files
committed
[GTK3] Do not crash in SetData event
GTK 3.24.41 (Ubuntu 24) crashes when renderers are replaced during render. If replacement is postponed, the crash no longer happens. Fixes eclipse-platform#678.
1 parent e6588c2 commit 09cfb68

File tree

1 file changed

+66
-54
lines changed
  • bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets

1 file changed

+66
-54
lines changed

bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TreeItem.java

+66-54
Original file line numberDiff line numberDiff line change
@@ -1518,69 +1518,81 @@ public void setImage(int index, Image image) {
15181518
surface = imageList.getSurface(imageIndex);
15191519
pixbuf = ImageList.createPixbuf(surface);
15201520
}
1521-
1522-
int modelIndex = parent.columnCount == 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex;
1523-
long parentHandle = parent.handle;
1524-
long column = GTK.gtk_tree_view_get_column (parentHandle, index);
1525-
long pixbufRenderer = parent.getPixbufRenderer (column);
1526-
int [] currentWidth = new int [1];
1527-
int [] currentHeight= new int [1];
1528-
GTK.gtk_cell_renderer_get_fixed_size (pixbufRenderer, currentWidth, currentHeight);
1529-
if (!parent.pixbufSizeSet) {
1530-
if (image != null) {
1531-
int iWidth, iHeight;
1532-
if (DPIUtil.useCairoAutoScale()) {
1533-
iWidth = image.getBounds ().width;
1534-
iHeight = image.getBounds ().height;
1535-
} else {
1536-
iWidth = image.getBoundsInPixels ().width;
1537-
iHeight = image.getBoundsInPixels ().height;
1538-
}
1539-
if (iWidth > currentWidth [0] || iHeight > currentHeight [0]) {
1540-
GTK.gtk_cell_renderer_set_fixed_size (pixbufRenderer, iWidth, iHeight);
1541-
parent.pixbufSizeSet = true;
1542-
parent.pixbufHeight = iHeight;
1543-
parent.pixbufWidth = iWidth;
1544-
/*
1545-
* Feature in GTK: a Tree with the style SWT.VIRTUAL has
1546-
* fixed-height-mode enabled. This will limit the size of
1547-
* any cells, including renderers. In order to prevent
1548-
* images from disappearing/being cropped, we re-create
1549-
* the renderers when the first image is set. Fix for
1550-
* bug 480261.
1551-
*/
1552-
if ((parent.style & SWT.VIRTUAL) != 0) {
1521+
try {
1522+
int modelIndex = parent.columnCount == 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex;
1523+
long parentHandle = parent.handle;
1524+
long column = GTK.gtk_tree_view_get_column (parentHandle, index);
1525+
long pixbufRenderer = parent.getPixbufRenderer (column);
1526+
int [] currentWidth = new int [1];
1527+
int [] currentHeight= new int [1];
1528+
GTK.gtk_cell_renderer_get_fixed_size (pixbufRenderer, currentWidth, currentHeight);
1529+
if (!parent.pixbufSizeSet) {
1530+
if (image != null) {
1531+
int iWidth, iHeight;
1532+
if (DPIUtil.useCairoAutoScale()) {
1533+
iWidth = image.getBounds ().width;
1534+
iHeight = image.getBounds ().height;
1535+
} else {
1536+
iWidth = image.getBoundsInPixels ().width;
1537+
iHeight = image.getBoundsInPixels ().height;
1538+
}
1539+
if (iWidth > currentWidth [0] || iHeight > currentHeight [0]) {
1540+
GTK.gtk_cell_renderer_set_fixed_size (pixbufRenderer, iWidth, iHeight);
1541+
parent.pixbufSizeSet = true;
1542+
parent.pixbufHeight = iHeight;
1543+
parent.pixbufWidth = iWidth;
15531544
/*
1554-
* Only re-create SWT.CHECK renderers if this is the first column.
1555-
* Otherwise check-boxes will be rendered in columns they are not
1556-
* supposed to be rendered in. See bug 513761.
1545+
* Feature in GTK: a Tree with the style SWT.VIRTUAL has
1546+
* fixed-height-mode enabled. This will limit the size of
1547+
* any cells, including renderers. In order to prevent
1548+
* images from disappearing/being cropped, we re-create
1549+
* the renderers when the first image is set. Fix for
1550+
* bug 480261.
15571551
*/
1558-
boolean check = modelIndex == Tree.FIRST_COLUMN && (parent.style & SWT.CHECK) != 0;
1559-
parent.createRenderers(column, modelIndex, check, parent.style);
1552+
if ((parent.style & SWT.VIRTUAL) != 0) {
1553+
/*
1554+
* Only re-create SWT.CHECK renderers if this is the first column.
1555+
* Otherwise check-boxes will be rendered in columns they are not
1556+
* supposed to be rendered in. See bug 513761.
1557+
*/
1558+
boolean check = modelIndex == Tree.FIRST_COLUMN && (parent.style & SWT.CHECK) != 0;
1559+
// Renderers can't be replaced during render on GTK 3.24.41
1560+
// https://github.com/eclipse-platform/eclipse.platform.swt/issues/678
1561+
getDisplay ().asyncExec (() -> {
1562+
// Do not perform request if it is no longer applicable
1563+
if (parent.isDisposed () || Math.max (1, parent.getColumnCount ()) <= index) return;
1564+
// On multiple resize requests, perform only the last one
1565+
if (parent.pixbufHeight != iHeight || parent.pixbufWidth != iWidth) return;
1566+
int modelIndexAsync = parent.columnCount == 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex;
1567+
long columnAsync = GTK.gtk_tree_view_get_column (parent.handle, index);
1568+
parent.createRenderers (columnAsync, modelIndexAsync, check, parent.style);
1569+
});
1570+
}
15601571
}
15611572
}
1573+
} else {
1574+
/*
1575+
* Bug 483112: We check to see if the cached value is greater than the size of the pixbufRenderer.
1576+
* If it is, then we change the size of the pixbufRenderer accordingly.
1577+
* Bug 489025: There is a corner case where the below is triggered when current(Width|Height) is -1,
1578+
* which results in icons being set to 0. Fix is to compare only positive sizes.
1579+
*/
1580+
if (parent.pixbufWidth > Math.max(currentWidth [0], 0) || parent.pixbufHeight > Math.max(currentHeight [0], 0)) {
1581+
GTK.gtk_cell_renderer_set_fixed_size (pixbufRenderer, parent.pixbufWidth, parent.pixbufHeight);
1582+
}
15621583
}
1563-
} else {
1584+
1585+
GTK.gtk_tree_store_set(parent.modelHandle, handle, modelIndex + Tree.CELL_PIXBUF, pixbuf, -1);
1586+
GTK.gtk_tree_store_set(parent.modelHandle, handle, modelIndex + Tree.CELL_SURFACE, surface, -1);
1587+
} finally {
15641588
/*
1565-
* Bug 483112: We check to see if the cached value is greater than the size of the pixbufRenderer.
1566-
* If it is, then we change the size of the pixbufRenderer accordingly.
1567-
* Bug 489025: There is a corner case where the below is triggered when current(Width|Height) is -1,
1568-
* which results in icons being set to 0. Fix is to compare only positive sizes.
1589+
* Bug 573633: gtk_tree_store_set() will reference the handle. So we unref the pixbuf here,
1590+
* and leave the destruction of the handle to be done later on by the GTK+ tree.
15691591
*/
1570-
if (parent.pixbufWidth > Math.max(currentWidth [0], 0) || parent.pixbufHeight > Math.max(currentHeight [0], 0)) {
1571-
GTK.gtk_cell_renderer_set_fixed_size (pixbufRenderer, parent.pixbufWidth, parent.pixbufHeight);
1592+
if (pixbuf != 0) {
1593+
OS.g_object_unref(pixbuf);
15721594
}
15731595
}
1574-
1575-
GTK.gtk_tree_store_set(parent.modelHandle, handle, modelIndex + Tree.CELL_PIXBUF, pixbuf, -1);
1576-
/*
1577-
* Bug 573633: gtk_tree_store_set() will reference the handle. So we unref the pixbuf here,
1578-
* and leave the destruction of the handle to be done later on by the GTK+ tree.
1579-
*/
1580-
if (pixbuf != 0) {
1581-
OS.g_object_unref(pixbuf);
1582-
}
1583-
GTK.gtk_tree_store_set(parent.modelHandle, handle, modelIndex + Tree.CELL_SURFACE, surface, -1);
15841596
cached = true;
15851597
updated = true;
15861598
}

0 commit comments

Comments
 (0)