fix(core): skip position hint band walk when disabled and document hint fade scheduling
- commit
- a46ff66551c2aa890d28d0cc0672c723f31f36c6
- author
- brice · · 2026-10-20 01:49 UTC
- parent
- 392b5b6
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
4 files · +16 -8
M internal/core/gesture.go +4 -2
| @@ -586,13 +586,15 @@ func (c *Core) animate(now time.Time, only *screen) { | |||
| 586 | 586 | } | |
| 587 | 587 | } | |
| 588 | 588 | ||
| 589 | - | // sliding reports whether a spring or focus flash runs on the named output. | |
| 589 | + | // sliding reports whether a spring, focus flash or position hint fade runs | |
| 590 | + | // on the named output. | |
| 590 | 591 | func (c *Core) sliding(output string) bool { | |
| 591 | 592 | i := c.screenIndex(output) | |
| 592 | 593 | return i >= 0 && (c.screens[i].springing() || c.flashing(c.screens[i]) || c.positionHintFading(c.screens[i])) | |
| 593 | 594 | } | |
| 594 | 595 | ||
| 595 | - | // animating reports whether a spring or focus flash runs on any output. | |
| 596 | + | // animating reports whether a spring, focus flash or position hint fade | |
| 597 | + | // runs on any output. | |
| 596 | 598 | func (c *Core) animating() bool { | |
| 597 | 599 | if c.flash.running != nil { | |
| 598 | 600 | return true | |
| @@ -586,13 +586,15 @@ func (c *Core) animate(now time.Time, only *screen) { | |||||
| 586 | } | 586 | } | ||
| 587 | } | 587 | } | ||
| 588 | 588 | ||||
| 589 | - | // sliding reports whether a spring or focus flash runs on the named output. | 589 | + | // sliding reports whether a spring, focus flash or position hint fade runs |
| 590 | + | // on the named output. | |||
| 590 | func (c *Core) sliding(output string) bool { | 591 | func (c *Core) sliding(output string) bool { | ||
| 591 | i := c.screenIndex(output) | 592 | i := c.screenIndex(output) | ||
| 592 | return i >= 0 && (c.screens[i].springing() || c.flashing(c.screens[i]) || c.positionHintFading(c.screens[i])) | 593 | return i >= 0 && (c.screens[i].springing() || c.flashing(c.screens[i]) || c.positionHintFading(c.screens[i])) | ||
| 593 | } | 594 | } | ||
| 594 | 595 | ||||
| 595 | - | // animating reports whether a spring or focus flash runs on any output. | 596 | + | // animating reports whether a spring, focus flash or position hint fade |
| 597 | + | // runs on any output. | |||
| 596 | func (c *Core) animating() bool { | 598 | func (c *Core) animating() bool { | ||
| 597 | if c.flash.running != nil { | 599 | if c.flash.running != nil { | ||
| 598 | return true | 600 | return true | ||
M internal/core/position_hint.go +7 -1
| @@ -41,6 +41,12 @@ func (c *Core) updatePositionHints(only *screen) { | |||
| 41 | 41 | h.live, h.sample = false, ports.PositionHint{} | |
| 42 | 42 | continue | |
| 43 | 43 | } | |
| 44 | + | // Disabled hints skip the band walk; dropping the baseline keeps a | |
| 45 | + | // later re-enable from announcing the position it finds. | |
| 46 | + | if !c.cfg.Focus.PositionHint { | |
| 47 | + | *h = positionHintState{} | |
| 48 | + | continue | |
| 49 | + | } | |
| 44 | 50 | w := sc.mon.Current() | |
| 45 | 51 | band := 0 | |
| 46 | 52 | if w.Overflow == OverflowCascade { | |
| @@ -59,7 +65,7 @@ func (c *Core) updatePositionHints(only *screen) { | |||
| 59 | 65 | } | |
| 60 | 66 | } | |
| 61 | 67 | h.workspace, h.band, h.focused, h.initialized = w, band, focused, true | |
| 62 | - | if !c.cfg.Focus.PositionHint || c.protectionRequested() || w.cover() != 0 { | |
| 68 | + | if c.protectionRequested() || w.cover() != 0 { | |
| 63 | 69 | h.live, h.sample = false, ports.PositionHint{} | |
| 64 | 70 | continue | |
| 65 | 71 | } | |
| @@ -41,6 +41,12 @@ func (c *Core) updatePositionHints(only *screen) { | |||||
| 41 | h.live, h.sample = false, ports.PositionHint{} | 41 | h.live, h.sample = false, ports.PositionHint{} | ||
| 42 | continue | 42 | continue | ||
| 43 | } | 43 | } | ||
| 44 | + | // Disabled hints skip the band walk; dropping the baseline keeps a | |||
| 45 | + | // later re-enable from announcing the position it finds. | |||
| 46 | + | if !c.cfg.Focus.PositionHint { | |||
| 47 | + | *h = positionHintState{} | |||
| 48 | + | continue | |||
| 49 | + | } | |||
| 44 | w := sc.mon.Current() | 50 | w := sc.mon.Current() | ||
| 45 | band := 0 | 51 | band := 0 | ||
| 46 | if w.Overflow == OverflowCascade { | 52 | if w.Overflow == OverflowCascade { | ||
| @@ -59,7 +65,7 @@ func (c *Core) updatePositionHints(only *screen) { | |||||
| 59 | } | 65 | } | ||
| 60 | } | 66 | } | ||
| 61 | h.workspace, h.band, h.focused, h.initialized = w, band, focused, true | 67 | h.workspace, h.band, h.focused, h.initialized = w, band, focused, true | ||
| 62 | - | if !c.cfg.Focus.PositionHint || c.protectionRequested() || w.cover() != 0 { | 68 | + | if c.protectionRequested() || w.cover() != 0 { |
| 63 | h.live, h.sample = false, ports.PositionHint{} | 69 | h.live, h.sample = false, ports.PositionHint{} | ||
| 64 | continue | 70 | continue | ||
| 65 | } | 71 | } | ||
M internal/core/position_hint_test.go +1 -1
| @@ -55,7 +55,7 @@ func TestPositionHintChangesAndTiming(t *testing.T) { | |||
| 55 | 55 | } | |
| 56 | 56 | ||
| 57 | 57 | func TestPositionHintWorkspaceAndSuppression(t *testing.T) { | |
| 58 | - | for _, mode := range []string{"workspace", "overview", "fullscreen", "off", "no-animation"} { | |
| 58 | + | for _, mode := range []string{"overview", "fullscreen", "off", "no-animation"} { | |
| 59 | 59 | t.Run(mode, func(t *testing.T) { | |
| 60 | 60 | c, clock := indicatorCore(t) | |
| 61 | 61 | c.cfg.Focus.PositionHint = true | |
| @@ -55,7 +55,7 @@ func TestPositionHintChangesAndTiming(t *testing.T) { | |||||
| 55 | } | 55 | } | ||
| 56 | 56 | ||||
| 57 | func TestPositionHintWorkspaceAndSuppression(t *testing.T) { | 57 | func TestPositionHintWorkspaceAndSuppression(t *testing.T) { | ||
| 58 | - | for _, mode := range []string{"workspace", "overview", "fullscreen", "off", "no-animation"} { | 58 | + | for _, mode := range []string{"overview", "fullscreen", "off", "no-animation"} { |
| 59 | t.Run(mode, func(t *testing.T) { | 59 | t.Run(mode, func(t *testing.T) { | ||
| 60 | c, clock := indicatorCore(t) | 60 | c, clock := indicatorCore(t) | ||
| 61 | c.cfg.Focus.PositionHint = true | 61 | c.cfg.Focus.PositionHint = true | ||
M internal/ports/scene.go +4 -4
| @@ -79,10 +79,10 @@ type Scene struct { | |||
| 79 | 79 | Flash *FocusFlash | |
| 80 | 80 | // PositionHint is drawn on the physical output only, never in captures. | |
| 81 | 81 | PositionHint PositionHint | |
| 82 | - | // Animating is set by core when a spring or a focus flash runs on | |
| 83 | - | // this output after this frame was computed: the output reports the | |
| 84 | - | // flip of the scene to core (OutputFrame), which moves the animation to | |
| 85 | - | // the next frame. A scene of a settled output carries false, so a flip | |
| 82 | + | // Animating is set by core when a spring, a focus flash or a position | |
| 83 | + | // hint fade runs on this output after this frame was computed: the | |
| 84 | + | // output reports the flip of the scene to core (OutputFrame), which | |
| 85 | + | // moves the animation to the next frame. A scene of a settled output carries false, so a flip | |
| 86 | 86 | // of it wakes nobody. It describes scheduling, not drawing: SameAs and | |
| 87 | 87 | // the renderer ignore it. | |
| 88 | 88 | Animating bool | |
| @@ -79,10 +79,10 @@ type Scene struct { | |||||
| 79 | Flash *FocusFlash | 79 | Flash *FocusFlash | ||
| 80 | // PositionHint is drawn on the physical output only, never in captures. | 80 | // PositionHint is drawn on the physical output only, never in captures. | ||
| 81 | PositionHint PositionHint | 81 | PositionHint PositionHint | ||
| 82 | - | // Animating is set by core when a spring or a focus flash runs on | 82 | + | // Animating is set by core when a spring, a focus flash or a position |
| 83 | - | // this output after this frame was computed: the output reports the | 83 | + | // hint fade runs on this output after this frame was computed: the |
| 84 | - | // flip of the scene to core (OutputFrame), which moves the animation to | 84 | + | // output reports the flip of the scene to core (OutputFrame), which |
| 85 | - | // the next frame. A scene of a settled output carries false, so a flip | 85 | + | // moves the animation to the next frame. A scene of a settled output carries false, so a flip |
| 86 | // of it wakes nobody. It describes scheduling, not drawing: SameAs and | 86 | // of it wakes nobody. It describes scheduling, not drawing: SameAs and | ||
| 87 | // the renderer ignore it. | 87 | // the renderer ignore it. | ||
| 88 | Animating bool | 88 | Animating bool | ||