# \[FAQ\] Migrating stickywindows.json to v10: properties mapping

**URL:** <https://community.interop.io/t/faq-migrating-stickywindows-json-to-v10-properties-mapping/645>\
**Category:** io.Connect Desktop\
**Tags:** FAQs, iocd-10, iocd-9, migration\
**Created:** [August 3, 2026, 8:51am UTC](https://community.interop.io/t/faq-migrating-stickywindows-json-to-v10-properties-mapping/645 "2026-08-03T08:51:31Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![bvalev](https://yyz2.discourse-cdn.com/flex028/user_avatar/community.interop.io/bvalev/32/382_2.png) [@bvalev](https://community.interop.io/u/bvalev)\
**Post date:** [August 3, 2026, 8:51am UTC](https://community.interop.io/t/faq-migrating-stickywindows-json-to-v10-properties-mapping/645/1 "2026-08-03T08:51:31Z")

</div>

> **Checked against** io.Connect Desktop 10.3.0 and its shipped configuration schema, with v9 behavior checked against 9.13.0. Defaults do move between releases, so confirm against the changelog for the version you’re upgrading to, and where the official docs cover a property, trust them over this post.

In io.Connect Desktop 10, `stickywindows.json` is no longer where window behavior is configured. The file still loads and still works, with a deprecation warning, but its settings have moved under `windowManagement` in `system.json`: some renamed, some pinned to values you can’t set anymore, some gone for good.

The [10.0 changelog](https://docs.interop.io/desktop/getting-started/changelog/10-0/index.html#breaking_changes-platform_configuration_files-ioconnect_window_configuration) doc lists the new keys, but not the old ones, and there’s no property-level migration guide, so finding out where a particular setting went means putting the two schemas side by side. Here’s that mapping for all 45 properties the v9 file accepted.

## Renamed properties

Same setting, new location under `windowManagement` in `system.json`.

| v9 `stickywindows.json` | v10 `windowManagement.*` |
| --- | --- |
| `enableStickiness` | `snapping.enabled` |
| `approachingDistance` | `snapping.approachingDistance` - 10–100, same meaning as v9: the distance at which approaching window edges highlight. Effective default is 30, though the schema description still cites the old v9 default of 50. |
| `edgeDistance` | `snapping.edgeDistance` - 2–10, default 4. v9 documented 0–10, so a kept `0` or `1` is reset to 4 with a warning. |
| `autoAlign` | `snapping.autoAlign` |
| `snapDistance` | `snapToScreenEdges.distance` - 5–30, default 20. Not available on macOS. |
| `snapToScreenEdges` | `snapToScreenEdges.enabled` - default `false`, and not available on macOS. The shape changed: a boolean in v9, an object with `enabled` and `distance` in v10. |
| `reverseAltSnapping` | `alternateBehavior.snapping.reverse` - default `false` |
| `reverseAltTabDrop` | `alternateBehavior.dropInTabGroup.reverse` - default `false` |
| `reverseAltWorkspaceDrop` | `alternateBehavior.dropInWorkspace.reverse` - default `false` |
| `groupType` | `group.type` - default is now `"Web"`; `"Classic"` also requires top-level `"advancedMode": true` |
| `groupMaximizedMode` | `group.externalResizeMode` - default `"Fill"` |
| `hideGroupCaption` | `group.header.hide` |
| `enableWindowGroupsCaptionEdit` | `group.header.editTitle` |
| `tabs.flatWhenSingle` | `group.tabs.flatWhenSingle` |
| `unlockWithLongMousePress` | `group.unlockOnLongMousePress.enabled` - default `true` |
| `unlockTimeout` | `group.unlockOnLongMousePress.timeout` - default 1000 |
| `unlockTolerance` | `group.unlockOnLongMousePress.tolerance` - default 5 |
| `enableWindowsCaptionEdit` | `editWindowTitle` |
| `collapseExpandMode` | `collapseExpand.mode` |
| `alignBordersWhenExpanding` | `collapseExpand.alignBottomBordersWhenExpanding` |
| `rendererTransparencyMode` | `transparencyControl.mode` - in the advanced platform mode, `"Auto"` resolves to `"Transparent"` with hardware acceleration off and `"Regions"` with it on; the default platform mode always uses `"Transparent"` |
| `rendererTransparencyKeyColor` | `transparencyControl.keyColor` - applies only when `mode` is `"KeyColor"` |
| `rendererHWTransparencyMode` | `hardwareAcceleration.transparency.mode` - `"UseRegions"` / `"UseNative"`, default `"UseRegions"` |
| `rendererHWTransparencyMouseRedirectMode` | `hardwareAcceleration.transparency.mouseEventRedirection` - `"UseRegions"` / `"UseRenderedContent"`, default `"UseRegions"` |
| `flydownShowDelay` | `flydownWindows.showDelay` |
| `flydownChangeDelay` | `flydownWindows.zoneChangeCallbackTimeout` |
| `flydownHideDelay` | `flydownWindows.hideDelay` |
| `flydownHideCheckInterval` | `flydownWindows.hideCheckInterval` |

One property moves outside `windowManagement` entirely:

| v9 `stickywindows.json` | v10 `system.json` |
| --- | --- |
| `minimumWindowSize` | Top-level `windows.minWidth` / `windows.minHeight` - a floor for windows that set no minimum of their own, overridable per app definition, honored while resizing a group. The floor is applied through the io.Connect window settings, so a native window that supplies its own size constraints may not pick it up - worth testing one rather than assuming. |

## Properties now fixed

These still exist internally but are pinned - remove them from your config, since nothing you set will apply.

| v9 property | Pinned to |
| --- | --- |
| `identity` | The computed `<region>-<env>` string. Already the case in late v9, where the file’s value was overridden anyway. Environment isolation now rides on top-level `region` / `env`. |
| `targetMode` | Derived from top-level `registerHtmlContainer` - default `false`, giving `"Glue"`. |
| `enableCrossProcess` | Always `true`. |
| `sizingMode` | Always `"Proportional"`. |
| `enableWindowGroupsDropShadow` | Always `true`. |
| `tabs.buttonsAlwaysVisible` | Always `true`, reversing the v9 default of `false` - tab buttons are no longer hover-only. |
| `qtWindowClassnameRegex` | Always `"Qt.*?QWindow.*?"`, the v9 default. |

## Properties dropped

| v9 property | What happened |
| --- | --- |
| `autoCollapse`, `autoRemoveWindows`, `groupCaptionHeight`, `groupBorderSize` | Deprecated in 10.0 and deleted when the config loads. |
| `autoSnap`, `autoArrange` | Dropped and already inert on 9.13, where the platform overwrote both to `true` right after loading the file, so whatever you set never applied. Snapping is governed by `snapping.enabled` and `snapping.autoAlign`. |
| `movingGroupsFromTopWindowOnly` | Dropped and already dead on 9.13, where it was parsed but never read. Removing it changes nothing. |
| `hideSwimlaneFrameCaption`, `enableSwimlaneFrameDropShadow` | Dropped with the legacy Canvas (“swimlane”) frames, and no `windowManagement` equivalent exists - the modern Workspaces frame ignores both keys. Both were already inert on 9.13 unless you ran the legacy Canvas frames. |

## Before and after

A representative v9 file:

```json
{
    "identity": "%IO_CD_REGION%-%IO_CD_ENV%",
    "targetMode": "Glue",
    "enableCrossProcess": true,
    "sizingMode": "Proportional",
    "enableWindowGroupsDropShadow": true,
    "enableStickiness": true,
    "approachingDistance": 30,
    "edgeDistance": 4,
    "autoAlign": true,
    "snapToScreenEdges": true,
    "snapDistance": 5,
    "groupType": "Classic",
    "groupMaximizedMode": "Fill",
    "hideGroupCaption": false,
    "enableWindowGroupsCaptionEdit": true,
    "enableWindowsCaptionEdit": true,
    "rendererTransparencyMode": "Auto",
    "rendererTransparencyKeyColor": "#FE0000",
    "minimumWindowSize": 100,
    "flydownShowDelay": 200,
    "flydownChangeDelay": 150,
    "flydownHideDelay": 400,
    "flydownHideCheckInterval": 100,
    "autoSnap": true,
    "autoArrange": true,
    "movingGroupsFromTopWindowOnly": false,
    "hideSwimlaneFrameCaption": true,
    "enableSwimlaneFrameDropShadow": true,
    "tabs": {
        "buttonsAlwaysVisible": true,
        "flatWhenSingle": false
    }
}

```

The same configuration in v10 `system.json`:

```json
{
    "advancedMode": true,
    "windows": {
        "minWidth": 100,
        "minHeight": 100
    },
    "windowManagement": {
        "snapping": {
            "enabled": true,
            "approachingDistance": 30,
            "edgeDistance": 4,
            "autoAlign": true
        },
        "snapToScreenEdges": {
            "enabled": true,
            "distance": 5
        },
        "transparencyControl": {
            "mode": "Auto"
        },
        "editWindowTitle": true,
        "flydownWindows": {
            "showDelay": 200,
            "zoneChangeCallbackTimeout": 150,
            "hideDelay": 400,
            "hideCheckInterval": 100
        },
        "group": {
            "type": "Classic",
            "externalResizeMode": "Fill",
            "header": {
                "hide": false,
                "editTitle": true
            },
            "tabs": {
                "flatWhenSingle": false
            }
        }
    }
}

```

Three things to notice. `"advancedMode": true` is what keeps `"Classic"` groups - without it the group type is forced to `"Web"`; if you don’t need classic groups or visual integration of native apps, drop both and stay in the default mode. `minimumWindowSize` lands in the top-level `windows` section, not under `windowManagement`. And `rendererTransparencyKeyColor` is gone, because under `"Auto"` the key color is never used - keep it only alongside an explicit `"mode": "KeyColor"`.

Several values above equal their v10 defaults and could be omitted; they’re spelled out to show the mapping.

## Defaults that changed

If a property was absent from your v9 file, you inherited the v9 default - and for these four the v10 default differs. Set them explicitly if the old behavior matters.

| Property | v9 default | v10 default | What you’ll notice |
| --- | --- | --- | --- |
| `snapToScreenEdges` → `snapToScreenEdges.enabled` | `true` | `false` | Windows no longer snap to screen edges. On late v9 the old file’s value was already being overridden, so check what you were actually running. |
| `groupType` → `group.type` | `"Classic"` | `"Web"` | Group decorations move from WPF and `themes.json` to HTML and CSS. |
| `groupMaximizedMode` → `group.externalResizeMode` | `"Proportional"` | `"Fill"` | Groups containing a size-restricted window resize differently. |
| `approachingDistance` → `snapping.approachingDistance` | `50` | `30` | Approaching window edges highlight later. |

The pinned values need the same check. The v9 config that shipped with the product already used them, so a file derived from it sees no change, but if you wrote a minimal file and let the v9 defaults apply, four of them flip: `enableCrossProcess` (`false` → always `true`), `sizingMode` (`"Single"` → always `"Proportional"`), `enableWindowGroupsDropShadow` (`false` → always `true`), and `tabs.buttonsAlwaysVisible` (`false` → always `true`). `targetMode` now resolves to `"Glue"` unless `registerHtmlContainer` is `true`, where the v9 default was `"Connect"`.

## Where each setting applies

A correctly migrated value can still look like it does nothing, because not every setting applies in every setup:

- `transparencyControl` and `flydownWindows` - available in advanced platform mode only.
- `collapseExpand` - classic groups in the advanced platform mode only.
- `snapToScreenEdges` - not available on macOS.
- Advanced mode itself is Windows-only. It’s recommended to enable it only if your use case requires using classic groups or visual integration of native apps, because doing so uses additional internal logic for processing native app windows which leads to overall performance disadvantages.

Two override rules matter once the file is in the right shape. `windowManagement` settings can be overridden per app from the app definition - with the documented exception of the window group settings - so a global value that appears ignored may be overridden downstream; `snapToScreenEdges` is the documented per-app example. And `hardwareAcceleration.enabled` is listed among the properties that “must be defined only locally and must not be overridden by any remote configuration source”, so setting it from a remote config store won’t work.

## Mistakes that look right, but aren’t

- **`group.externalResizeMode` is the successor of `groupMaximizedMode`, not of `sizingMode`.** Moving your `sizingMode` value into it silently changes how maximized groups resize. `sizingMode` needs no migration at all as it’s pinned.
- **`snapDistance` did not become `snapping.edgeDistance` or `snapping.approachingDistance`.** Its v9 description called it the distance at which windows snap together into a group, which makes `snapping.*` look like the right home - but by 9.13 that was no longer what the value did; it fed snapping to screen edges, which is what the v10 key controls. Not a change, despite appearances: the v9 description gave the range as 5–20, but the engine already accepted up to 30, the same 5–30 the v10 key declares.
- **Values that were valid in v9 are rejected outright in v10.** `"Default"` was accepted for `rendererTransparencyMode`, `collapseExpandMode`, and `groupMaximizedMode`, and `"None"` for the two hardware-transparency settings. None are valid for the corresponding `windowManagement` keys, and copying them across fails startup rather than being ignored. If you want the default, omit the property.
- **`transparencyControl.mode: "Auto"` no longer means the key-color mechanism.** That was v9 behavior with hardware acceleration off; it now resolves to `"Transparent"` there, and a migrated `keyColor` is ignored unless you explicitly set `"mode": "KeyColor"`. In the advanced platform mode with hardware acceleration on, `"Regions"` is used regardless of the configured mode - even an explicit `"KeyColor"` is overridden - so a key color can never take effect in that combination. Since `"Auto"` resolves per setup at startup, one shared transparency block works across configurations that differ on `hardwareAcceleration.enabled`. In the default platform mode none of this applies: the mode is forced to `"Transparent"` whatever you configure, even though hardware acceleration is forced on there.
- **`"Classic"` needs `advancedMode`, and the default doesn’t give it to you.** `advancedMode` defaults to `false`, and in that mode the group type is forced to `"Web"` whatever you configure - so a file migrated key-for-key still comes up with web groups unless `"advancedMode": true` is set at the top level of `system.json`. The only signal is an info-level log line: `forcing group type to 'Web' when in 'universal' mode`, where `'universal'` is the platform’s internal name for non-advanced mode.
- **`advancedMode: true` does not commit you to classic groups.** Platform mode and `group.type` are independent, and advanced mode with the default `"Web"` group type is a valid combination. The changelog sentence saying native windows can’t be snapped to io.Connect windows describes the _default_ mode only; advanced mode is what enables visual integration of native (Java, .NET) apps. Still worth choosing deliberately: classic groups are deprecated, won’t receive fixes, and the same changelog says they “will be entirely removed in a future release”.
- **Validation won’t catch a wrong key name.** Unknown properties in `system.json` only log warnings, so a misspelled key silently does nothing; a wrong _value_ (bad enum or type) fails startup instead. Two refinements: the warning-only path applies when _every_ validation error is an unknown-property error, so a typo combined with a bad enum value fails startup; and out-of-range numbers differ per key, because only some declare bounds in the schema. `snapToScreenEdges.distance: 3` fails validation, while `snapping.approachingDistance: 500` starts up and is clamped to the default with a warning.
- **Your old file may not be an accurate record of your v9 behavior.** `windowManagement` already existed in v9’s `system.json`, and on 9.13 it already won for several keys: `snapToScreenEdges` was taken from `windowManagement.snapToScreenEdges.enabled` (falling back to `false`) no matter what the old file said, `snapDistance` came from `.distance` whenever edge snapping was on, and the three ALT-reverse settings were overwritten unconditionally. `collapseExpandMode` and the unlock-on-long-press trio were overwritten whenever `system.json` set them. Read your v9 `system.json` alongside the old file before deciding what your baseline was.
- **Keeping `stickywindows.json` in place does not preserve all your old values.** For most settings the legacy file still acts as a fallback where you haven’t set the new key, but `snapToScreenEdges`, `collapseExpand`, and the `alternateBehavior` settings ignore it entirely and take the new defaults. A kept `"snapDistance": 5` therefore becomes 20, silently. Migrate the values instead of relying on the old file.

## Verifying your migration

On startup, `application.log` carries a line beginning `effective window management config:` - the fully resolved `windowManagement` section, and the fastest way to confirm a key took effect. The now-fixed values (`identity`, `sizingMode`, `enableCrossProcess`, and the rest) aren’t part of that section; they appear in the window engine’s own configuration dump in `bridge.log`, under the `SW-Config` logger. A legacy `stickywindows.json` that’s still present loads with a deprecation warning, and `windowManagement` values take precedence over it.

## Looking up your v9 values

The v9 schema, with every property’s default, is published at [assets/configuration/9-0/stickywindows.json](https://docs.interop.io/desktop/assets/configuration/9-0/stickywindows.json). The page documenting those properties is [io.Connect Windows configuration](https://docs.interop.io/desktop/developers/configuration/io-connect-windows/index.html) - note it’s scoped to the 9.0 stream, so it describes the old file, not the new one. The v10 keys live in the [system configuration reference](https://docs.interop.io/desktop/developers/configuration/system/index.html) under `windowManagement`.

**Applies to:** io.Connect Desktop 10.x, verified on 10.3.0; v9 behavior statements verified on 9.13.0.

---

<div class="post-metadata">

**Author:** ![toni.petrov](https://yyz2.discourse-cdn.com/flex028/user_avatar/community.interop.io/toni.petrov/32/17_2.png) [@toni.petrov](https://community.interop.io/u/toni.petrov)\
**Post date:** [August 3, 2026, 2:26pm UTC](https://community.interop.io/t/faq-migrating-stickywindows-json-to-v10-properties-mapping/645/2 "2026-08-03T14:26:45Z")

</div>

Listed on August 3, 2026, 2:26pm UTC


