refactor(daemon): define floating geometry coordinate boundary
- commit
- 4005fb8e3312f486d713e24fea38a91f78fec05e
- author
- brice · · 2026-07-11 05:12 UTC
- parent
- 5fcde4c
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +30 -3
M internal/usecase/daemon/floating_render.go +13 -3
| @@ -8,7 +8,8 @@ import ( | |||
| 8 | 8 | ) | |
| 9 | 9 | ||
| 10 | 10 | // floatingGeometry describes a popup's outer frame and terminal content area. | |
| 11 | - | // Bounds and Inner are both relative to the supplied content rectangle. | |
| 11 | + | // Committed geometry is tab-content-relative; Bounds and Inner are both relative | |
| 12 | + | // to the supplied content rectangle. | |
| 12 | 13 | type floatingGeometry struct { | |
| 13 | 14 | Bounds domain.Rect | |
| 14 | 15 | Inner domain.Rect | |
| @@ -18,6 +19,14 @@ func (g floatingGeometry) valid() bool { | |||
| 18 | 19 | return g.Bounds.Width > 0 && g.Bounds.Height > 0 && g.Inner.Width > 0 && g.Inner.Height > 0 | |
| 19 | 20 | } | |
| 20 | 21 | ||
| 22 | + | func (g floatingGeometry) translate(dx, dy int) floatingGeometry { | |
| 23 | + | g.Bounds.X += dx | |
| 24 | + | g.Bounds.Y += dy | |
| 25 | + | g.Inner.X += dx | |
| 26 | + | g.Inner.Y += dy | |
| 27 | + | return g | |
| 28 | + | } | |
| 29 | + | ||
| 21 | 30 | // committedFloatingGeometryLocked returns the geometry whose PTY resize was | |
| 22 | 31 | // last committed. Newly constructed test panes fall back to the requested | |
| 23 | 32 | // geometry until their first resize. The caller holds p.mu. | |
| @@ -47,8 +56,9 @@ func calculateFloatingAxisGeometry(available, percent int) floatingAxisGeometry | |||
| 47 | 56 | return axis | |
| 48 | 57 | } | |
| 49 | 58 | ||
| 50 | - | // calculateFloatingGeometry centers a percentage-sized popup in content. | |
| 51 | - | // Launch sizing derives from Inner too, so rendering and PTY geometry share | |
| 59 | + | // calculateFloatingGeometry returns coordinates in the supplied rectangle's | |
| 60 | + | // space and centers a percentage-sized popup in content. Launch sizing derives | |
| 61 | + | // from Inner too, so rendering and PTY geometry share | |
| 52 | 62 | // the same per-axis percentage and tiny-border rules. | |
| 53 | 63 | func calculateFloatingGeometry(content domain.Rect, cfg domain.FloatingConfig) floatingGeometry { | |
| 54 | 64 | if content.Width <= 0 || content.Height <= 0 { | |
| @@ -8,7 +8,8 @@ import ( | |||||
| 8 | ) | 8 | ) | ||
| 9 | 9 | ||||
| 10 | // floatingGeometry describes a popup's outer frame and terminal content area. | 10 | // floatingGeometry describes a popup's outer frame and terminal content area. | ||
| 11 | - | // Bounds and Inner are both relative to the supplied content rectangle. | 11 | + | // Committed geometry is tab-content-relative; Bounds and Inner are both relative |
| 12 | + | // to the supplied content rectangle. | |||
| 12 | type floatingGeometry struct { | 13 | type floatingGeometry struct { | ||
| 13 | Bounds domain.Rect | 14 | Bounds domain.Rect | ||
| 14 | Inner domain.Rect | 15 | Inner domain.Rect | ||
| @@ -18,6 +19,14 @@ func (g floatingGeometry) valid() bool { | |||||
| 18 | return g.Bounds.Width > 0 && g.Bounds.Height > 0 && g.Inner.Width > 0 && g.Inner.Height > 0 | 19 | return g.Bounds.Width > 0 && g.Bounds.Height > 0 && g.Inner.Width > 0 && g.Inner.Height > 0 | ||
| 19 | } | 20 | } | ||
| 20 | 21 | ||||
| 22 | + | func (g floatingGeometry) translate(dx, dy int) floatingGeometry { | |||
| 23 | + | g.Bounds.X += dx | |||
| 24 | + | g.Bounds.Y += dy | |||
| 25 | + | g.Inner.X += dx | |||
| 26 | + | g.Inner.Y += dy | |||
| 27 | + | return g | |||
| 28 | + | } | |||
| 29 | + | ||||
| 21 | // committedFloatingGeometryLocked returns the geometry whose PTY resize was | 30 | // committedFloatingGeometryLocked returns the geometry whose PTY resize was | ||
| 22 | // last committed. Newly constructed test panes fall back to the requested | 31 | // last committed. Newly constructed test panes fall back to the requested | ||
| 23 | // geometry until their first resize. The caller holds p.mu. | 32 | // geometry until their first resize. The caller holds p.mu. | ||
| @@ -47,8 +56,9 @@ func calculateFloatingAxisGeometry(available, percent int) floatingAxisGeometry | |||||
| 47 | return axis | 56 | return axis | ||
| 48 | } | 57 | } | ||
| 49 | 58 | ||||
| 50 | - | // calculateFloatingGeometry centers a percentage-sized popup in content. | 59 | + | // calculateFloatingGeometry returns coordinates in the supplied rectangle's |
| 51 | - | // Launch sizing derives from Inner too, so rendering and PTY geometry share | 60 | + | // space and centers a percentage-sized popup in content. Launch sizing derives |
| 61 | + | // from Inner too, so rendering and PTY geometry share | |||
| 52 | // the same per-axis percentage and tiny-border rules. | 62 | // the same per-axis percentage and tiny-border rules. | ||
| 53 | func calculateFloatingGeometry(content domain.Rect, cfg domain.FloatingConfig) floatingGeometry { | 63 | func calculateFloatingGeometry(content domain.Rect, cfg domain.FloatingConfig) floatingGeometry { | ||
| 54 | if content.Width <= 0 || content.Height <= 0 { | 64 | if content.Width <= 0 || content.Height <= 0 { | ||
M internal/usecase/daemon/floating_render_test.go +17 -0
| @@ -14,6 +14,23 @@ import ( | |||
| 14 | 14 | "github.com/bnema/vev/pkg/renderer" | |
| 15 | 15 | ) | |
| 16 | 16 | ||
| 17 | + | func TestFloatingGeometryTranslate(t *testing.T) { | |
| 18 | + | geometry := floatingGeometry{ | |
| 19 | + | Bounds: domain.Rect{X: 3, Y: 5, Width: 10, Height: 8}, | |
| 20 | + | Inner: domain.Rect{X: 4, Y: 6, Width: 8, Height: 6}, | |
| 21 | + | } | |
| 22 | + | ||
| 23 | + | translated := geometry.translate(11, 13) | |
| 24 | + | require.Equal(t, floatingGeometry{ | |
| 25 | + | Bounds: domain.Rect{X: 14, Y: 18, Width: 10, Height: 8}, | |
| 26 | + | Inner: domain.Rect{X: 15, Y: 19, Width: 8, Height: 6}, | |
| 27 | + | }, translated) | |
| 28 | + | require.Equal(t, floatingGeometry{ | |
| 29 | + | Bounds: domain.Rect{X: 3, Y: 5, Width: 10, Height: 8}, | |
| 30 | + | Inner: domain.Rect{X: 4, Y: 6, Width: 8, Height: 6}, | |
| 31 | + | }, geometry) | |
| 32 | + | } | |
| 33 | + | ||
| 17 | 34 | func TestCalculateFloatingGeometry(t *testing.T) { | |
| 18 | 35 | tests := []struct { | |
| 19 | 36 | name string | |
| @@ -14,6 +14,23 @@ import ( | |||||
| 14 | "github.com/bnema/vev/pkg/renderer" | 14 | "github.com/bnema/vev/pkg/renderer" | ||
| 15 | ) | 15 | ) | ||
| 16 | 16 | ||||
| 17 | + | func TestFloatingGeometryTranslate(t *testing.T) { | |||
| 18 | + | geometry := floatingGeometry{ | |||
| 19 | + | Bounds: domain.Rect{X: 3, Y: 5, Width: 10, Height: 8}, | |||
| 20 | + | Inner: domain.Rect{X: 4, Y: 6, Width: 8, Height: 6}, | |||
| 21 | + | } | |||
| 22 | + | ||||
| 23 | + | translated := geometry.translate(11, 13) | |||
| 24 | + | require.Equal(t, floatingGeometry{ | |||
| 25 | + | Bounds: domain.Rect{X: 14, Y: 18, Width: 10, Height: 8}, | |||
| 26 | + | Inner: domain.Rect{X: 15, Y: 19, Width: 8, Height: 6}, | |||
| 27 | + | }, translated) | |||
| 28 | + | require.Equal(t, floatingGeometry{ | |||
| 29 | + | Bounds: domain.Rect{X: 3, Y: 5, Width: 10, Height: 8}, | |||
| 30 | + | Inner: domain.Rect{X: 4, Y: 6, Width: 8, Height: 6}, | |||
| 31 | + | }, geometry) | |||
| 32 | + | } | |||
| 33 | + | ||||
| 17 | func TestCalculateFloatingGeometry(t *testing.T) { | 34 | func TestCalculateFloatingGeometry(t *testing.T) { | ||
| 18 | tests := []struct { | 35 | tests := []struct { | ||
| 19 | name string | 36 | name string | ||