core/titlebar/titlebar.go
Functions
func AccessibilityActions
func (w *Widget) AccessibilityActions() []a11y.Action {
return nil
}
func AccessibilityHint
AccessibilityHint returns the window title as a hint.
func (w *Widget) AccessibilityHint() string {
return w.cfg.title
}
func AccessibilityLabel
AccessibilityLabel returns "Title Bar".
func (w *Widget) AccessibilityLabel() string {
return a11yLabel
}
func AccessibilityRole
AccessibilityRole returns [a11y.RoleBanner].
func (w *Widget) AccessibilityRole() a11y.Role {
return a11y.RoleBanner
}
func AccessibilityState
AccessibilityState returns the accessibility state.
func (w *Widget) AccessibilityState() a11y.State {
return a11y.State{
Disabled: !w.IsEnabled(),
Hidden: !w.IsVisible(),
}
}
func AccessibilityValue
AccessibilityValue returns an empty string.
func (w *Widget) AccessibilityValue() string {
return ""
}
func Children
Children returns all child widgets (leading + center).
func (w *Widget) Children() []widget.Widget {
var children []widget.Widget
for _, child := range w.cfg.leading {
if child != nil {
children = append(children, child)
}
}
for _, child := range w.cfg.center {
if child != nil {
children = append(children, child)
}
}
if len(children) == 0 {
return nil
}
return children
}
func Draw
Draw renders the title bar background, child widgets, and control buttons.
func (w *Widget) Draw(ctx widget.Context, canvas widget.Canvas) {
if !w.IsVisible() {
return
}
bounds := w.Bounds()
// Draw background.
w.painter.DrawBackground(canvas, bounds, BackgroundState{
Focused: w.cfg.focused,
})
// Draw children with transform offset.
canvas.PushTransform(bounds.Min)
// Draw leading children.
for _, child := range w.cfg.leading {
if child == nil {
continue
}
widget.StampScreenOrigin(child, canvas)
child.Draw(ctx, canvas)
}
// Draw title text if no center children and title is set.
if len(w.cfg.center) == 0 && w.cfg.title != "" {
controlsWidth := w.controlsZoneWidth()
titleBounds := geometry.NewRect(0, 0, bounds.Width()-controlsWidth, bounds.Height())
canvas.DrawText(w.cfg.title, titleBounds, titleFontSize, defaultControlFg, false, widget.TextAlignCenter)
}
// Draw center children.
for _, child := range w.cfg.center {
if child == nil {
continue
}
widget.StampScreenOrigin(child, canvas)
child.Draw(ctx, canvas)
}
// Draw control buttons.
if w.cfg.chrome != nil {
for i := 0; i < controlCount; i++ {
ct := w.controlTypeForIndex(i)
w.painter.DrawControlButton(canvas, w.controlBounds[i], ct, ControlState{
Hovered: w.controlStates[i] == stateHover,
Pressed: w.controlStates[i] == statePressed,
})
}
}
canvas.PopTransform()
}
func Event
Event handles input events for the title bar and its children.
func (w *Widget) Event(ctx widget.Context, e event.Event) bool {
if !w.IsVisible() || !w.IsEnabled() {
return false
}
switch ev := e.(type) {
case *event.MouseEvent:
return w.handleMouseEvent(ctx, ev)
default:
// Dispatch to child widgets.
return w.dispatchToChildren(ctx, e)
}
}
func HasChrome
HasChrome reports whether a WindowChrome is available.
func (w *Widget) HasChrome() bool {
return w.cfg.chrome != nil
}
func HitTest
HitTest returns what region of the title bar a screen-space point falls in.
This is intended to be called from a hit-test callback registered with the
window system.
func (w *Widget) HitTest(x, y float64) HitTestResult {
pt := geometry.Pt(float32(x), float32(y))
screenBounds := w.ScreenBounds()
// Not in title bar at all.
if !screenBounds.Contains(pt) {
return HitTestClient
}
local := pt.Sub(screenBounds.Min)
// Check control buttons (reverse order: close first for priority).
if w.cfg.chrome != nil {
for i := controlCount - 1; i >= 0; i-- {
if w.controlBounds[i].Contains(local) {
switch i {
case controlIdxClose:
return HitTestClose
case controlIdxMaximize:
return HitTestMaximize
case controlIdxMinimize:
return HitTestMinimize
}
}
}
}
// Check leading and center child widgets.
if hitTestChildren(w.cfg.leading, w.leadingBounds, local) {
return HitTestClient
}
if hitTestChildren(w.cfg.center, w.centerBounds, local) {
return HitTestClient
}
// Empty space = caption (drag to move).
return HitTestCaption
}
func IsFocusable
IsFocusable reports whether the title bar can receive keyboard focus.
Title bars are not typically focusable.
func (w *Widget) IsFocusable() bool {
return false
}
func Layout
Layout calculates the title bar's preferred size within the given constraints.
func (w *Widget) Layout(ctx widget.Context, constraints geometry.Constraints) geometry.Size {
preferred := geometry.Sz(constraints.MaxWidth, w.cfg.height)
size := constraints.Constrain(preferred)
w.layoutChildren(ctx, size)
w.SetBounds(geometry.FromPointSize(w.Position(), size))
return size
}
func New
New creates a new title bar Widget with the given options.
The returned widget is visible and enabled by default. The default
height is 40 logical pixels.
func New(opts ...Option) *Widget {
w := &Widget{
painter: DefaultPainter{},
}
w.SetVisible(true)
w.SetEnabled(true)
w.cfg.height = defaultBarHeight
w.cfg.focused = true
for _, opt := range opts {
opt(&w.cfg)
}
if w.cfg.painter != nil {
w.painter = w.cfg.painter
}
w.leadingBounds = make([]geometry.Rect, len(w.cfg.leading))
w.centerBounds = make([]geometry.Rect, len(w.cfg.center))
// ADR-028: parent chain for upward dirty propagation.
// Flutter: RenderObject.adoptChild sets parent on each child.
type parentSetter interface{ SetParent(widget.Widget) }
for _, child := range w.cfg.leading {
if child != nil {
if ps, ok := child.(parentSetter); ok {
ps.SetParent(w)
}
}
}
for _, child := range w.cfg.center {
if child != nil {
if ps, ok := child.(parentSetter); ok {
ps.SetParent(w)
}
}
}
return w
}
func SetFocusedState
SetFocusedState updates whether the window is focused, affecting visual appearance.
func (w *Widget) SetFocusedState(focused bool) {
w.cfg.focused = focused
}
func SetTitle
SetTitle updates the title text.
func (w *Widget) SetTitle(title string) {
w.cfg.title = title
}
func Title
Title returns the current title text.
func (w *Widget) Title() string {
return w.cfg.title
}
Structs
type Widget struct
Widget implements a custom window title bar.
The title bar renders a horizontal bar with three zones: leading (left),
center, and trailing (right). The trailing zone contains window control
buttons (minimize, maximize/restore, close) when a [WindowChrome] is provided.
Empty space in the title bar acts as a drag region for window movement.
Child widgets placed in the leading and center zones receive events normally.
A Widget is created with [New] using functional options:
tb := titlebar.New(
titlebar.Title("My App"),
titlebar.Leading(menuBtn),
titlebar.Chrome(windowChrome),
titlebar.PainterOpt(painter),
)
type Widget struct {
widget.WidgetBase
cfg config
painter Painter
// controlBounds holds the bounds for each control button (min, max, close).
controlBounds [controlCount]geometry.Rect
// controlStates holds the interaction state for each control button.
controlStates [controlCount]interactionState
// leadingBounds holds the calculated bounds for each leading child widget.
leadingBounds []geometry.Rect
// centerBounds holds the calculated bounds for each center child widget.
centerBounds []geometry.Rect
// hoveredChild tracks the currently hovered child for MouseLeave dispatch.
// nil means no child is hovered.
hoveredChild widget.Widget
}
Interfaces
type WindowChrome interface
WindowChrome provides window management operations.
This interface is a subset of gpucontext.WindowChrome, defined locally
to avoid a direct dependency on the gpucontext package. Callers should
pass the gpucontext.WindowChrome value obtained from the window provider.
type WindowChrome interface {
// Minimize minimizes the window.
Minimize()
// Maximize maximizes the window.
Maximize()
// IsMaximized reports whether the window is currently maximized.
IsMaximized() bool
// Close closes the window.
Close()
}
AccessibilityActions returns nil.