---
updatedAt: 2025-06-16T21:15:20.000Z
---

Fetch the complete documentation index at: https://docs.ultralig.ht/llms.txt. Use this file to discover all available pages before exploring further.

# Porting from 1.3 to 1.4

Summary of changes needed when updating code to v1.4

# Critical Changes:

## - Renderer::RefreshDisplay() must now be called from your render loop.

When managing rendering yourself via `Renderer::Create()`, you must now call `Renderer::RefreshDisplay(0)` before calling `Renderer::Render()`.

```cplusplus
void MyApplication::Render() {
    // **NEW**:
    // Notify the renderer that the default display has physically refreshed
    // so that the engine has a chance to update animations.
    renderer.RefreshDisplay(0);
  
    // Render all Views to their respective surfaces / render-targets.
    renderer.Render();
  
    // Handle any updated surfaces / textures here.
}
```

### Discussion

Previous to 1.4, calling `Renderer::Render()` would update animations (eg, CSS animations, JavaScript `requestAnimationFrame()`, scroll animations, etc.) each time it was called.

This didn't quite match the spec since animations are supposed to be updated in lock-step with the physical refresh rate of the display which may or may not have matched the rate at which `Renderer::Render()` was called.

To fix this, we've introduced a new API method, `Renderer::RefreshDisplay(display_id)`, that should be called whenever the display refreshes.

#### Single Monitor Setup

If you're using a single display, simply call `Renderer::RefreshDisplay(0)` whenever the display updates (all Views have a default `display_id` of `0`).

#### Multi-Monitor Setup

If you're using multiple displays and want to independently control their refresh rate, you should:

1. Associate a `View` with a display by updating `ViewConfig::display_id` with a unique integer identifying the display.
2. Call `Renderer::RefreshDisplay(display_id)` whenever the display physically refreshes.

## - ViewListener::OnAddConsoleMessage() now has different parameters.

You will need to update your `ViewListener::OnAddConsoleMessage()` implementation to use the new `ConsoleMessage` class instead of individual parameters.

```cplusplus
virtual void OnAddConsoleMessage(ultralight::View* caller,
                                 const ultralight::ConsoleMessage& message) { }
```

# Other Changes

## - New ImageSource API

* `ImageSource` and `ImageSourceProvider` can be used to composite custom image and texture data inside a web-page.

## - New Listener APIs

* `NetworkListener` (and `View::set_network_listener()`) can be used to listen for network requests and individually block/allow them.
* `DownloadListener` (and `View::set_download_listener()`) can be used to handle file downloads.

## - New String API Improvements

* `ultralight::String` and other string classes now have improved support for comparison, hashing, and `std::move()` for better compatibility with STL containers.
* You can optionally include the new `StringSTL.h` header for easy conversions between `ultralight::String` and `std::string` or `std::string_view`.

## - New MessageSource enum values

The values for the`MessageSource` enum have changed.

## - Defines Updated

* `ULTRALIGHT_VERSION` has been updated to **`"1.4.0"`**
* `WEBKIT_VERSION` has been updated to **`"615.1.18.100.1"`**

You can use these defines to verify that you're working with the correct API version.

<br />

<br />

<br />

<br />

<br />

<br />

###