Skip to content

Feature: frameless / custom-titlebar window support in blitz-shell (DOM-driven move, resize, window controls) #481

Description

@postadelmaga

Building a desktop app on dioxus-native with a borderless window (with_decorations(false)) to draw a custom titlebar, there is currently no way for the DOM to drive the window: dioxus-native never hands the winit Window to components, and blitz-shell (which owns the Window) has no built-in support for move/resize/min/max/fullscreen triggered from page content.

This is the equivalent of Electron's -webkit-app-region: drag / no-drag plus the usual window-control buttons. It seems like a natural fit for blitz-shell since it already owns the Window and the hit-testing.

What's missing

For a frameless window, an app needs:

  1. Move-drag from a titlebar region — start an OS window move when the user presses a draggable area.
  2. Resize-drag from edge/corner bands — start an OS resize, with the correct resize cursor on hover.
  3. Window controls — minimize / maximize-restore / fullscreen, triggered by in-DOM buttons (and ideally F11 for fullscreen).

All of these require calling winit methods (drag_window, drag_resize_window, set_minimized, set_maximized, set_fullscreen) that only the shell can reach.

Approach that works (happy to upstream as a PR)

We carry these as a local patch on blitz-shell in our project; it has held up well and is small/self-contained. The mechanism mirrors -webkit-app-region using data-* attributes the shell hit-tests before forwarding the event to the DOM:

  • Move-drag: on left mouse-press, walk up from the hit node; an element marked data-drag enables a window move, while a focusable element or one marked data-nodrag vetoes it (so buttons/inputs inside the titlebar still work). If enabled, call window.drag_window() and don't forward the press.
  • Resize-drag: when the cursor is within a small band (e.g. 6 logical px) of an edge/corner of an undecorated window, map it to a ResizeDirection, set the matching resize cursor on CursorMoved, and on press call window.drag_resize_window(dir).
  • Window controls: walk up from the hit node for data-minimize / data-maximize / data-fullscreen markers (no focusable veto — the trigger is itself a <button>) and call the corresponding winit method. F11 toggles Fullscreen::Borderless.

The frameless paths are gated on !window.is_decorated() so decorated windows are unaffected; the window-control markers work in both modes.

This is implemented entirely in window.rs (handle_winit_event + a few helpers) and needs no new public API surface beyond the attribute convention. I can open a PR if the maintainers are open to the data-* attribute approach — or adapt it to whatever convention you'd prefer (a dedicated CSS property, a config hook, etc.).

Would support for this be welcome in blitz-shell?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions