# io.Connect Desktop 10.3

Source: https://docs.interop.io/desktop/getting-started/changelog/platform/10-3/index.html

## io.Connect Desktop 10.3

*Release date: 02.07.2026*

| Components | Version |
|------------|---------|
| Electron | [42.3.3](https://releases.electronjs.org/release/v42.3.3) |
| Chromium | 148.0.7778.218 |
| Node.js | 24.15.0 |

The following libraries are bundled with **io.Connect Desktop** 10.3 and will be used for [auto injection](https://docs.interop.io/desktop/getting-started/how-to/interop-enable-your-apps/javascript/index.md#auto_injection):

| Injected Library | Version |
|------------------|---------|
| [`@interopio/desktop`](https://www.npmjs.com/package/@interopio/desktop) | [6.21](https://docs.interop.io/desktop/getting-started/changelog/libraries/interopio-desktop/index.md#621-6210) |
| [`@interopio/fdc3`](https://www.npmjs.com/package/@interopio/fdc3) | 2.10 |

## New Features

> ### Retrieving Layout Contents
>
> The Layouts API has been extended with a new [`getLayoutContents()`](https://docs.interop.io/desktop/reference/javascript/layouts/api/index.md#API-getLayoutContents) method that allows you to [retrieve the contents](https://docs.interop.io/desktop/capabilities/windows/layouts/javascript/index.md#layout_operations-retrieving_layout_contents) of Global Layouts and Workspace Layouts. The method receives a [`GetContentsOptions`](https://docs.interop.io/desktop/reference/javascript/layouts/getcontentsoptions/index.md) object as a required argument.
>
> When used for retrieving the contents of a Global Layout, the returned [`LayoutContents`](https://docs.interop.io/desktop/reference/javascript/layouts/layoutcontents/index.md) object will contain all components participating in the Global Layout: individual app instances (including all Workspaces App instances), all Workspace instances hosted in all Workspaces App instances, and all windows participating in all Workspaces.
>
> When used for retrieving the contents of a Workspace Layout, the returned `LayoutContents` object will contain only the windows participating in the Workspace.
>
> The following example demonstrates how to retrieve the contents of a Global Layout:
>
> ```javascript
> const options = { name: "My Layout", type: "Global" };
>
> const {
>    appComponents,
>    workspaceComponents,
>    workspaceWindows
> } = await io.layouts.getLayoutContents(options);
>
> // List all apps in the Layout.
> console.log("Apps:", appComponents);
>
> // List all Workspaces App instances in the Layout.
> console.log("Workspaces App instances:", workspaceComponents);
>
> // List all windows participating in all Workspaces.
> console.log("Workspace windows:", workspaceWindows);
> ```

> ### Interacting with io.Manager
>
> The [`@interopio/manager-api`](https://www.npmjs.com/package/@interopio/manager-api) library now exposes a `ManagerLib()` factory function that can be included in the `libraries` array of the optional configuration object for initializing the [`@interopio/desktop`](https://www.npmjs.com/package/@interopio/desktop) library.
>
> Including the `ManagerLib()` factory function in the configuration object will add a new `manager` property to the initialized io.Connect API object which you can use to access [methods for interacting](https://docs.interop.io/manager/apis/initiating-interactions-from-io-connect/index.md) with **io.Manager**. The exposed methods allow apps to monitor the connection state to **io.Manager** and to trigger data fetching operations programmatically.
>
> The following example demonstrates including the `ManagerLib()` factory function when initializing the [`@interopio/desktop`](https://www.npmjs.com/package/@interopio/desktop) library and using the methods available on the `io.manager` object:
>
> ```javascript
> import IODesktop from "@interopio/desktop";
> import { ManagerLib } from "@interopio/manager-api/desktop";
>
> const config = { libraries: [ManagerLib] };
>
> const io = await IODesktop(config);
>
> // Retrieving the state of the connection to io.Manager.
> const connectionState = await io.manager.getConnectionState();
>
> // Providing a handler and subscribing for changes in the connection state.
> const handler = connectionState => console.log(`Connection state: ${JSON.stringify(connectionState)}`);
>
> const unsubscribe = io.manager.onConnectionStateChange(handler);
>
> // Refreshing the available apps and Layouts.
> const dataToFetch = {
>     layouts: true,
>     applications: true
> };
>
> await io.manager.fetchData(dataToFetch);
> ```
>
> This feature is available in [`@interopio/manager-api`](https://www.npmjs.com/package/@interopio/manager-api) 4.2 and later.
>
> > ℹ️ *For more details on the available methods, see the [APIs > Initiating Interaction from io.Connect](https://docs.interop.io/manager/apis/initiating-interactions-from-io-connect/index.md) section in the **io.Manager** documentation.*

> ### Workspace Frame On Top State
>
> It's now possible to dynamically control the [z-order](https://docs.interop.io/desktop/capabilities/windows/workspaces/javascript/index.md#frame-zorder) of a Workspace App instance by using the [`setOnTop()`](https://docs.interop.io/desktop/reference/javascript/workspaces/frame/index.md#Frame-setOnTop) method of a [`Frame`](https://docs.interop.io/desktop/capabilities/windows/workspaces/overview/index.md) instance:
>
> ```javascript
> const myFrame = await io.workspaces.getMyFrame();
>
> // Instruct the framework to keep the `Frame` instance always on top of other windows.
> const options = { onTop: true };
>
> await myFrame.setOnTop(options);
> ```
>
> By default, the `onTop` property of a `Frame` instance is set to `false`.
>
> If you extract a Workspace from a Workspace App instance that has its `onTop` property set to `true`, the `onTop` property of the newly created Workspace App instance that will host the extracted Workspace will be set to `false` by default.
>
> It's possible to set more than one Workspace App instance to be always on top. In this case, the users will be able to switch between these Workspace App instances if they overlap visually, but they will always remain above all other windows in the z-order.
>
> This feature is available in [`@interopio/workspaces-api`](https://www.npmjs.com/package/@interopio/workspaces-ui-react) 4.5 and later.

> ### Workspace Tab Reorder Events
>
> You can now get notified when Workspace tabs or window tabs are reordered within their respective containers (Workspace Frames and window tab groups). These events are triggered only when dragging a tab to a different position without removing it from its current container.
>
> To subscribe for Workspace tab reorder events at the API level, use the [`onWorkspaceTabReordered()`](https://docs.interop.io/desktop/reference/javascript/workspaces/api/index.md#API-onWorkspaceTabReordered) method. The event handler receives the reordered [`Workspace`](https://docs.interop.io/desktop/reference/javascript/workspaces/workspace/index.md) instance with the updated `positionIndex`:
>
> ```javascript
> const handler = ({ title, positionIndex }) => console.log(`Workspace "${title}" was reordered to position ${positionIndex}.`);
>
> const unsubscribe = await io.workspaces.onWorkspaceTabReordered(handler);
> ```
>
> To subscribe for window tab reorder events at the API level, use the [`onWindowTabReordered()`](https://docs.interop.io/desktop/reference/javascript/workspaces/api/index.md#API-onWindowTabReordered) method. The event handler receives the reordered [`WorkspaceWindow`](https://docs.interop.io/desktop/reference/javascript/workspaces/workspacewindow/index.md) instance with the updated `positionIndex`:
>
> ```javascript
> const handler = ({ title, positionIndex }) => console.log(`Window "${title}" was reordered to position ${positionIndex}.`);
>
> const unsubscribe = await io.workspaces.onWindowTabReordered(handler);
> ```
>
> Tab reorder events are also available for:
>
> - [`Workspace`](https://docs.interop.io/desktop/reference/javascript/workspaces/workspace/index.md) instances via the [`ontabReordered()`](https://docs.interop.io/desktop/reference/javascript/workspaces/workspace/index.md#Workspace-ontabReordered) and [`onWindowTabReordered()`](https://docs.interop.io/desktop/reference/javascript/workspaces/workspace/index.md#Workspace-onWindowTabReordered) methods.
>
> - [`WorkspaceWindow`](https://docs.interop.io/desktop/reference/javascript/workspaces/workspacewindow/index.md) instances via the [`ontabReordered()`](https://docs.interop.io/desktop/reference/javascript/workspaces/workspacewindow/index.md#WorkspaceWindow-ontabReordered) method.
>
> This feature is available in [`@interopio/workspaces-api`](https://www.npmjs.com/package/@interopio/workspaces-ui-react) 4.4 and later.

> ### Workspace Splitter Size
>
> It's now possible to customize the size of the [Workspace splitters](https://docs.interop.io/desktop/capabilities/windows/workspaces/overview/index.md#extending_workspaces-splitter_size) (the draggable dividers between the windows in a Workspace).
>
> To specify a splitter size in pixels, use the `splitterSize` property of the `settings` object within the `components` prop of the `<Workspaces />` component:
>
> ```javascript
> import Workspaces from "@interopio/workspaces-ui-react";
>
> const App = () => {
>     return (
>         <Workspaces
>             components={{
>                 settings: {
>                     splitterSize: 10
>                 }
>             }}
>         />
>     );
> };
>
> export default App;
> ```
>
> This feature is available in [`@interopio/workspaces-ui-react`](https://www.npmjs.com/package/@interopio/workspaces-ui-react) 4.5 and later.

> ### Download Path
>
> The [`DownloadOptions`](https://docs.interop.io/desktop/reference/javascript/windows/downloadoptions/index.md) object passed as a second argument to the [`download()`](https://docs.interop.io/desktop/reference/javascript/windows/my%20window/index.md#IOConnectWindow-download) method of an `IOConnectWindow` instance now accepts a `path` property. Use it to specify a download destination for each individual download:
>
> ```javascript
> const downloadURL = "https://example.com/logo.png";
> const options = { path: "C:/Downloads/my-folder" };
>
> const { path, size, url } = await myWindow.download(downloadURL, options);
> ```
>
> The `path` property in `DownloadOptions` takes precedence over the global download path set via the `setSavePath()` method of the `iodesktop` object. Using the `download()` method of an `IOConnectWindow` instance may prevent potential race conditions when multiple windows attempt to download files concurrently and set different save paths globally via the `setSavePath()` method.

> ### Download Auto Save State
>
> You can now use the `setAutoSave()` and `getAutoSave()` methods accessible via the `downloads` property of the `iodesktop` object injected in the global `window` object, which enable you to control the auto save behavior for [downloads](https://docs.interop.io/desktop/capabilities/windows/window-management/javascript/index.md#window_operations-download) at runtime:
>
> ```javascript
> // Disabling auto saving of downloads.
> await iodesktop.downloads.setAutoSave(false);
>
> // Retrieving the current auto save state.
> const autoSave = await iodesktop.downloads.getAutoSave();
>
> if (autoSave) {
>     console.log("Auto saving of downloads is enabled.");
> } else {
>     console.log("Auto saving of downloads is disabled.");
> }
> ```
>
> The `setAutoSave()` method takes precedence over the `"autoSave"` property specified in the system configuration or the app definition, and can be overridden by using the `autoSave` property of the `DownloadOptions` object when using the `download()` method of an `IOConnectWindow` instance.
>
> If auto saving is enabled, but the download path specified via configuration or dynamically can't be resolved, a system save dialog will be shown to the user.

> ### Closing Blank Download Windows
>
> When a [download](https://docs.interop.io/desktop/developers/configuration/system/index.md#window_settings-downloads) is initiated from a link with `target="_blank"`, a new window is opened to handle the download, which by default stays open after the download is complete.
>
> To instruct **io.Connect Desktop** to automatically close the download window after the download is complete, use the `"closeBlankDownloadWindows"` property of the `"downloadSettings"` object under the `"windows"` top-level key in the `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md) file of **io.Connect Desktop**:
>
> ```json
> {
>     "windows": {
>         "downloadSettings": {
>             "closeBlankDownloadWindows": true
>         }
>     }
> }
> ```

> ### Zoom Keyboard Shortcuts
>
> To customize the keyboard shortcuts for zoom in, zoom out, and zoom reset, use the `"shortcuts"` property of the `"zoom"` object under the `"windows"` top-level key in `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md) file of **io.Connect Desktop**.
>
> The following example demonstrates the default settings for the zoom keyboard shortcuts:
>
> ```json
> {
>     "windows": {
>         "zoom": {
>             "shortcuts": {
>                 "zoomIn": ["ctrl+=", "ctrl+shift+=", "ctrl+numadd"],
>                 "zoomOut": ["ctrl+-", "ctrl+numsub"],
>                 "resetZoom": ["ctrl+0", "ctrl+num0"]
>             }
>         }
>     }
> }
> ```
>
> The `"shortcuts"` object has the following properties:
>
> | Property | Type | Description |
> |----------|------|-------------|
> | `"resetZoom"` | `string[]` | Keyboard shortcuts for resetting the zoom factor to the default value. Defaults to `["ctrl+0", "ctrl+num0"]`. |
> | `"zoomIn"` | `string[]` | Keyboard shortcuts for zooming in. Defaults to `["ctrl+=", "ctrl+shift+=", "ctrl+numadd"]`. |
> | `"zoomOut"` | `string[]` | Keyboard shortcuts for zooming out. Defaults to `["ctrl+-", "ctrl+numsub"]`. |

> ### URL Filter
>
> The `"urlFilter"` property of the `"windows"` top-level key in `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md) file of **io.Connect Desktop** used for [filtering web requests](https://docs.interop.io/desktop/developers/configuration/system/index.md#window_settings-filtering_web_requests) now also accepts an array of regular expressions.
>
> This enables you to define multiple allowed domain patterns without combining them into a single complex regular expression:
>
> ```json
> {
>     "windows": {
>         "urlFilter": [
>             "^https://.*\\.example\\.com",
>             "^https://.*\\.another-example\\.com"
>         ]
>     }
> }
> ```

> ### Hardware Metadata in io.Insights
>
> It's now possible to include hardware metadata as resource attributes in all OpenTelemetry signals (metrics, traces, and logs) when using [**io.Insights**](https://docs.interop.io/insights/general-overview/index.md). This helps correlate performance data with the underlying hardware, enabling more informed analysis of startup times and resource usage across deployments with varied hardware configurations.
>
> To enable hardware metadata collection, set the `"addHardwareDataToAttributes"` property to `true` in the `"otel"` top-level key of `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md) file of **io.Connect Desktop**:
>
> ```json
> {
>     "otel": {
>         "addHardwareDataToAttributes": true
>     }
> }
> ```
>
> The following hardware data will be added as resource attributes to all OpenTelemetry signals:
>
> | Attribute | Description |
> |-----------|-------------|
> | `"cpuCores"` | Number of logical CPU cores. |
> | `"cpuModel"` | CPU model name. |
> | `"cpuSpeedGHz"` | CPU speed in GHz. |
> | `"memoryTotalGB"` | Total system memory in GB. |
> | `"osArch"` | OS CPU architecture (e.g., `"x64"`). |
> | `"osPlatform"` | OS platform identifier (e.g., `"win32"`). |
> | `"osRelease"` | OS release version string. |
> | `"osVersion"` | OS version string (e.g., the Windows version). |

> ### HTML Windows in the Default Platform Mode
>
> [HTML windows](https://docs.interop.io/desktop/capabilities/windows/window-management/overview/index.md#window_modes-html_windows) are now partially supported in the default [platform mode](https://docs.interop.io/desktop/developers/configuration/system/index.md#platform_modes) - you can define apps as HTML windows, but only the move area at the top of the window is supported and configurable and the HTML buttons aren't available. currently, only the OS buttons configurable via the `"useOSSystemButtons"` property of the `"details"` object in the [Web Groups App definition](https://docs.interop.io/desktop/developers/configuration/application/index.md#app_definition-web_group_app) can be used.
>
> Previously, when the different platform modes were introduced in **io.Connect Desktop** 10.0, HTML windows were available only in the advanced platform mode.
>
> To configure a web app as an HTML window, set the `"mode"` property of the `"details"` top-level key to `"html"` in the [app definition](https://docs.interop.io/desktop/developers/configuration/application/index.md):
>
> ```json
> {
>     "name": "my-html-app",
>     "type": "window",
>     "details": {
>         "url": "https://example.com/my-app",
>         "mode": "html"
>     }
> }
> ```
>
> The following move area properties are supported for HTML windows in the default platform mode: `"hasMoveAreas"`, `"moveAreaThickness"`, and `"moveAreaTopMargin"`. Currently, the rest of the properties for configuring the window move areas aren't supported for HTML windows in the default platform mode.

## Improvements & Bug Fixes

> - Upgraded to Electron 42.3.3 (Chromium 148).
>
> - Improved the mechanism for applying configurations from remote sources (REST and **io.Manager**) to enable overriding the platform logging configuration when the `logger.json` file is specified in a remote source.
>
> - Improved the platform log filtering to prevent logging of custom headers set via the `iodesktop.customHeaders.set()` method and extra headers configured via the `"extraHeaders"` property of the `"urlLoadOptions"` object in the app definitions of web apps in order to avoid exposure of sensitive data.
>
> - Improved handling case conversion of Layout context property names to prevent issues when exporting and importing Layouts.
>
> - Improved the Launcher UI for handling secondary actions for search results when a main action hasn't been defined. Now, if a main action isn't available, the secondary actions will be accessible by clicking directly on the result row - a context menu with the available secondary actions will appear on click and the row won't contain a three-dot menu.
>
> - Fixed an issue related to executing a protocol handler command when an instance of **io.Connect Desktop** hasn't been started yet.
