List icon Contents

Rendering

The guide describes how different rendering modes work and explores their limitations.

Overview 

The way JxBrowser renders web content inside BrowserView is determined by the rendering mode. There are two rendering modes in JxBrowser: HARDWARE_ACCELERATED and OFF_SCREEN.

You specify the rendering mode when you create an Engine instance, and it can’t be changed later. All browsers created within the Engine will use the same rendering mode.

Java
Kotlin

import static com.teamdev.jxbrowser.engine.RenderingMode.HARDWARE_ACCELERATED;
...
var engine = Engine.newInstance(HARDWARE_ACCELERATED);

import com.teamdev.jxbrowser.engine.RenderingMode.HARDWARE_ACCELERATED
...
val engine = Engine(HARDWARE_ACCELERATED)

Choosing the right rendering mode affects:

  • rendering performance,
  • overall resource consumption,
  • and the way JxBrowser handles user input.

When the GPU is available, Chromium uses hardware acceleration in both rendering modes. When the GPU is not available, Chromium switches to the CPU-bound software rendering — also in both rendering modes.

Hardware accelerated 

In this rendering mode, Chromium renders the web content directly on a special rendering surface that the library puts on top of BrowserView. The type of surface depends on the operating system.

Architecture of the HARDWARE_ACCELERATED rendering mode

Architecture of the HARDWARE_ACCELERATED rendering mode.

On Windows and Linux, JxBrowser embeds a native Chromium window into the Java application. This way, Chromium renders content in its own window with the same performance as a standalone browser. The embedded window is unobtrusive to the end user: it has no Chromium UI elements, taskbar icon, or other characteristics of a regular window.

No visual difference between the rendering modes

The embedded window looks like any other UI component.

On macOS, JxBrowser creates a native CARemoteLayer surface that is shared between the Java and Chromium processes. The surface is embedded into the Java window, and Chromium renders the content directly to the surface.

On macOS, a different approach is required because the operating system allows native windows to be re-parented only within the same process. Since JxBrowser launches Chromium in a separate process, the Chromium window cannot be attached to the Java window hierarchy as it can on Windows and Linux.

Input handling 

On Windows and Linux, the input is handled by Chromium. Since the user interacts directly with the Chromium window, the OS sends keyboard, accessibility, and other input events there, bypassing the Java window. That ensures exactly the same reaction on input as in Google Chrome.

On macOS, the input is handled by Java UI toolkits. See the “Input handling” section in the off-screen mode for details.

You can intercept mouse, keyboard, and touch events in the Java code. Visit the Intercepting events guide to learn how.

Limitations 

Overlapping with other UI components 

Regardless of the operating system, the rendering surface for web content is always placed above the Java window. As a result, regular UI components cannot appear over BrowserView because its area is obscured by the rendering surface.

In particular, avoid using the HARDWARE_ACCELERATED rendering mode when adding BrowserView into JInternalFrame or JLayeredPane in Swing, or StackPane in JavaFX.

JxBrowser overlapped by other components

Two BrowserView components — in different modes — overlapping with JPanel.

Transparent windows in JavaFX 

In JavaFX on Windows, the HARDWARE_ACCELERATED rendering mode is not compatible with the StageStyle.TRANSPARENT style. To show a transparent Stage, JavaFX uses layered windows, but this approach doesn’t work with the embedded Chromium window.

Off-screen 

In this rendering mode, Chromium renders content on the GPU. Then, the library copies pixels into an off-screen buffer in the Java process memory. The BrowserView acts as a lightweight component that reads pixels from the buffer and displays them using standard UI toolkit graphics, such as Graphics2D in Swing.

Architecture of the OFF_SCREEN rendering mode

Architecture of the OFF_SCREEN rendering mode.

Input handling 

By default, input events are handled by the Java window. When an input event occurs, the operating system dispatches it to a Java UI toolkit, which passes it to BrowserView, which forwards it to Chromium, which delivers it to the web page.

Limitations 

Native input handling 

At every stage of event handling, the event is converted from one data structure to another. Because data structures in different subsystems don’t match exactly, the data may be lost or misinterpreted. That creates rare cases in which a user interaction in JxBrowser produces a different JavaScript event than the same interaction in Chromium.

In JxBrowser 7.39.0, we introduced an experimental feature that directly forwards input events from the operating system to Chromium. This way, the JavaScript events generated in JxBrowser always match those in Chromium.

To activate the feature, use the system property:

System.setProperty("jxbrowser.native.input.enabled", "true");

Touch events 

Swing, JavaFX, SWT, and Compose lack full touch support. As a result, some Chromium gestures, such as pinch-to-zoom, don’t work in JxBrowser — in OFF_SCREEN mode on Windows and Linux, and in both modes on macOS.

Performance 

In the HARDWARE_ACCELERATED mode, the GPU usage directly affects rendering performance since Chromium renders content directly on the surface. This mode provides the same rendering performance as standalone Google Chrome. On most platforms, it can output 60 FPS for a 4K video.

In the OFF_SCREEN mode, using the GPU improves overall resource consumption, but doesn’t affect rendering performance as much. In this mode, the limiting factor is copying pixels between processes, which is a CPU-bound operation. This mode provides good rendering performance in most cases. For applications where the rendering performance is critical, it’s better to use the HARDWARE_ACCELERATED mode.

Headless 

When you don’t need to show the browser in the UI, prefer the HARDWARE_ACCELERATED rendering mode. The reason is that the OFF_SCREEN mode may consume extra CPU and RAM even when the browser is not displayed.

Regardless of the rendering mode, JxBrowser remains fully functional outside of BrowserView. For example, you can take a screenshot of a bare Browser in any rendering mode:

Java
Kotlin

var engine = Engine.newInstance(HARDWARE_ACCELERATED);
var browser = engine.newBrowser();

browser.resize(1920, 1080);
browser.navigation().loadUrlAndWait("https://html5test.teamdev.com");

// Take the bitmap of the web page. Its size will be 1920x1080.
var bitmap = browser.bitmap();

import com.teamdev.jxbrowser.dsl.Engine
...
val engine = Engine(HARDWARE_ACCELERATED)
val browser = engine.newBrowser()

browser.resize(1920, 1080)
browser.navigation().loadUrlAndWait("https://html5test.teamdev.com")

// Take the bitmap of the web page. Its size will be 1920x1080.
val bitmap = browser.bitmap()