Skip to content

Commit 65586c3

Browse files
Copilotlaeubi
andcommitted
Fix GTK4 crash when creating and closing many shells
Add signal handler tracking for GdkSurface signals in Shell.java. Store handler IDs when connecting signals and disconnect them in releaseWidget(). Add test for creating and disposing multiple shells. Co-authored-by: laeubi <1331477+laeubi@users.noreply.github.com>
1 parent 91823b9 commit 65586c3

2 files changed

Lines changed: 33 additions & 2 deletions

File tree

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

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ public class Shell extends Decorations {
133133
boolean ignoreFocusOut, ignoreFocusIn;
134134
boolean ignoreFocusOutAfterGrab, grabbedFocus;
135135
Region originalRegion;
136+
long gdkSurfaceNotifyStateHandler, gdkSurfaceComputeSizeHandler;
136137

137138
static final int MAXIMUM_TRIM = 128;
138139
static final int BORDER = 3;
@@ -965,8 +966,8 @@ void hookEvents () {
965966
// Replaced "window-state-event" with GdkSurface "notify::state", pass shellHandle as user_data
966967
GTK.gtk_widget_realize(shellHandle);
967968
long gdkSurface = gtk_widget_get_surface (shellHandle);
968-
OS.g_signal_connect (gdkSurface, OS.notify_state, display.notifyProc, shellHandle);
969-
OS.g_signal_connect (gdkSurface, OS.compute_size, display.computeSizeProc, shellHandle);
969+
gdkSurfaceNotifyStateHandler = OS.g_signal_connect (gdkSurface, OS.notify_state, display.notifyProc, shellHandle);
970+
gdkSurfaceComputeSizeHandler = OS.g_signal_connect (gdkSurface, OS.compute_size, display.computeSizeProc, shellHandle);
970971
OS.g_signal_connect(shellHandle, OS.notify_default_height, display.notifyProc, Widget.NOTIFY_DEFAULT_HEIGHT);
971972
OS.g_signal_connect(shellHandle, OS.notify_default_width, display.notifyProc, Widget.NOTIFY_DEFAULT_WIDTH);
972973
OS.g_signal_connect(shellHandle, OS.notify_maximized, display.notifyProc, Widget.NOTIFY_MAXIMIZED);
@@ -3431,6 +3432,20 @@ void releaseWidget () {
34313432
if (group != 0) OS.g_object_unref (group);
34323433
group = modalGroup = 0;
34333434
lastActive = null;
3435+
// Disconnect GdkSurface signal handlers for GTK4
3436+
if (GTK.GTK4 && shellHandle != 0) {
3437+
long gdkSurface = gtk_widget_get_surface(shellHandle);
3438+
if (gdkSurface != 0) {
3439+
if (gdkSurfaceNotifyStateHandler != 0) {
3440+
OS.g_signal_handler_disconnect(gdkSurface, gdkSurfaceNotifyStateHandler);
3441+
gdkSurfaceNotifyStateHandler = 0;
3442+
}
3443+
if (gdkSurfaceComputeSizeHandler != 0) {
3444+
OS.g_signal_handler_disconnect(gdkSurface, gdkSurfaceComputeSizeHandler);
3445+
gdkSurfaceComputeSizeHandler = 0;
3446+
}
3447+
}
3448+
}
34343449
if (regionToDispose != null) {
34353450
regionToDispose.dispose();
34363451
}

tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Shell.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,22 @@ public void test_Issue450_NoShellActivateOnSetFocus() {
10041004
}
10051005
}
10061006

1007+
@Test
1008+
public void test_createAndDisposeMultipleShells() {
1009+
// Test for GTK4 crash when creating and disposing many shells
1010+
// See https://github.com/eclipse-platform/eclipse.platform.swt/issues/XXXX
1011+
Display display = shell.getDisplay();
1012+
for (int i = 0; i < 100; i++) {
1013+
Shell testShell = new Shell(display);
1014+
testShell.open();
1015+
while (display.readAndDispatch()) {
1016+
// Process events
1017+
}
1018+
testShell.close();
1019+
testShell.dispose();
1020+
}
1021+
}
1022+
10071023
@Override
10081024
public void test_setLocationLorg_eclipse_swt_graphics_Point() {
10091025
//Setting location for Windows is not supported in GTK4

0 commit comments

Comments
 (0)