Skip to content

lys-ui completeness ​

The capability map against relm4, GTK4 and libadwaita: what lys-ui ships per area and where it lives. Known gaps are listed at the end; anything not listed there is shipped. The standing non-goals and their reasons live in architecture.md.

Framework ​

relm4 / GTKlys-uiWhere
relm4::Application, ApplicationWindowapp.Application (one loop for every window), app.Window, app.LayerWindowapp/application.go, application-model.md
main-thread contract, glib::timeout_addone loop goroutine; Application.Invoke, Every; the off-loop mutation guardapp/invoke.go, widget/thread.go, threading.md
Component, Controller, RelmApp::run, dialog componentscomponent.Component[In, Out], Context, Controller (Forward, ForwardTo, Detach, State() watcher: typed state observation after each update batch, no copy per notification), component.Run/Window/Layer/Dialog/Popover; headless tests with componenttest.Loopcomponent/, components.md
view!, #[name], #[watch] setters, #[relm4::widget_template]ui: a generated typed builder per widget (setters, Watch*, hooks, Bind*, adders), Ref, Column/Row, If, Match, Each, Use; templates are functions; ui.Mount/ui.Buildui/, internal/uigen, components.md
Command, oneshot_command, spawn_command, AsyncComponentContext.Oneshot, Spawn, Context() (cancelled at shutdown); Loader (loading view, Load off the loop, held input); Context.Await/Busy for awaiting updatescomponent/command.go
FactoryVecDeque, FactoryHashMap, FactoryComponent, AsyncFactoryComponent, DynamicIndex, FactoryView, FixedPositioncomponent.Factory[C, In, Out] of item components with in-place edits (async items through Loader: loading view first, input held, mapped to relm4's AsyncFactoryComponent), KeyedFactory[K, ...], Index, BoxView/FlowBoxView/StackView/NotebookView/GridView/FixedView/ListBoxViewcomponent/factory.go, component/keyed.go, component/views.go
Worker, detach_workercomponent.Worker[In, Out] on its own goroutine, LaunchWorker (top-level or owned by a component), WorkerControllercomponent/worker.go
tracker::track, #[watch], #[track]Context.Tracked (*Tracked[T], cleared after each refresh), Context.Watch, Context.Trackcomponent/tracked.go
MessageBroker, SharedState, Reducerapp.Stream[Msg], app.SharedState[T], app.Reducer[S, M]app/message.go
relm4 binding modulewidget.Binding[T] + the widget Bind* connectorswidget/binding.go
GApplication single instance, command-line, openapp.ClaimInstance + InstanceConfig hooksapp/instance.go
GSettingsapp.NewSettings + typed Key[T], persisted atomicallyapp/settings.go
gettext (gettext, ngettext, pgettext, catalogs, locales)i18n: pure-Go .mo/.po parsing, Plural-Forms, contexts, Locales(), Load/LoadSystem; widget.SetMessageCatalog, Tr, TrN, TrCtx for built-in and app stringsi18n/, widget/message.go
RelmAction, RelmActionGroup, menu!, set_accels_for_actiontyped widget.Action, ParamAction[P] and StateAction[S] (Toggle, Target); ActionItem/CheckItem/RadioItem menu rows; BindAction on buttons and toggles; AddAccel (chords) and subtree-scoped AddScopedAccelwidget/action.go, app/accel.go
library logginginjectable *slog.Logger (app.SetLogger), silent by defaultinternal/logutil
GTK inspectorLYS_UI_INSPECT=1, Application.SetInspect, widget.DumpTreeapp/inspect.go, inspector.md

Widgets ​

relm4 / GTK / adwlys-uiWhere
Label, styled textLabel (UAX #14 wrap, start/middle/end ellipsize), RichLabel (markup, links)widget/label.go, widget/richlabel.go
Button, ToggleButton, CheckButton, Switch, radio groupsButton (any child), ToggleButton, CheckButton, Switch; toggles and checks join radio groupswidget/button.go, widget/toggle.go, widget/radio.go
Scale, ProgressBar, LevelBar, SpinButtonSlider, ProgressBar, ProgressRing (circular, with a centred child), LevelBar, SpinButtonwidget/slider.go, widget/progressbar.go, widget/progressring.go, widget/levelbar.go, widget/spin.go
Entry, PasswordEntry, SearchEntry, EditableLabelEntry (selection, clipboard, IME, EchoPassword/EchoNone), SearchEntry, SearchBar, ComboEntry + completion, EditableLabelwidget/entry.go, widget/echo.go, widget/search.go, widget/completion.go, widget/editablelabel.go
undo/redobounded coalescing stack shared by Entry and TextAreawidget/undo.go
TextView, SourceViewTextArea (soft wrap, Tab trap), code view (line numbers, highlighters, auto-indent); highlight: TOML, Go, JSON, YAML, Markdown, Adwaita schemeswidget/textarea.go, widget/codeview.go, highlight/
DropDown, ComboBoxDropdown, DropdownOf[T], NewDropdownRows (icons, headers); type-aheadwidget/dropdown.go
widget layout properties (hexpand, vexpand, halign, valign, margin-*, set_size_request, max-width/max-height)SetHExpand/SetVExpand (propagated like GTK's computed expand), SetHAlign/SetVAlign, SetMargin, SetSizeRequest and SetMaximumSize (clipping what overflows) on every widget, honored by the containerswidget/layoutprops.go
Box, CenterBox, Stack, Overlay, ScrolledWindowBox, CenterBox, Stack (transitions), Overlay, Scroll (kinetic, RevealRect, smooth scrolling, snap, overscroll chaining), Scrollbarwidget/box.go, widget/centerbox.go, widget/containers.go, widget/scrollbar.go
Grid, FlowBox, adw WrapBox, FixedGrid (spans, squeeze to the children's minimums), FlowBox, NewWrapBox, Fixed (children at explicit (x, y) logical pixels, natural size, union measurement)widget/grid.go, widget/flowbox.go, widget/fixed.go
Paned, Frame, AspectFrame, Revealer, Expander, SizeGroupthe same nameswidget/paned.go, widget/frame.go, widget/revealer.go, widget/expander.go
NotebookNotebook: close hook, reorder by drag, overflow scrollingwidget/notebook.go
adw ToolbarViewToolbarView: top and bottom bar stacks, sliding reveal, flat/raised/raised-border styles, content extending under the barswidget/toolbarview.go
adw TabView, TabBar, TabOverviewTabView (pages with title, icon, loading, indicator, attention, pinned; close veto; transfer between views), TabBar (select, close, drag to reorder or move to another window's bar), TabOverview (thumbnail grid); Application.AttachTabView binds ctrl+Tab, ctrl+PageUp/Down, alt+1..9widget/tabview.go, widget/tabbar.go, app/chrome.go
ListView, GridView, ColumnView, TreeExpander, TypedListView/TypedGridView, ListBoxvirtualized List (none/single/browse/multiple selection, rubber band), virtualized GridView (min/max columns, 2D keyboard motion, gridview > child), ColumnView[T] (sort, filter stack), FlatTree[T]; typed TypedList[T]/TypedGrid[T] over TypedItems[T] (widget recycling: Setup once, Bind per item, Unbind; InsertSorted; filter stack; typed selection), non-virtual ListBox (selection modes, activation, keyboard navigation, filter/sort/header functions, placeholder)widget/list.go, widget/gridview.go, widget/columnview.go, widget/tree.go, widget/typedview.go, widget/listbox.go
PopoverMenu, PopoverMenuBarMenu (check/radio, submenus, mnemonics, accels), MenuBarwidget/menu.go, widget/menubar.go
adw WindowTitle, adaptive AdwDialogWindowTitle (title and subtitle pair); Application.AdaptiveDialog: a parented dialog over a wide parent, a bottom sheet inside a narrow one (or forced either way), with the dialog card, responses and cancel-on-dismisswidget/windowtitle.go, app/adaptivedialog.go
HeaderBar, WindowControls, ActionBarthe same names; Application.AttachHeaderwidget/chrome.go, app/chrome.go
Popoverapp.Popover, anchored to any widget, on toplevels and layer surfacesapp/popover.go
Dialog, MessageDialog, AlertDialogapp.Dialog, MessageBox, PromptDialog, ProgressDialog; modality through xdg-dialog-v1app/dialog.go, app/prompt.go
FileDialogApplication.OpenFileDialog, OpenFilesDialog, OpenFolderDialog, SaveFileDialog (pure-Go picker, XDG recents); relm4-components' OpenButton is Application.NewOpenButton (label, filters, folder mode, recent-files dropdown over the shared store)app/filedialog.go, app/openbutton.go, widget/filechooser.go
ColorDialogButton, FontDialogButton, InscriptionColorButton (opens a SwatchPicker popover of ColorSwatch presets, a custom row and the full ColorChooser in place) and FontButton (Application.AttachFontButton opens the chooser); BindColor/BindFont; Inscription (sized by character and line counts)widget/dialogbuttons.go, widget/colorswatch.go, widget/inscription.go, app/chrome.go
ColorDialog, FontDialog, Calendar, EmojiChooserColorChooserDialog, FontChooserDialog, CalendarDialog, EmojiChooserapp/dialog.go, app/emojichooser.go
adw AboutDialogApplication.AboutDialogapp/about.go
ShortcutsWindowShortcutsView + Application.ShortcutsDialog from the accelerator registrywidget/shortcuts.go, app/accel.go
adw ToastToast + Application.ShowToast (stacking, action, hover pause)widget/toast.go, app/toast.go
TooltipSetTooltip and SetTooltipMarkup on any widget; Application.SetTooltipOptions for every windowwidget/widget.go, app/tooltip.go
GLAreawidget.GPUArea: application-rendered dmabufs (zero copy, async import checked against the advertised formats) or CPU images, on a subsurface below the window, paced by OnFramewidget/gpuarea.go, app/gpuarea.go, lys-lib/dmabuf/
Video, MediaControls, MediaStream, MediaFilewidget.Video (fit policies, controls on hover or pause, autoplay), widget.MediaControls, media.Stream (play, pause, seek, loop, volume, mute, audio-clocked sync); sources: animated images, YUV4MPEG2 in pure Go, any file through an ffmpeg subprocess; sound through the PulseAudio protocolmedia/, widget/video.go, widget/mediacontrols.go
Spinner, Separator, Image, IconSpinner, NewSeparator, Image (fit/cover, async decode, PNG/JPEG/GIF/WebP, animated GIF/APNG), Icon (theme, file, SVG, symbolic tint, bundled Lucide fallback)widget/spinner.go, widget/separator.go, widget/image.go, widget/icon.go
DrawingArea, GestureStylusDrawingArea (OnDraw, OnStylus); relm4 DrawHandler as DrawSurface: a retained backing canvas (incremental Draw, damage limited to the touched rect, resize keeps content, rescale reallocates and calls OnResize)widget/drawingarea.go, widget/drawsurface.go
adw PreferencesDialogwidget.PreferencesView (page switcher, search over every searchable row's title and subtitle with jump-to-row results, subpages) in Application.PreferencesDialog with AddToastwidget/prefsview.go, app/dialog.go
adw PreferencesPage/Group, ActionRow familyPreferencesPage, PreferencesGroup, ActionRow, SwitchRow, SpinRow, ComboRow, EntryRow, ButtonRow, ExpanderRowwidget/prefs.go, widget/actionrow.go, widget/controlrows.go
adw NavigationView, NavigationSplitView, OverlaySplitView, Carousel, ViewSwitcher, StackSwitcher, Clamp, BreakpointBinthe same names; one breakpoint enginewidget/navigation.go, widget/adaptive.go
adw Banner, BottomSheet, StatusPage, Avatar, SplitButton, ButtonContent, ToggleGroupthe same nameswidget/adw.go, widget/sheet.go
drag and dropDragSource/DragEnterer per widget, action negotiation, cross-windowwidget/input.go, app/dragdrop.go
GestureClick, EventControllerScrollSetOnPointer (any button, click count, modifiers) and SetOnScroll (steps, modifiers) on every widget; List.OnPointer/OnScroll with the rowwidget/pointerhook.go, widget/list.go
modern components (no GTK counterpart)Accordion, Alert, Badge, Breadcrumb, Chart, Combobox, DataTable, DatePicker, Form, HoverCard, InputOTP, Pagination, Sidebarwidget/accordion.go, widget/alert.go, widget/display.go, widget/breadcrumb.go, widget/chart.go, widget/combobox.go, widget/datatable.go, widget/datepicker.go, widget/form.go, widget/hovercard.go, widget/inputotp.go, widget/pagination.go, widget/sidebar.go
shell parts (no GTK counterpart)Bar (start, center and end zones along an edge, turning with SetEdge), BarButton, BarSeparator, SegmentIndicator, app.NewBar; FloatingPanel (drag, resize, confinement, input-region pass-through via InputRegioner); Card; Chip and the drag-reorderable ChipBoxwidget/bar.go, app/bar.go, widget/floatingpanel.go, widget/card.go, widget/chip.go
RTL/bidiUAX #9 in every text path; Direction on text widgets, menus, dropdowns and Boxlys-lib's text, widget/direction.go

Text, rendering and theming ​

Arealys-uiWhere
renderingpremultiplied ARGB8888, signed-distance AA, damage-clipped repaint, gradients (linear, radial, conic, repeating)lys-lib/render/
GPU renderinga Vulkan renderer into dmabufs through lys-lib's gpu, chosen by LYS_UI_RENDERER (auto, gpu, cpu), on the CPU where it cannot openapp/gpurender.go, lys-lib/gpu/
fontssystem lookup (app.Font, FontWeighted, FontFamilies), per-rune fallback chains, color emoji (CBDT/sbix, COLRv0/v1, OT-SVG), variable fontsapp/fonts.go, lys-lib/render/, internal/sysfont
themingtyped Theme palette with copying With*, dark/light/high-contrast presets, WCAG guardwidget/theme.go
CSSGTK-flavored stylesheets above the palette: selectors, @define-color, transitions, @keyframes, hot reload; stylesheet files loadable at chosen priorities (AddStylesheetFile) with one shared pollerinternal/style, widget/style.go, css.md
glass surfacesthe css.Glass, css.LiquidGlass and css.Frosted style classes; behind-window and behind-popover blur through ext_background_effect_v1 (WindowConfig, LayerConfig and PopoverConfig.BackgroundBlur)widget/adwaita.go, app/surfacehints.go, internal/blursync, cmd/lys-ui-glass
GTK settingsgtksettings: GTK 4's settings.inigtksettings/
icon themesfreedesktop spec in pure Go, live icon-theme following; icontheme for programs that draw icons without widgetsinternal/icons, icontheme/, icons.md
accessibilitysemantic roles, keyboard-first guarantee, in-process AT-SPI bridgewidget/a11y.go, internal/atspi, a11y.md
animation (adw::TimedAnimation, SpringAnimation)anim: tweens, easing curves, springs, Sequence/Parallel/Delay timelines, reduced motionanim/, internal/animclock

Protocols and platform ​

Arealys-uiWhere
windowsxdg-shell toplevels (close veto, resize edges, min/max, maximize, fullscreen per output, transient parents, move/resize grabs), wlr-layer-shell surfacesinternal/window, internal/layersurface, app/windowctl.go
decorationsxdg-decoration when the compositor decorates; HeaderBar is the explicit client-side opt-ininternal/window, application-model.md
window iconsxdg-toplevel-icon-v1app/windowicon.go
surface hintscontent type, live opacity (alpha-modifier), error bell, wm_capabilitiesapp/surfacehints.go
keyboardthe compositor's xkb keymap, synthesized repeatinternal/wlsession
IMEzwp_text_input_v3 into Entry and TextArea, popovers includedinternal/wlsession/textinput.go
pointer, cursorscursor-shape-v1 with xcursor fallback, pointer constraints, relative motioninternal/wlsession, app/constraints.go
touch, gestures, tabletswl_touch with pointer emulation, pointer-gestures, tablet-v2 stylus samplesinternal/wlsession, widget/touch.go
fractional scalewp_viewporter + wp_fractional_scale_v1, live rescale; integer fallbackinternal/scale
clipboardwl_data_device + primary selection; text, images, URIs, HTMLapp/clipboard.go, transfer/
clipboard managersext-data-control-v1, wlr-data-control fallbackapp/datacontrol.go
taskbars, launcherswlr-foreign-toplevel-management, xdg-activation, OpenURL/OpenPath (portal, xdg-open fallback); xdg-foreign v2 exports every toplevel so portal dialogs parent to itinternal/wlsession, app/launcher.go
idleidle inhibit, ext-idle-notify-v1 (OnIdle)app/application.go
shortcutskeyboard-shortcuts-inhibit, GlobalShortcuts portalinternal/wlsession, app/globalshortcuts.go
printing (GtkPrintDialog, GtkPrintOperation)Application.Print through the Print portal, ExportPDF; pages painted as rasters into a PDF by pdfapp/print.go, pdf/
session, backgroundInhibit portal (Inhibit, OnSessionStateChange with query-end), Background portal (RequestBackground, SetBackgroundStatus)app/portals.go
lock screensext-session-lock-v1 (LockSession, every output, hotplug)app/sessionlock.go
notificationsApplication.Notify with actionsapp/notification.go
screen capturecapture: wlr-screencopy, ext-image-copy-capture, Hyprland toplevel export, dmabuf importlys-lib/capture/
file and fd watchingWatchFiles, WatchFD on the loopapp/watch.go
compositor restartstyped disconnect, clean exit code 75, optional reconnect with rebuildapp/disconnect.go, app/reconnect.go
system appearance (adw::StyleManager)Application.ColorScheme, Accent, Contrast with loop-delivered On*Change hooks; types in appearanceapp/appearance.go, appearance/, appearance.md

Known gaps ​

  • The AT-SPI bridge has no Selection or Table interfaces and reports no text attributes (a11y.md).
  • Tablet pads are not bound (input-model.md).
  • The CSS engine's limits are listed in css.md.

Sway and Hyprland are both required CI gates. Sway runs the full compositor-in-the-loop suite; Hyprland runs internal/headlesstest without the restart test, as its VM boots Hyprland once.

Released under the MIT License.