Skip to content

Comments

Fix/linux toolwindow focus#1015

Merged
wieslawsoltes merged 2 commits intomasterfrom
fix/linux-toolwindow-focus
Jan 31, 2026
Merged

Fix/linux toolwindow focus#1015
wieslawsoltes merged 2 commits intomasterfrom
fix/linux-toolwindow-focus

Conversation

@wieslawsoltes
Copy link
Owner

Issue 1013 - Linux floating ToolWindow blocks TextBox focus

Context

Issue reported on January 31, 2026 for Linux (KDE, Wayland). Windows and macOS do not reproduce.

Reproduction (Linux)

  1. Open a tool window that contains a TextBox.
  2. Float the tool window.
  3. Focus the TextBox, then click outside to remove focus.
  4. Click the TextBox again. Focus does not return.

Investigation summary

  • ToolChromeControl uses different drag behavior per OS.
  • Windows and macOS attach a grip to HostWindow so drag starts only from the chrome grip.
  • Linux uses WindowDragHelper attached to the entire HostWindow (full window).
  • WindowDragHelper handles PointerPressed in the tunnel phase and sets e.Handled = true for any non-button control.
  • When the helper is attached to the whole window, TextBox clicks are consumed before focus can be set.
  • This matches the report: once focus is lost it cannot be regained.

Avalonia check

BeginMoveDrag in Avalonia (for example Avalonia/src/Avalonia.Native/WindowImpl.cs) forwards to platform APIs and does not alter focus handling. The focus loss is caused by Dock's Linux-specific drag helper placement, not Avalonia itself. The Linux-specific path exists to avoid inconsistent drag behavior when starting a move immediately on some Linux window managers.

Root cause

Dock's Linux branch attaches WindowDragHelper to the HostWindow and uses a permissive canStartDrag filter (only excludes buttons). This causes pointer presses on input controls (TextBox, etc.) to be handled as drag starts, blocking focus.

Fix applied

Keep the Linux full-window drag helper but prevent it from stealing focus:

  • Ignore focusable controls (TextBox, ComboBox, etc.) when deciding to start a drag.
  • Do not mark PointerPressed as handled until a drag is actually initiated (after the threshold).
// before (Linux)
_windowDragHelper = CreateDragHelper(hostWindow);

// after (Linux)
_windowDragHelper = CreateDragHelper(hostWindow, ignoreFocusable: true, handlePointerPressed: false);

The helper now checks for focusable ancestors and only handles the pointer once a drag begins.

Files changed

  • src/Dock.Avalonia/Controls/ToolChromeControl.axaml.cs
  • src/Dock.Avalonia/Internal/WindowDragHelper.cs

Alternative workarounds (if needed)

A) Restrict drag to the tool chrome grip (title bar only)

Attach the drag helper to PART_Grip instead of the full HostWindow. This matches the Windows/macOS behavior and fully avoids input interception.

  • Pros: Simple, low risk, no impact on control interactions.
  • Cons: You lose “drag anywhere” on Linux tool windows.
  • Sketch:
    _windowDragHelper = CreateDragHelper(Grip);

B) Exclude focusable controls (broader allowlist/denylist)

Keep full-window drag but expand canStartDrag to reject focusable controls and/or specific input types (TextBox, ComboBox, DatePicker, etc.). This avoids focus loss while keeping drag-anywhere.

  • Pros: Maintains drag-anywhere.
  • Cons: Requires ongoing maintenance for new control types; can miss custom focusable controls.
  • Sketch:
    if (source is IInputElement input && input.Focusable) return false;
    if (WindowDragHelper.IsChildOfType<TextBox>(owner, source)) return false;

C) Don’t handle PointerPressed until drag starts

Let pointer presses flow through to controls; only mark Handled when the drag threshold is exceeded and a drag begins.

  • Pros: Most general; works for all controls with no explicit denylist.
  • Cons: If a press begins a drag, some controls may still receive partial input; requires careful release handling.
  • Sketch:
    // Only set Handled once BeginMoveDrag is called.

D) Linux-only hybrid (current fix)

Combine A/B/C just for Linux: keep full-window drag, ignore focusable elements, and delay handling until drag begins. This preserves Linux drag-anywhere while preventing focus loss.

  • Pros: Fixes focus issue without removing drag-anywhere.
  • Cons: Still Linux-specific behavior; needs regression testing on different WMs/Wayland vs X11.
  • Sketch:
    _windowDragHelper = CreateDragHelper(hostWindow, ignoreFocusable: true, handlePointerPressed: false);

E) Use system chrome on Linux

Disable custom chrome for tool windows on Linux by leaving system decorations enabled.

  • Pros: Relies on WM behavior; avoids custom drag logic entirely.
  • Cons: Appearance mismatch across platforms; may limit styling.

Verification notes

  • Test on Linux (Wayland and X11) by floating a tool window containing a TextBox and verifying focus can be regained after it is lost.

Fixes #1013

@wieslawsoltes wieslawsoltes merged commit 0f6a7bf into master Jan 31, 2026
8 checks passed
@wieslawsoltes wieslawsoltes deleted the fix/linux-toolwindow-focus branch January 31, 2026 15:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Linux] Floating ToolWindow blocks Textboxes

1 participant