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

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 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:

{
    "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:

{
    "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
snapToScreenEdgessnapToScreenEdges.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.
groupTypegroup.type "Classic" "Web" Group decorations move from WPF and themes.json to HTML and CSS.
groupMaximizedModegroup.externalResizeMode "Proportional" "Fill" Groups containing a size-restricted window resize differently.
approachingDistancesnapping.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. The page documenting those properties is io.Connect Windows configuration - 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 under windowManagement.

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

1 Like