Baike.dev
All toolsAI codingTrendingOpen sourceNewsSubmit
Log in
Back to tool/Back to issues
#22239·Avalonia

X11 CSD: double-click on ElementRole="TitleBar" does not maximize/restore the window

Author: Lev02Created Sep 15, 2026Updated Sep 15, 2026
Labelsbug

On Linux (X11) with client-side decorations enabled (X11PlatformOptions.EnableDrawnDecorations = true and Window.ExtendClientAreaToDecorationsHint = true), double-clicking the title bar does not toggle WindowState between Normal and Maximized.

The same setup works on Windows and macOS.

The maximize button (PART_MaximizeButton / ElementRole="MaximizeButton") still works. Only the title-bar double-click gesture is missing.

Avalonia docs say that a control marked with WindowDecorationProperties.ElementRole="TitleBar" should get native drag and double-click-to-maximize automatically:

Mark an element as a title bar drag region using the WindowDecorationProperties.ElementRole attached property. The operating system handles drag and double-click-to-maximize behavior automatically.

On X11 CSD this second part is not implemented.

To Reproduce

  1. Create a desktop Avalonia app (12.1.0 or current master).
  2. Enable X11 drawn decorations:
AppBuilder.Configure<App>()
    .UsePlatformDetect()
    .With(new X11PlatformOptions
    {
        EnableDrawnDecorations = true,
    });
  1. Use a window with extended client area and a title-bar role, for example:
<Window ExtendClientAreaToDecorationsHint="True">
    <Border Height="32"
            Background="SteelBlue"
            WindowDecorationProperties.ElementRole="TitleBar" />
</Window>

(Default WindowDrawnDecorations with PART_TitleBar / ElementRole="TitleBar" reproduces it as well.) 4. Run on Linux under X11 (not WSL/WSLg). 5. Restore the window to WindowState.Normal. 6. Double-click the title bar (not the maximize button).

Avalonia version 12.1.0 (also present on current master in src/Avalonia.X11/X11Window.cs)

OS Linux / Debian / X11 (reproduced with EnableDrawnDecorations CSD). Windows and macOS are fine.

Expected behavior

Double-click on the title bar while Normal → WindowState.Maximized Double-click while Maximized → WindowState.Normal Single-click + drag still moves the window This is how Win32 (HTCAPTION) and macOS (DoubleClickHelper in Avalonia.Native.WindowImpl.ChromeHitTest) already behave.

Actual behavior

The window is dragged (or a drag is initiated). WindowState does not change.

Avalonia version

12.1.0

OS

Linux

Additional context

Root cause: in X11Window.ScheduleInput, a LeftButtonDown on chrome TitleBar immediately sends _NET_WM_MOVERESIZE with direction _NET_WM_MOVERESIZE_MOVE and returns, without checking for a double-click:

// Chrome hit-test for drawn decorations
if (NeedsDrawnDecorations
    && mouse.Type == RawPointerEventType.LeftButtonDown
    && _inputRoot is { } inputRoot)
{
    var chromeRole = inputRoot.HitTestChromeElement(mouse.Position);
    if (chromeRole is { } role)
    {
        var moveResizeSide = role switch
        {
            WindowDecorationsElementRole.TitleBar => NetWmMoveResize._NET_WM_MOVERESIZE_MOVE,
            // ... resize edges ...
        };
        if (moveResizeSide.HasValue)
        {
            SendNetWMMessage(_x11.Atoms._NET_WM_MOVERESIZE, ...);
            return; // event never reaches Avalonia input / DoubleTapped
        }
    }
}

There is no DoubleClickHelper usage in this file.

Why this breaks double-click

On Linux the application does not move its own window by changing X/Y. For CSD, the toolkit asks the window manager (GNOME/Mutter, KDE/KWin, etc.) to take over the pointer and move the window. That request is the EWMH client message _NET_WM_MOVERESIZE with direction MOVE.

Avalonia sends that message on the first click. After that:

the pointer is handed to the WM for a move operation; the second click of a double-click is no longer a title-bar double-click inside Avalonia; EWMH has no “double-click = maximize” message — the toolkit must detect the double-click itself and set _NET_WM_STATE / WindowState. macOS already does the right split in Avalonia.Native/WindowImpl.cs:

if (_doubleClickHelper.IsDoubleClick(e.Timestamp, e.Position))
{
    switch (WindowState)
    {
        case WindowState.Maximized or WindowState.FullScreen when _canResize:
            WindowState = WindowState.Normal;
            break;
        case WindowState.Normal when _canMaximize:
            WindowState = WindowState.Maximized;
            break;
    }
}
else
{
    _native.BeginMoveDrag();
}

Win32 maps TitleBar to HTCAPTION; DefWindowProc handles WM_NCLBUTTONDBLCLK.

Why an app-level DoubleTapped workaround does not work

Because ScheduleInput returns before _rawEventGrouper.HandleEvent, the click never enters Avalonia’s input pipeline. DoubleTapped on PART_TitleBar never fires.

The maximize button is unaffected: MaximizeButton is not mapped to NET_WM_MOVERESIZE*, so WindowDrawnDecorations.OnMaximizeButtonClick still toggles WindowState.

Suggested fix

Mirror the macOS ChromeHitTest logic in the X11 CSD path: on TitleBar + LeftButtonDown, if DoubleClickHelper.IsDoubleClick(...) then toggle WindowState (respecting CanMaximize / CanResize); otherwise send _NET_WM_MOVERESIZE_MOVE.

Source: AvaloniaUI/Avalonia

View original on GitHubView discussion on GitHub