Skip to content

Releases: Redth/Maui.Gtk

v0.6.0 — libsecret SecureStorage

03 Mar 01:20

Choose a tag to compare

What's New

  • SecureStorage now uses libsecret (GNOME Keyring / freedesktop.org Secret Service) when available, with automatic fallback to AES-256 encrypted file storage
  • New LinuxSecureStorage.Backend property exposes the active backend ("libsecret" or "encrypted-file")
  • Sample app shows which SecureStorage backend is in use

Details

SecureStorage previously stored the AES encryption key as a plaintext file next to the encrypted data — security was file-permission based only. Now on GNOME desktops (and any system with a Secret Service provider), secrets are stored in the system keyring via libsecret P/Invoke. Systems without libsecret or a running keyring daemon fall back to the previous encrypted-file approach automatically.

v0.5.1

01 Mar 21:54

Choose a tag to compare

Fixes

  • Modal dialog sizing: Use SetSizeRequest on the content widget instead of SetDefaultSize on the window, so the requested dimensions describe the content area. GTK adds the CSD titlebar height automatically.

Full Changelog: v0.5.0...v0.5.1

v0.5.0

01 Mar 20:10

Choose a tag to compare

What's New

Native GTK4 Modal Dialog Windows (#9)

PushModalAsync now presents pages as native GTK4 modal windows by default — a real Gtk.Window with SetModal(true) and SetTransientFor(parent) — instead of inline widget swapping.

New GtkPage attached properties

Aligned with the macOS MacOSPage API from shinyorg/mauiplatforms:

Property Type Default Description
ModalPresentationStyle GtkModalPresentationStyle Dialog Dialog (native window) or Inline (legacy)
ModalSizesToContent bool false Measure MAUI content and size dialog to fit
ModalWidth / ModalHeight double -1 Explicit dialog size (-1 = match parent)
ModalMinWidth / ModalMinHeight double -1 Minimum size constraints

Examples

// Default — full-size native dialog:
await Navigation.PushModalAsync(new MyPage());

// Custom size:
GtkPage.SetModalWidth(page, 400);
GtkPage.SetModalHeight(page, 300);

// Sizes to content:
GtkPage.SetModalSizesToContent(page, true);
GtkPage.SetModalMinWidth(page, 250);

// Legacy inline:
GtkPage.SetModalPresentationStyle(page, GtkModalPresentationStyle.Inline);

Full Changelog: v0.4.0...v0.5.0

v0.4.0

27 Feb 19:49

Choose a tag to compare

What's New

Linux Packaging Support

Added MSBuild targets for producing Linux distribution packages from MAUI apps:

  • AppImagedotnet publish -r linux-x64 --self-contained -p:CreateAppImage=true
  • Debian (.deb)dotnet publish -r linux-x64 --self-contained -p:CreateDeb=true
  • Flatpakdotnet publish -r linux-x64 --self-contained -p:CreateFlatpak=true

All formats automatically use MAUI conventions (ApplicationId, ApplicationTitle, ApplicationDisplayVersion, MauiIcon) and auto-detect BlazorWebView/WebKitGTK dependencies.

See AppImage docs, Deb docs, and Flatpak docs for details.

v0.3.1 — Switch Styling Fix

26 Feb 22:45

Choose a tag to compare

Bug Fixes

🔘 Switch Control — Rounded Corners Restored

The Switch track was rendering with rectangular corners instead of its native GTK4 pill shape.

Root cause: The MapClip handler in GtkViewHandler was applying border-radius: 0; to every widget when no clip geometry was set. This blanket CSS override stripped the Adwaita theme's default rounded styling from the Switch (and potentially other widgets with theme-defined border-radius).

Fixes:

  • Removed the blanket border-radius: 0; from the null-clip path in MapClip — the theme's native styling is now preserved when no clip is set
  • Added border-radius: 9999px; to MapTrackColor CSS so custom track colors also preserve the pill shape

📄 Docs

  • Fixed asset link in README

Full Changelog: v0.3.0...v0.3.1

v0.3.0 — Multi-Window & Theme Support

23 Feb 00:34

Choose a tag to compare

What's New

🪟 Multi-Window Support

  • Application.OpenWindow() and Application.CloseWindow() now work — open and close additional windows at runtime
  • Full window lifecycle: Activated, Deactivated, Destroying events fire correctly
  • Window registry tracks all open windows with proper cleanup on close
  • Follows the same CreateWindow(activationState) pattern as WinUI and macOS backends

🎨 App Theme (Light/Dark Mode) Support

  • Force Light / Force Dark / Follow System — set Application.UserAppTheme to override or follow the desktop theme
  • Application.PlatformAppTheme correctly reports the system theme (Light or Dark) from GTK settings
  • AppThemeBinding / SetAppThemeColor respond to theme changes — UI updates automatically
  • System theme monitoring: if the desktop switches between light and dark, the app detects it and updates
  • Switches both the GTK prefer-dark-theme flag and the actual theme name (e.g. YaruYaru-dark)

🔧 Under the Hood

  • New GtkAppInfoImplementation registers with MAUI Essentials so AppInfo.RequestedTheme returns the correct system theme
  • GtkThemeManager separates system theme detection from app-level overrides (matches the iOS/macOS pattern where PlatformAppTheme always reflects the OS preference)
  • Removed broken variadic g_object_set P/Invoke (doesn't work on ARM64), uses GirCore property setters instead

📄 Sample Pages

  • Multi-Window Page — Open/Close buttons, window count display, secondary window with its own content
  • Theme Page — Force Light/Dark/System buttons, live theme status label, AppThemeBinding color demo

v0.2.4

20 Feb 15:05

Choose a tag to compare

What's New

Bug Fixes

  • Fix Shell flyout sidebar not rendering — The Shell flyout navigation sidebar was not visible when using ShellContent items directly under Shell (flyout mode). This happened because Shell.FlyoutIsPresented defaults to false (a mobile UX pattern), but on desktop GTK the sidebar should be shown by default. The Shell handler now auto-presents the flyout when it's enabled and has multiple items.

Upgrade Notes

Apps using Shell with direct ShellContent items (the default flyout pattern) will now correctly see a sidebar with navigation items on the left side of the window. Apps using TabBar are not affected.

v0.2.3 — Jitter-Free Layout & Scroll Fix

19 Feb 21:28

Choose a tag to compare

What's Changed

🏗️ CustomLayout Refactor — Jitter-Free Sizing

  • Replaced GTK's FixedLayout with a CustomLayout via P/Invoke (gtk_custom_layout_new), so children are allocated at their MAUI-arranged sizes directly during GTK's native layout phase — no more post-paint corrections that caused visible 1–2 frame jitter when scrolling or resizing.
  • Static native callbacks with instance tracking prevent GC delegate collection crashes.
  • New API: AddChild/RemoveChild/SetChildBounds/SetChildTransform replace Fixed.Put/Move internals.

🔧 ScrollView Scrolling Fix

  • Fixed scrolling not working after the CustomLayout refactor:
    • SetChildBounds now uses QueueResize() instead of QueueAllocate() so parent widgets (ScrolledWindow/Viewport) re-measure and discover the full content extent.
    • Set GTK Viewport scroll policy to NATURAL via P/Invoke, since our CustomLayout returns minimum=0 (to prevent window growth) but natural=content_height for correct scroll range.

📐 Layout & Sizing Improvements

  • Pages no longer auto-wrap content in a ScrollView — developers add ScrollView explicitly (matches iOS/Android behavior).
  • Scrollable views (ScrollView, CollectionView) no longer expand the window to their full content height.
  • CollectionView DataTemplate refactored to use the full MAUI handler pipeline (ToPlatform + MarkExternallyManaged).
  • Added Border, Frame, and ContentView support inside CollectionView DataTemplates.

Full Changelog

v0.2.2...v0.2.3

v0.2.2 — RefreshView, SwipeView & Animation Fixes

19 Feb 00:27

Choose a tag to compare

What's Changed

Bug Fixes

  • Animations now work visually — Fixed property mapper chain: 12 handlers were chaining from ViewHandler.ViewMapper (MAUI base) instead of GtkViewHandler.ViewMapper, so transform/opacity mappers were never invoked during animations. Also added RemoveAll<ITicker>() to ensure GtkPlatformTicker isn't overridden by MAUI's default.

    • TranslateTo, FadeTo, ScaleTo, RotateTo all verified working at ~60fps
    • Translation-only animations use Gtk.Fixed.Move() directly for reliability
  • RefreshView layout fixed — Removed SetVexpand(true) that caused RefreshView to consume all vertical space in a StackLayout. Added PlatformArrange override to size content correctly.

  • SwipeView cleaned up:

    • Action buttons now hidden at rest — only revealed as the card is dragged
    • Left actions show only when dragging right, right actions only when dragging left
    • Buttons hide again on snap-close and after action invoke
    • Added PlatformArrange for proper Fixed container sizing
  • Dark theme compatibility — Removed hardcoded light background colors from RefreshView item list and SwipeView card that were invisible in dark themes.

Other

  • Updated README with comprehensive feature parity tables (43 handlers, 20 Essentials services)
  • CI now auto-publishes NuGet packages on GitHub release creation

Full Changelog: v0.2.1...v0.2.2

v0.2.1 — Animation Fix & CI Improvements

19 Feb 00:05

Choose a tag to compare

What's Changed

Bug Fixes

  • Animations now work visually — Fixed two root causes:
    • 12 handlers had their property mapper chained from ViewHandler.ViewMapper (MAUI base) instead of GtkViewHandler.ViewMapper, so transform/opacity mappers were never invoked during animations
    • Added RemoveAll<ITicker>() before registering GtkPlatformTicker to ensure MAUI's default timer doesn't override ours
  • Translation-only animations use Gtk.Fixed.Move() directly for better reliability; rotation/scale still use Gsk.Transform

CI/CD

  • NuGet packages now auto-publish on GitHub release creation
  • Added release: published trigger to the build workflow

Verified Working

  • TranslateTo, FadeTo, ScaleTo, RotateTo — all animation types confirmed working at ~60fps
  • Combined/parallel animations work correctly

Full Changelog: v0.2.0...v0.2.1