Skip to content

Comments

fix: window position drift on Windows multi-monitor setups#93

Closed
edospadoni wants to merge 1 commit intomainfrom
fix/window-position-drift-multimonitor-windows
Closed

fix: window position drift on Windows multi-monitor setups#93
edospadoni wants to merge 1 commit intomainfrom
fix/window-position-drift-multimonitor-windows

Conversation

@edospadoni
Copy link
Member

Summary

Fixes NethLink and PhoneIsland windows gradually drifting off-position on Windows with multiple monitors:

  • NethLink shifted ~1-2px upward on every show/hide cycle
  • PhoneIsland shifted on both axes by several pixels per call, eventually disappearing off-screen

This only occurred on Windows multi-monitor setups — macOS, Linux, and single-monitor Windows were unaffected.

Root causes

  1. PhoneIsland double setBounds() calls: showPhoneIsland() first called resize() which did setBounds({ width, height }) (no x/y), then separately called setBounds({ x, y }) (no width/height). On Windows with per-monitor DPI awareness, each partial call triggers coordinate rounding, and the omitted fields get filled from the current (already-rounded) state — accumulating drift on every cycle.

  2. NethLink DPI rounding accumulation: The getBounds() → save → setBounds() cycle introduces fractional pixel rounding errors when Windows converts between logical and physical coordinates at non-100% scale factors (e.g., 125%, 150%).

  3. Drag handler size mismatch: updateWindowPosition() used getContentSize() (inner area, excluding title bar and window frame) but passed the result to setBounds() which expects outer window dimensions — causing the window to effectively shrink each drag.

Changes

  • PhoneIslandController.ts: Combined the two partial setBounds() calls into a single setBounds({ x, y, width, height }) with the full rectangle. Added Math.round() when saving position in hidePhoneIsland().
  • NethLinkWindow.ts: Added Math.round() on all coordinate values in saveBounds() to prevent rounding error accumulation.
  • ipcEvents.ts: Replaced getContentSize() with getBounds() in the drag handler for non-PhoneIsland windows.

@github-actions
Copy link

Automatic builds from https://github.com/NethServer/nethlink/actions/runs/22137682879.
Commit: bfe8d04

Name Platform Link
win-app.exe Windows (x64) Link
macos-app-x64.dmg MacOS (x64) Link
macos-app-arm64.dmg MacOS (arm64) Link
linux-app.AppImage Linux (x64) Link

@edospadoni edospadoni force-pushed the fix/window-position-drift-multimonitor-windows branch from bfe8d04 to f402081 Compare February 18, 2026 11:43
@github-actions
Copy link

Automatic builds from https://github.com/NethServer/nethlink/actions/runs/22138346670.
Commit: f402081

Name Platform Link
win-app.exe Windows (x64) Link
macos-app-x64.dmg MacOS (x64) Link
macos-app-arm64.dmg MacOS (arm64) Link
linux-app.AppImage Linux (x64) Link

@edospadoni edospadoni force-pushed the fix/window-position-drift-multimonitor-windows branch from f402081 to 7dbee76 Compare February 18, 2026 13:04
@github-actions
Copy link

Automatic builds from https://github.com/NethServer/nethlink/actions/runs/22140892022.
Commit: 7dbee76

Name Platform Link
win-app.exe Windows (x64) Link
macos-app-x64.dmg MacOS (x64) Link
macos-app-arm64.dmg MacOS (arm64) Link
linux-app.AppImage Linux (x64) Link

@edospadoni edospadoni force-pushed the fix/window-position-drift-multimonitor-windows branch from 7dbee76 to 5c1e803 Compare February 18, 2026 13:29
@github-actions
Copy link

Automatic builds from https://github.com/NethServer/nethlink/actions/runs/22141731612.
Commit: 5c1e803

Name Platform Link
win-app.exe Windows (x64) Link
macos-app-x64.dmg MacOS (x64) Link
macos-app-arm64.dmg MacOS (arm64) Link
linux-app.AppImage Linux (x64) Link

@edospadoni edospadoni force-pushed the fix/window-position-drift-multimonitor-windows branch from 5c1e803 to 08ec0f0 Compare February 18, 2026 14:18
@github-actions
Copy link

Automatic builds from https://github.com/NethServer/nethlink/actions/runs/22143418934.
Commit: 08ec0f0

Name Platform Link
win-app.exe Windows (x64) Link
macos-app-x64.dmg MacOS (x64) Link
macos-app-arm64.dmg MacOS (arm64) Link
linux-app.AppImage Linux (x64) Link

@edospadoni edospadoni force-pushed the fix/window-position-drift-multimonitor-windows branch from 08ec0f0 to bda77ec Compare February 18, 2026 14:40
@github-actions
Copy link

Automatic builds from https://github.com/NethServer/nethlink/actions/runs/22144220329.
Commit: bda77ec

Name Platform Link
win-app.exe Windows (x64) Link
macos-app-x64.dmg MacOS (x64) Link
macos-app-arm64.dmg MacOS (arm64) Link
linux-app.AppImage Linux (x64) Link

@edospadoni edospadoni force-pushed the fix/window-position-drift-multimonitor-windows branch from bda77ec to e54489f Compare February 18, 2026 16:25
@github-actions
Copy link

Automatic builds from https://github.com/NethServer/nethlink/actions/runs/22148118038.
Commit: e54489f

Name Platform Link
win-app.exe Windows (x64) Link
macos-app-x64.dmg MacOS (x64) Link
macos-app-arm64.dmg MacOS (arm64) Link
linux-app.AppImage Linux (x64) Link

On Windows with mixed DPI monitors (e.g. laptop at 125% + external at
100%), the PhoneIsland window drifted progressively on each call cycle,
eventually disappearing off-screen.

Root cause confirmed via diagnostic logging: calling setBounds() with
zero dimensions ({width:0, height:0}) causes Chromium on Windows to
multiply the window position by the primary display's scaleFactor.
Each resize(0,0) at call end shifted coordinates by exactly 1.25x:

  x=150 → 187 → 233 → 291 → 363 → 453 (×1.25 each cycle)

Additionally, showPhoneIsland() called resize() first (showing the
window at the wrong position) then repositioned with a second
setBounds(), causing a visible "trail" artifact.

Changes:
- PhoneIslandController.resize(): skip setBounds entirely when
  dimensions are 0x0, just hide directly. Always pass full rect
  {x, y, width, height} for non-zero resizes.
- PhoneIslandController.showPhoneIsland(): set position and size in a
  single setBounds() call BEFORE show(), eliminating the visual trail.
  Only fall back to resize()+center() when no saved position exists.
- ipcEvents.ts drag handler: use getBounds() instead of
  getContentSize() to get correct outer window dimensions.
@edospadoni edospadoni force-pushed the fix/window-position-drift-multimonitor-windows branch from e54489f to f43dbe4 Compare February 19, 2026 13:13
@github-actions
Copy link

Automatic builds from https://github.com/NethServer/nethlink/actions/runs/22183239235.
Commit: f43dbe4

Name Platform Link
win-app.exe Windows (x64) Link
macos-app-x64.dmg MacOS (x64) Link
macos-app-arm64.dmg MacOS (arm64) Link
linux-app.AppImage Linux (x64) Link

@tonyco97 tonyco97 closed this Feb 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants