From 365b0ce6b0e728b4b96f612e45f2279f47b87336 Mon Sep 17 00:00:00 2001 From: Denton Gentry Date: Mon, 2 Jan 2023 16:41:37 -0800 Subject: [PATCH] ui: Fix background color of exit node status. (#75) Prior to https://github.com/tailscale/tailscale-android/pull/73/, the exit node status pane was set to a background color using: paint.Fill(gtx.Ops, bg) paint.Fill() is documented to fill the entire clipped area. It assumes that one has already applied a clip area... but no clip area had been set in this code path. As far as I can tell, that this worked prior to pull #73 was a bug, something had a side-effect of setting a clipping rectangle. We updated to the head of the Gio repo, which apparently fixed that bug. After pull #73, the paint.Fill() painted the entire app window. Fix this using a stacked layout. A color filled widget is the lower layer, and will expand to the size of the widget sitting atop of it. Fixes https://github.com/tailscale/tailscale/issues/6873 Signed-off-by: Denton Gentry Signed-off-by: Denton Gentry --- cmd/tailscale/ui.go | 59 +++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/cmd/tailscale/ui.go b/cmd/tailscale/ui.go index 90ce1a0..ac3294e 100644 --- a/cmd/tailscale/ui.go +++ b/cmd/tailscale/ui.go @@ -668,35 +668,48 @@ func (ui *UI) layoutExitStatus(gtx layout.Context, state *BackendState) layout.D text = "Using exit node" bg = rgb(0x338b51) } - paint.Fill(gtx.Ops, bg) return material.Clickable(gtx, &ui.openExitDialog, func(gtx C) D { gtx.Constraints.Min.X = gtx.Constraints.Max.X - return layout.Inset{ - Top: unit.Dp(12), - Bottom: unit.Dp(12), - Right: unit.Dp(24), - Left: unit.Dp(24), - }.Layout(gtx, func(gtx C) D { - return layout.Flex{Alignment: layout.Middle}.Layout(gtx, - layout.Flexed(1, func(gtx C) D { - return layout.Flex{Axis: layout.Vertical}.Layout(gtx, - layout.Rigid(func(gtx C) D { - lbl := material.Body2(ui.theme, text) - lbl.Color = rgb(white) - return lbl.Layout(gtx) + return layout.Stack{}.Layout(gtx, + layout.Expanded(func(gtx layout.Context) layout.Dimensions { + sz := image.Point{ + X: gtx.Constraints.Min.X, + Y: gtx.Constraints.Min.Y, + } + defer clip.Rect(image.Rectangle{Max: sz}).Push(gtx.Ops).Pop() + paint.ColorOp{Color: bg}.Add(gtx.Ops) + paint.PaintOp{}.Add(gtx.Ops) + return layout.Dimensions{Size: sz} + }), + layout.Stacked(func(gtx layout.Context) layout.Dimensions { + return layout.Inset{ + Top: unit.Dp(12), + Bottom: unit.Dp(12), + Right: unit.Dp(24), + Left: unit.Dp(24), + }.Layout(gtx, func(gtx C) D { + return layout.Flex{Alignment: layout.Middle}.Layout(gtx, + layout.Flexed(1, func(gtx C) D { + return layout.Flex{Axis: layout.Vertical}.Layout(gtx, + layout.Rigid(func(gtx C) D { + lbl := material.Body2(ui.theme, text) + lbl.Color = rgb(white) + return lbl.Layout(gtx) + }), + layout.Rigid(func(gtx C) D { + node := material.Body2(ui.theme, state.Exit.Label) + node.Color = argb(0x88ffffff) + return node.Layout(gtx) + }), + ) }), layout.Rigid(func(gtx C) D { - node := material.Body2(ui.theme, state.Exit.Label) - node.Color = argb(0x88ffffff) - return node.Layout(gtx) + return ui.icons.exitStatus.Layout(gtx, rgb(white)) }), ) - }), - layout.Rigid(func(gtx C) D { - return ui.icons.exitStatus.Layout(gtx, rgb(white)) - }), - ) - }) + }) + }), + ) }) }