Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ public class Display extends Device implements Executor {
Shell activeShell;
boolean activePending;
boolean ignoreFocus;
/* GTK4: depth of focusProc() calls, and popovers disposed meanwhile, see Shell.releaseHandle() */
int focusProcDepth;
ArrayList<Long> disposedPopovers = new ArrayList<>();

Tracker tracker;

Expand Down Expand Up @@ -6149,7 +6152,32 @@ boolean scrollProc(long controller, double dx, double dy, long user_data) {
long handle = GTK.gtk_event_controller_get_widget(controller);
Widget widget = getWidget(handle);

if (widget != null) widget.focusProc(controller, user_data);
if (widget == null) return;
Comment thread
akurtakov marked this conversation as resolved.
focusProcDepth++;
try {
widget.focusProc(controller, user_data);
} finally {
// GTK goes on with the focus change after this, so destroy the popovers later
if (--focusProcDepth == 0 && !disposedPopovers.isEmpty() && !isDisposed()) asyncExec(this::destroyDisposedPopovers);
Comment thread
akurtakov marked this conversation as resolved.
}
}

/**
* GTK4: destroys the popovers of shells disposed while a focus change was dispatched.
*/
void destroyDisposedPopovers () {
// Still in a focus change, e.g. in a nested event loop of a listener, see focusProc()
if (focusProcDepth > 0) return;
ArrayList<Long> popovers = disposedPopovers;
disposedPopovers = new ArrayList<>();
for (long popover : popovers) {
// The parent window may have destroyed the popover meanwhile
if (GTK.gtk_widget_get_parent (popover) != 0) {
GTK.gtk_popover_popdown (popover);
GTK.gtk_widget_unparent (popover);
}
OS.g_object_unref (popover);
}
}

void windowActiveProc(long handle, long user_data) {;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3854,9 +3854,17 @@ void releaseHandle () {
* its parent is released with destroy=false, which calls releaseHandle() but not
* destroyWidget(); unparenting here covers both paths and avoids leaving the popover
* attached to a finalizing parent window.
*
* GTK sends the focus leave events walking up the widget tree from the old focus
* widget, so a popover disposed by a FocusOut listener is hidden and unparented
* only once that focus change is done, see Display.focusProc().
*/
GTK.gtk_popover_popdown (shellHandle);
GTK.gtk_widget_unparent (shellHandle);
if (display.focusProcDepth > 0) {
display.disposedPopovers.add (OS.g_object_ref (shellHandle));
} else {
GTK.gtk_popover_popdown (shellHandle);
GTK.gtk_widget_unparent (shellHandle);
}
}
super.releaseHandle ();
shellHandle = 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2025 IBM Corporation and others.
* Copyright (c) 2000, 2026 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -1063,6 +1063,28 @@ public void test_Issue450_NoShellActivateOnSetFocus() {
}
}

@Test
public void test_onTopChildShellDisposedInFocusOut() throws InterruptedException {
Comment thread
akurtakov marked this conversation as resolved.
shell.setLayout(new FillLayout());
Text text = new Text(shell, SWT.BORDER);
shell.open();
SwtTestUtil.processEvents();

Shell popup = new Shell(shell, SWT.ON_TOP | SWT.TOOL);
popup.setLayout(new FillLayout());
Text popupText = new Text(popup, SWT.BORDER);
popup.setSize(100, 100);
// Close when the focus leaves, as popups do
popupText.addListener(SWT.FocusOut, e -> popup.dispose());
popup.open();
popupText.forceFocus();
SwtTestUtil.processEvents();

text.forceFocus();
SwtTestUtil.processEvents(1000, popup::isDisposed);
assertTrue(popup.isDisposed());
}

@Test
@Override
public void test_setLocationLorg_eclipse_swt_graphics_Point() {
Expand Down
Loading