From 6e8dd5a0ef7d06de28378dc945ef6456aa45c193 Mon Sep 17 00:00:00 2001 From: Mark Domingo Date: Fri, 22 May 2026 17:24:43 +0800 Subject: [PATCH] [#2242] do not aggregate empty browser controls in CompositeInformationControl Added a method to check if HTML content is empty and modified control reassignment logic for browser controls. --- .../hover/CompositeInformationControl.java | 50 +++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/bundles/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/hover/CompositeInformationControl.java b/bundles/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/hover/CompositeInformationControl.java index 2b811c86fa8..b946d2176ff 100644 --- a/bundles/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/hover/CompositeInformationControl.java +++ b/bundles/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/hover/CompositeInformationControl.java @@ -30,7 +30,10 @@ import org.eclipse.jface.text.IInformationControlExtension2; import org.eclipse.jface.text.IInformationControlExtension5; import org.eclipse.jface.text.ITextHover; +import org.eclipse.lsp4e.operations.hover.FocusableBrowserInformationControl; import org.eclipse.swt.SWT; +import org.eclipse.swt.browser.Browser; +import org.eclipse.swt.browser.ProgressListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; @@ -105,9 +108,21 @@ public void createContent(Composite parent) { if (children.isEmpty()) { continue; } - for (Control control : children) { - control.setParent(parent); - } + if (abstractInformationControl instanceof FocusableBrowserInformationControl browserControl) { + for (Control control : ((Composite) browserControl.getShell().getChildren()[0]).getChildren()) { + if (control instanceof Browser browser) { + browser.addProgressListener(ProgressListener.completedAdapter(p -> { + if (!isHtmlEmpty(browser.getText())) { + reassignParent(parent, children); + getShell().layout(true, true); + getShell().setSize(computeSizeHint()); + } + })); + } + } + } else { + reassignParent(parent, children); + } controls.put(hoverControlCreator.getKey(), abstractInformationControl); } else { ILog.of(CompositeInformationControl.class).warn( @@ -118,6 +133,35 @@ public void createContent(Composite parent) { } } + /** + * if the html is empty. + * + * @param html + * the html + * @return {@code true} if the html is empty, {@code false} otherwise + */ + @SuppressWarnings("nls") + public boolean isHtmlEmpty(final String html) { + if (html == null || html.isEmpty()) { + return true; + } + + // Remove all HTML tags + String plainText = html.replaceAll("<[^>]*>", "").trim(); + + // Check if what's left is actually content + // We also decode common entities like   which can trick empty checks + plainText = plainText.replace(" ", " ").trim(); + + return plainText.isEmpty(); + } + + private void reassignParent(final Composite parent, final List children) { + for (Control control : children) { + control.setParent(parent); + } + } + @Override public void dispose() { controls.values().forEach(IInformationControl::dispose);