Skip to content

[GTK3] Fix ToolBar.computeSize 60 Hz repaint loop with SWT.WRAP#3240

Merged
akurtakov merged 1 commit into
eclipse-platform:masterfrom
vogella:fix/toolbar-wrap-repaint-loop
Apr 16, 2026
Merged

[GTK3] Fix ToolBar.computeSize 60 Hz repaint loop with SWT.WRAP#3240
akurtakov merged 1 commit into
eclipse-platform:masterfrom
vogella:fix/toolbar-wrap-repaint-loop

Conversation

@vogella

@vogella vogella commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Remove the gtk_toolbar_set_show_arrow toggle workaround in ToolBar.computeSizeInPixels that caused two GTK invalidation cycles per measurement call
  • This workaround was added in 2012 (Bug 46025) for GTK 3.4 and is no longer needed on modern GTK 3.24
  • When a SWT.WRAP ToolBar sits inside a frequently-measured parent (e.g. CTabFolder.setTopRight), the toggle created a self-sustaining ~60 Hz repaint loop burning 10-25% CPU while idle
  • Add Snippet394 to verify ToolBar sizing works correctly without the workaround

Test plan

Fixes #3236

🤖 Generated with Claude Code

@vogella
vogella force-pushed the fix/toolbar-wrap-repaint-loop branch 2 times, most recently from 05ec74d to 29468e1 Compare April 15, 2026 18:51
@akurtakov

Copy link
Copy Markdown
Member

Very good catch. The snippet is good for testing but it is not smth that any SWT user can use as an example so it shouldn't end up in snippets whenever the PR is merged.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results

  182 files  ±0    182 suites  ±0   27m 43s ⏱️ + 2m 59s
4 701 tests ±0  4 680 ✅ ±0   21 💤 ±0  0 ❌ ±0 
6 704 runs  ±0  6 546 ✅ ±0  158 💤 ±0  0 ❌ ±0 

Results for commit 29468e1. ± Comparison against base commit dbac219.

Comment thread bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ToolBar.java Outdated
Comment thread bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ToolBar.java Outdated
@akurtakov

Copy link
Copy Markdown
Member

With the requested changes in Toolbar GTK3.gtk_toolbar_set_show_arrow will no longer be needed so it can be removed too.

@vogella

vogella commented Apr 15, 2026

Copy link
Copy Markdown
Contributor Author
/*******************************************************************************
 * Copyright (c) 2026 Eclipse Foundation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Eclipse Foundation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.snippets;

import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

/**
 * ToolBar computeSize test: verify whether the GTK3 toolbar sizing bug
 * (toolbar reports only the overflow arrow width when show_arrow is enabled)
 * is still present.
 *
 * <p>This snippet creates a ToolBar with several items and compares the
 * computed size with and without the SWT.WRAP style. If the GTK bug is fixed,
 * both sizes should be similar. If the bug is still present, the WRAP toolbar
 * will report a much smaller width (just the arrow).
 *
 * <p>See https://github.com/eclipse-platform/eclipse.platform.swt/issues/3236
 *
 * <p>For a list of all SWT example snippets see
 * https://eclipse.dev/eclipse/swt/snippets/
 */
public class Snippet395 {

public static void main(String[] args) {
	Display display = new Display();
	Shell shell = new Shell(display);
	shell.setText("Snippet 395 - ToolBar computeSize with WRAP");
	shell.setLayout(new GridLayout(1, false));

	// Create a toolbar WITHOUT SWT.WRAP
	ToolBar toolBarNoWrap = new ToolBar(shell, SWT.FLAT | SWT.RIGHT);
	addItems(toolBarNoWrap);

	// Create a toolbar WITH SWT.WRAP
	ToolBar toolBarWrap = new ToolBar(shell, SWT.FLAT | SWT.RIGHT | SWT.WRAP);
	addItems(toolBarWrap);

	// Compute sizes
	Point sizeNoWrap = toolBarNoWrap.computeSize(SWT.DEFAULT, SWT.DEFAULT);
	Point sizeWrap = toolBarWrap.computeSize(SWT.DEFAULT, SWT.DEFAULT);

	// Display results
	Label resultLabel = new Label(shell, SWT.WRAP);
	resultLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
	StringBuilder sb = new StringBuilder();
	sb.append("ToolBar without WRAP: " + sizeNoWrap.x + " x " + sizeNoWrap.y + "\n");
	sb.append("ToolBar with    WRAP: " + sizeWrap.x + " x " + sizeWrap.y + "\n\n");

	int widthDiff = Math.abs(sizeNoWrap.x - sizeWrap.x);
	if (widthDiff > sizeNoWrap.x / 2) {
		sb.append("RESULT: Large width difference (" + widthDiff + "px). "
			+ "The GTK sizing bug may still be present.\n"
			+ "The WRAP toolbar is likely reporting only the arrow width.");
	} else {
		sb.append("RESULT: Widths are similar (diff=" + widthDiff + "px). "
			+ "The GTK sizing bug appears to be fixed.");
	}
	resultLabel.setText(sb.toString());

	// Also print to console
	System.out.println(sb);

	shell.pack();
	shell.open();
	while (!shell.isDisposed()) {
		if (!display.readAndDispatch()) display.sleep();
	}
	display.dispose();
}

private static void addItems(ToolBar toolBar) {
	for (int i = 0; i < 5; i++) {
		ToolItem item = new ToolItem(toolBar, SWT.PUSH);
		item.setText("Action " + (i + 1));
	}
}

}


@vogella
vogella force-pushed the fix/toolbar-wrap-repaint-loop branch from 971ec6c to 8428c35 Compare April 15, 2026 19:40
@akurtakov

Copy link
Copy Markdown
Member

Changes in GTK3.java should have caused changes in gtk3.c and gtk3_stats.h

@github-actions

github-actions Bot commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

Test Results (linux)

   94 files  ±0     94 suites  ±0   14m 12s ⏱️ -9s
4 575 tests ±0  4 354 ✅ ±0  221 💤 ±0  0 ❌ ±0 
3 329 runs  ±0  3 257 ✅ ±0   72 💤 ±0  0 ❌ ±0 

Results for commit 07a989d. ± Comparison against base commit dbac219.

♻️ This comment has been updated with latest results.

@vogella
vogella force-pushed the fix/toolbar-wrap-repaint-loop branch from 8428c35 to b2fce68 Compare April 15, 2026 22:38
@vogella

vogella commented Apr 15, 2026

Copy link
Copy Markdown
Contributor Author

Changes in GTK3.java should have caused changes in gtk3.c and gtk3_stats.h

I do not see how. The gtk-dev-guide.md mentions that "SWT Tools also generates JNI bindings (i.e. os.c, os_stat.c, etc.) for you automatically." but my SDK build does not have the SWT Tools installled. And mvn clean install '-Dnative=gtk.linux.x86_64' -DskipTests does also not do this.

Manually updated gtk3.c. The stats files (gtk3_stats.c/gtk3_stats.h) didn't seemt to have an entry for this function.

@akurtakov

Copy link
Copy Markdown
Member

SWT tools work only as eclipse plugin and do their work on save of java file as regular builder. The entry in gtk3_stats is gtk_1toolbar_1set_1show_1arrow_FUNC but I would prefer to see the changes done by the builder manually to reduce extra changes in other PRs where swt tools do the work.

@vogella

vogella commented Apr 16, 2026

Copy link
Copy Markdown
Contributor Author

SWT tools work only as eclipse plugin and do their work on save of java file as regular builder. The entry in gtk3_stats is gtk_1toolbar_1set_1show_1arrow_FUNC but I would prefer to see the changes done by the builder manually to reduce extra changes in other PRs where swt tools do the work.

As discussed via chat the tools usage is not document nor part of the SDK build. I will suggest to @HannesWell to document the usage in his pending #3212 for documention improvements

image

Remove all gtk_toolbar_set_show_arrow usage from ToolBar: both the
toggle in computeSizeInPixels (added in 2012 for Bug 46025) and the
toggle in setBounds. WRAP is not supported on GTK and the show_arrow
flag was being misused to work around a GTK3 sizing bug from the
GTK 3.4 era that no longer applies on modern GTK 3.24.

The workaround in computeSizeInPixels caused two GTK state transitions
per measurement, each triggering gtk_widget_queue_resize ->
gtk_widget_queue_draw -> gdk_window_invalidate_region. When a SWT.WRAP
ToolBar sits inside a frequently-measured parent (e.g.
CTabFolder.setTopRight), this created a self-sustaining ~60 Hz repaint
loop that burns 10-25% CPU while idle.

With no remaining callers, the gtk_toolbar_set_show_arrow native
binding is removed from GTK3.java as well.

Fixes eclipse-platform#3236

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vogella
vogella force-pushed the fix/toolbar-wrap-repaint-loop branch from b2fce68 to 07a989d Compare April 16, 2026 08:45
@vogella

vogella commented Apr 16, 2026

Copy link
Copy Markdown
Contributor Author

Coooool. After installing the swt.tools the c files get updated. Very nice feature. Would be nice if that would also be baked into the command line build.

@akurtakov PR updated as requested.

@vogella
vogella marked this pull request as ready for review April 16, 2026 09:12
@akurtakov

Copy link
Copy Markdown
Member

I'm updating jnigen in eclipse-platform/www.eclipse.org-eclipse#535 - outdated version available at https://eclipse.dev/eclipse/swt/jnigen.html

@vogella

vogella commented Apr 16, 2026

Copy link
Copy Markdown
Contributor Author

Any further concerns about this PR @akurtakov ?

@akurtakov
akurtakov merged commit a973632 into eclipse-platform:master Apr 16, 2026
20 checks passed
@vogella
vogella deleted the fix/toolbar-wrap-repaint-loop branch April 16, 2026 11:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[GTK3] ToolBar.computeSize with SWT.WRAP causes self-sustaining 60 Hz repaint loop in CTabFolder.setTopRight

2 participants