fix(bar): recreate the layer surface when the output width changes so it stays full width
- commit
- b5cca9e4fe16a13aa719c5036f8c11128fe2a362
- author
- brice · · 2026-10-05 15:15 UTC
- parent
- 9a0b0c5
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
1 file · +29 -5
M internal/bar/bar.go +29 -5
| @@ -86,9 +86,13 @@ type Bar struct { | |||
| 86 | 86 | // buffer of the wrong size, and some compositors keep that size. | |
| 87 | 87 | settling bool | |
| 88 | 88 | settleC <-chan time.Time | |
| 89 | - | Stats Stats | |
| 90 | - | fatal error | |
| 91 | - | closed bool | |
| 89 | + | ||
| 90 | + | // mappedW is the logical width the current layer surface was first drawn at. | |
| 91 | + | // It resets to 0 when the surface is recreated. | |
| 92 | + | mappedW int32 | |
| 93 | + | Stats Stats | |
| 94 | + | fatal error | |
| 95 | + | closed bool | |
| 92 | 96 | } | |
| 93 | 97 | ||
| 94 | 98 | // New builds a bar from a validated config. | |
| @@ -312,6 +316,7 @@ func (b *Bar) createSurface(h int32) error { | |||
| 312 | 316 | return fmt.Errorf("layer surface: %w", err) | |
| 313 | 317 | } | |
| 314 | 318 | b.surf, b.sid = surf, surf.ID() | |
| 319 | + | b.mappedW = 0 | |
| 315 | 320 | b.configured, b.canPresent = false, false | |
| 316 | 321 | return nil | |
| 317 | 322 | } | |
| @@ -405,7 +410,7 @@ func (b *Bar) reconcile() { | |||
| 405 | 410 | } | |
| 406 | 411 | b.dev, b.node = dev, node | |
| 407 | 412 | } | |
| 408 | - | _, h, scale := b.surf.Size() | |
| 413 | + | w, h, scale := b.surf.Size() | |
| 409 | 414 | px := b.cfg.Bar.Size * b.cfg.Bar.Scale * scale | |
| 410 | 415 | if b.face == nil || b.facePx != px { | |
| 411 | 416 | face, err := glyph.Load(b.fonts, px) | |
| @@ -441,6 +446,25 @@ func (b *Bar) reconcile() { | |||
| 441 | 446 | if b.rend != nil && b.rend.W == pw && b.rend.H == ph { | |
| 442 | 447 | return | |
| 443 | 448 | } | |
| 449 | + | if b.mappedW != 0 && w != b.mappedW { | |
| 450 | + | // The logical width changed (a scale change on the output). NeferWL | |
| 451 | + | // places a layer surface from the size it had when it was mapped and | |
| 452 | + | // does not re-read it when only the buffer and viewport change, so the | |
| 453 | + | // old width would stay: centered in a narrower output, the left part cut | |
| 454 | + | // off. A new surface is mapped fresh and placed from its real size. | |
| 455 | + | b.log.Info("recreating layer surface: the output width changed", "from", b.mappedW, "to", w) | |
| 456 | + | b.dropRenderer() | |
| 457 | + | if err := b.surf.Close(); err != nil { | |
| 458 | + | b.fail(err) | |
| 459 | + | return | |
| 460 | + | } | |
| 461 | + | if err := b.createSurface(h); err != nil { | |
| 462 | + | b.fail(err) | |
| 463 | + | return | |
| 464 | + | } | |
| 465 | + | b.Stats.Recreated++ | |
| 466 | + | return | |
| 467 | + | } | |
| 444 | 468 | b.dropRenderer() | |
| 445 | 469 | if mod, err := b.chooseModifier(); err != nil { | |
| 446 | 470 | b.fail(err) | |
| @@ -453,7 +477,7 @@ func (b *Bar) reconcile() { | |||
| 453 | 477 | b.fail(err) | |
| 454 | 478 | return | |
| 455 | 479 | } | |
| 456 | - | b.rend = rend | |
| 480 | + | b.rend, b.mappedW = rend, w | |
| 457 | 481 | b.Stats.Rebuilds++ | |
| 458 | 482 | if b.lay == nil { | |
| 459 | 483 | b.lay = layout.New(rend.Cols(), b.fg, b.bg, b.mods) | |
| @@ -86,9 +86,13 @@ type Bar struct { | |||||
| 86 | // buffer of the wrong size, and some compositors keep that size. | 86 | // buffer of the wrong size, and some compositors keep that size. | ||
| 87 | settling bool | 87 | settling bool | ||
| 88 | settleC <-chan time.Time | 88 | settleC <-chan time.Time | ||
| 89 | - | Stats Stats | 89 | + | |
| 90 | - | fatal error | 90 | + | // mappedW is the logical width the current layer surface was first drawn at. |
| 91 | - | closed bool | 91 | + | // It resets to 0 when the surface is recreated. |
| 92 | + | mappedW int32 | |||
| 93 | + | Stats Stats | |||
| 94 | + | fatal error | |||
| 95 | + | closed bool | |||
| 92 | } | 96 | } | ||
| 93 | 97 | ||||
| 94 | // New builds a bar from a validated config. | 98 | // New builds a bar from a validated config. | ||
| @@ -312,6 +316,7 @@ func (b *Bar) createSurface(h int32) error { | |||||
| 312 | return fmt.Errorf("layer surface: %w", err) | 316 | return fmt.Errorf("layer surface: %w", err) | ||
| 313 | } | 317 | } | ||
| 314 | b.surf, b.sid = surf, surf.ID() | 318 | b.surf, b.sid = surf, surf.ID() | ||
| 319 | + | b.mappedW = 0 | |||
| 315 | b.configured, b.canPresent = false, false | 320 | b.configured, b.canPresent = false, false | ||
| 316 | return nil | 321 | return nil | ||
| 317 | } | 322 | } | ||
| @@ -405,7 +410,7 @@ func (b *Bar) reconcile() { | |||||
| 405 | } | 410 | } | ||
| 406 | b.dev, b.node = dev, node | 411 | b.dev, b.node = dev, node | ||
| 407 | } | 412 | } | ||
| 408 | - | _, h, scale := b.surf.Size() | 413 | + | w, h, scale := b.surf.Size() |
| 409 | px := b.cfg.Bar.Size * b.cfg.Bar.Scale * scale | 414 | px := b.cfg.Bar.Size * b.cfg.Bar.Scale * scale | ||
| 410 | if b.face == nil || b.facePx != px { | 415 | if b.face == nil || b.facePx != px { | ||
| 411 | face, err := glyph.Load(b.fonts, px) | 416 | face, err := glyph.Load(b.fonts, px) | ||
| @@ -441,6 +446,25 @@ func (b *Bar) reconcile() { | |||||
| 441 | if b.rend != nil && b.rend.W == pw && b.rend.H == ph { | 446 | if b.rend != nil && b.rend.W == pw && b.rend.H == ph { | ||
| 442 | return | 447 | return | ||
| 443 | } | 448 | } | ||
| 449 | + | if b.mappedW != 0 && w != b.mappedW { | |||
| 450 | + | // The logical width changed (a scale change on the output). NeferWL | |||
| 451 | + | // places a layer surface from the size it had when it was mapped and | |||
| 452 | + | // does not re-read it when only the buffer and viewport change, so the | |||
| 453 | + | // old width would stay: centered in a narrower output, the left part cut | |||
| 454 | + | // off. A new surface is mapped fresh and placed from its real size. | |||
| 455 | + | b.log.Info("recreating layer surface: the output width changed", "from", b.mappedW, "to", w) | |||
| 456 | + | b.dropRenderer() | |||
| 457 | + | if err := b.surf.Close(); err != nil { | |||
| 458 | + | b.fail(err) | |||
| 459 | + | return | |||
| 460 | + | } | |||
| 461 | + | if err := b.createSurface(h); err != nil { | |||
| 462 | + | b.fail(err) | |||
| 463 | + | return | |||
| 464 | + | } | |||
| 465 | + | b.Stats.Recreated++ | |||
| 466 | + | return | |||
| 467 | + | } | |||
| 444 | b.dropRenderer() | 468 | b.dropRenderer() | ||
| 445 | if mod, err := b.chooseModifier(); err != nil { | 469 | if mod, err := b.chooseModifier(); err != nil { | ||
| 446 | b.fail(err) | 470 | b.fail(err) | ||
| @@ -453,7 +477,7 @@ func (b *Bar) reconcile() { | |||||
| 453 | b.fail(err) | 477 | b.fail(err) | ||
| 454 | return | 478 | return | ||
| 455 | } | 479 | } | ||
| 456 | - | b.rend = rend | 480 | + | b.rend, b.mappedW = rend, w |
| 457 | b.Stats.Rebuilds++ | 481 | b.Stats.Rebuilds++ | ||
| 458 | if b.lay == nil { | 482 | if b.lay == nil { | ||
| 459 | b.lay = layout.New(rend.Cols(), b.fg, b.bg, b.mods) | 483 | b.lay = layout.New(rend.Cols(), b.fg, b.bg, b.mods) | ||