Skip to content

Commit 95c98c9

Browse files
committed
Coalesce Quick Access resize updates and skip no-op resizes
QuickAccessContents armed a recompute on every shell resize during the popup's initial layout, and each recompute cancels the in-flight compute job. On Windows the native search field triggers a burst of initial layout resizes, so the compute job scheduled for freshly typed text was repeatedly cancelled and the table was never refreshed. This is the intermittent failure in QuickAccessDialogTest.testPreviousChoicesAvailableForExtension. A resize only changes the results by changing how many rows fit, so track the row count used for the last compute and skip the resize-triggered update when it is unchanged. Remaining resizes are coalesced with a trailing-edge debounce so a burst (for example scrollbar oscillation during initial layout) collapses into a single update once the layout settles, instead of cancelling the in-flight compute job repeatedly. Also fix an accidental ~83 minute timeout (TIMEOUT * 1000) in that test's dialog-init wait. Fixes #4009
1 parent a4171b1 commit 95c98c9

2 files changed

Lines changed: 32 additions & 16 deletions

File tree

bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/quickaccess/QuickAccessContents.java

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ public abstract class QuickAccessContents {
102102
*/
103103
private static final String QUICK_ACCESS_COMMAND_ID = "org.eclipse.ui.window.quickAccess"; //$NON-NLS-1$
104104

105+
/** Trailing-edge debounce window collapsing a burst of shell resizes. */
106+
private static final int RESIZE_DEBOUNCE_MS = 100;
107+
105108
protected Text filterText;
106109

107110
private final QuickAccessProvider[] providers;
@@ -123,7 +126,7 @@ public abstract class QuickAccessContents {
123126
private Color grayColor;
124127
private TextLayout textLayout;
125128
private boolean showAllMatches = false;
126-
protected boolean resized = false;
129+
private int lastComputedItemCount = -1;
127130
private TriggerSequence keySequence;
128131
private Job computeProposalsJob;
129132

@@ -164,6 +167,7 @@ public void updateProposals(String filter) {
164167

165168
String computingMessage = NLS.bind(QuickAccessMessages.QuickaAcessContents_computeMatchingEntries, filter);
166169
int maxNumberOfItemsInTable = computeNumberOfItems();
170+
lastComputedItemCount = maxNumberOfItemsInTable;
167171
AtomicReference<List<QuickAccessEntry>[]> entries = new AtomicReference<>();
168172
final Job currentComputeEntriesJob = Job.create(computingMessage, theMonitor -> {
169173
entries.set(
@@ -766,24 +770,36 @@ public Table createTable(Composite composite) {
766770
tableComposite = new Composite(composite, SWT.NONE);
767771
GridDataFactory.fillDefaults().grab(true, true).applyTo(tableComposite);
768772
table = new Table(tableComposite, SWT.SINGLE | SWT.FULL_SELECTION);
773+
final Runnable resizeUpdate = () -> {
774+
if (showAllMatches || table == null || table.isDisposed() || filterText == null
775+
|| filterText.isDisposed()) {
776+
return;
777+
}
778+
// Skip when the layout settled back to the row count we already computed for,
779+
// so an oscillating burst does not cancel the in-flight compute job.
780+
if (computeNumberOfItems() == lastComputedItemCount) {
781+
return;
782+
}
783+
if (Policy.DEBUG_QUICK_ACCESS) {
784+
trace("Resize listener triggering proposals update"); //$NON-NLS-1$
785+
}
786+
updateProposals(filterText.getText().toLowerCase());
787+
};
769788
table.getShell().addControlListener(new ControlAdapter() {
770789
@Override
771790
public void controlResized(ControlEvent e) {
772-
if (!showAllMatches) {
773-
if (!resized) {
774-
resized = true;
775-
e.display.timerExec(100, () -> {
776-
if (table != null && !table.isDisposed() && filterText != null
777-
&& !filterText.isDisposed()) {
778-
if (Policy.DEBUG_QUICK_ACCESS) {
779-
trace("Resize listener triggering proposals update"); //$NON-NLS-1$
780-
}
781-
updateProposals(filterText.getText().toLowerCase());
782-
}
783-
resized = false;
784-
});
785-
}
791+
if (showAllMatches || table == null || table.isDisposed() || filterText == null
792+
|| filterText.isDisposed()) {
793+
return;
794+
}
795+
// A resize only matters when the number of visible rows changes. Coalesce a
796+
// burst of resizes (e.g. scrollbar oscillation during initial layout) into a
797+
// single trailing update, and skip it when the row count is unchanged.
798+
if (computeNumberOfItems() == lastComputedItemCount) {
799+
return;
786800
}
801+
e.display.timerExec(-1, resizeUpdate);
802+
e.display.timerExec(RESIZE_DEBOUNCE_MS, resizeUpdate);
787803
}
788804
});
789805

tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/quickaccess/QuickAccessDialogTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ public void testPreviousChoicesAvailableForExtension() {
321321
* wait for the dialog initialization, to avoid race conditions later on in the test, see:
322322
* https://github.com/eclipse-platform/eclipse.platform.ui/issues/4009
323323
*/
324-
assertTrue(DisplayHelper.waitForCondition(text.getDisplay(), TIMEOUT * 1000,
324+
assertTrue(DisplayHelper.waitForCondition(text.getDisplay(), TIMEOUT,
325325
() -> dialog.infoText != null),
326326
"Unexpected dialog info: " + dialog.infoText);
327327
text.setText(TestQuickAccessComputer.TEST_QUICK_ACCESS_PROPOSAL_LABEL);

0 commit comments

Comments
 (0)