#2 fix(selection): freeze outputs wider than 4096 pixels
M go.mod +1 -1
| @@ -6,7 +6,7 @@ require ( | |||
| 6 | 6 | github.com/bnema/go-wayland-bindings v0.1.0 | |
| 7 | 7 | github.com/bnema/kvconf v0.1.2 | |
| 8 | 8 | github.com/bnema/neferclient v0.3.0 | |
| 9 | - | github.com/bnema/nefergui v0.7.2 | |
| 9 | + | github.com/bnema/nefergui v0.7.3 | |
| 10 | 10 | github.com/bnema/purego-libwayland v0.8.0 | |
| 11 | 11 | github.com/bnema/wlturbo v0.6.2 | |
| 12 | 12 | github.com/bnema/zerowrap v1.4.1 | |
| @@ -6,7 +6,7 @@ require ( | |||||
| 6 | github.com/bnema/go-wayland-bindings v0.1.0 | 6 | github.com/bnema/go-wayland-bindings v0.1.0 | ||
| 7 | github.com/bnema/kvconf v0.1.2 | 7 | github.com/bnema/kvconf v0.1.2 | ||
| 8 | github.com/bnema/neferclient v0.3.0 | 8 | github.com/bnema/neferclient v0.3.0 | ||
| 9 | - | github.com/bnema/nefergui v0.7.2 | 9 | + | github.com/bnema/nefergui v0.7.3 |
| 10 | github.com/bnema/purego-libwayland v0.8.0 | 10 | github.com/bnema/purego-libwayland v0.8.0 | ||
| 11 | github.com/bnema/wlturbo v0.6.2 | 11 | github.com/bnema/wlturbo v0.6.2 | ||
| 12 | github.com/bnema/zerowrap v1.4.1 | 12 | github.com/bnema/zerowrap v1.4.1 | ||
M go.sum +2 -2
| @@ -4,8 +4,8 @@ github.com/bnema/kvconf v0.1.2 h1:1hDKL9jkQSBdR9dSKbwTONhUUBfJgAdh5vu+yFHOb70= | |||
| 4 | 4 | github.com/bnema/kvconf v0.1.2/go.mod h1:+P2X9I/sLx+Lfir45s9a7WA0GnC22WgKbZWE9LK6lcU= | |
| 5 | 5 | github.com/bnema/neferclient v0.3.0 h1:sEBphi11YpgMOPYHW1OcDtQYA8aD3WSaFILnb8fdp90= | |
| 6 | 6 | github.com/bnema/neferclient v0.3.0/go.mod h1:CzZflJIvinLP8u0rYPjdmAnZjl4Ec2cvdnEGvqFO4Yw= | |
| 7 | - | github.com/bnema/nefergui v0.7.2 h1:9gnYhVlMxpBp+cVE+9Uursc/HwPXe/Li16+m4HL/gkU= | |
| 8 | - | github.com/bnema/nefergui v0.7.2/go.mod h1:G2iRRleA9bjSohU1RySwRqqxS0BbkPziK407HkuyEBc= | |
| 7 | + | github.com/bnema/nefergui v0.7.3 h1:T6NamM17arkan3K38+YF1/flsQ/v4ROSytSNNMz+3M4= | |
| 8 | + | github.com/bnema/nefergui v0.7.3/go.mod h1:G2iRRleA9bjSohU1RySwRqqxS0BbkPziK407HkuyEBc= | |
| 9 | 9 | github.com/bnema/purego v0.13.0-bnema.1 h1:fKRdztnvTmRqAjANMoN+utEIH73dvPqVPJh2iZCCAO8= | |
| 10 | 10 | github.com/bnema/purego v0.13.0-bnema.1/go.mod h1:xS1iX3noypxnbOUEUAqOvkfnUzgHuu19VtL4+dfUMJM= | |
| 11 | 11 | github.com/bnema/purego-libwayland v0.8.0 h1:e82G1nMre4HvnR1Q8TvdnVNITUStSc+hD3eMwkYjxQY= | |
| @@ -4,8 +4,8 @@ github.com/bnema/kvconf v0.1.2 h1:1hDKL9jkQSBdR9dSKbwTONhUUBfJgAdh5vu+yFHOb70= | |||||
| 4 | github.com/bnema/kvconf v0.1.2/go.mod h1:+P2X9I/sLx+Lfir45s9a7WA0GnC22WgKbZWE9LK6lcU= | 4 | github.com/bnema/kvconf v0.1.2/go.mod h1:+P2X9I/sLx+Lfir45s9a7WA0GnC22WgKbZWE9LK6lcU= | ||
| 5 | github.com/bnema/neferclient v0.3.0 h1:sEBphi11YpgMOPYHW1OcDtQYA8aD3WSaFILnb8fdp90= | 5 | github.com/bnema/neferclient v0.3.0 h1:sEBphi11YpgMOPYHW1OcDtQYA8aD3WSaFILnb8fdp90= | ||
| 6 | github.com/bnema/neferclient v0.3.0/go.mod h1:CzZflJIvinLP8u0rYPjdmAnZjl4Ec2cvdnEGvqFO4Yw= | 6 | github.com/bnema/neferclient v0.3.0/go.mod h1:CzZflJIvinLP8u0rYPjdmAnZjl4Ec2cvdnEGvqFO4Yw= | ||
| 7 | - | github.com/bnema/nefergui v0.7.2 h1:9gnYhVlMxpBp+cVE+9Uursc/HwPXe/Li16+m4HL/gkU= | 7 | + | github.com/bnema/nefergui v0.7.3 h1:T6NamM17arkan3K38+YF1/flsQ/v4ROSytSNNMz+3M4= |
| 8 | - | github.com/bnema/nefergui v0.7.2/go.mod h1:G2iRRleA9bjSohU1RySwRqqxS0BbkPziK407HkuyEBc= | 8 | + | github.com/bnema/nefergui v0.7.3/go.mod h1:G2iRRleA9bjSohU1RySwRqqxS0BbkPziK407HkuyEBc= |
| 9 | github.com/bnema/purego v0.13.0-bnema.1 h1:fKRdztnvTmRqAjANMoN+utEIH73dvPqVPJh2iZCCAO8= | 9 | github.com/bnema/purego v0.13.0-bnema.1 h1:fKRdztnvTmRqAjANMoN+utEIH73dvPqVPJh2iZCCAO8= | ||
| 10 | github.com/bnema/purego v0.13.0-bnema.1/go.mod h1:xS1iX3noypxnbOUEUAqOvkfnUzgHuu19VtL4+dfUMJM= | 10 | github.com/bnema/purego v0.13.0-bnema.1/go.mod h1:xS1iX3noypxnbOUEUAqOvkfnUzgHuu19VtL4+dfUMJM= | ||
| 11 | github.com/bnema/purego-libwayland v0.8.0 h1:e82G1nMre4HvnR1Q8TvdnVNITUStSc+hD3eMwkYjxQY= | 11 | github.com/bnema/purego-libwayland v0.8.0 h1:e82G1nMre4HvnR1Q8TvdnVNITUStSc+hD3eMwkYjxQY= | ||
M internal/adapters/selection/backdrop_test.go +11 -2
| @@ -31,13 +31,22 @@ func TestWithBackdrops(t *testing.T) { | |||
| 31 | 31 | ||
| 32 | 32 | huge := ports.Frame{Width: maxBackdrop + 1, Height: 1, Stride: (maxBackdrop + 1) * 4, Format: ports.XRGB8888} | |
| 33 | 33 | _, err = New(ports.Screenshot, ports.VideoSettings{}, nil, false).WithBackdrops(map[uint32]ports.Frame{9: huge}) | |
| 34 | - | assert.ErrorContains(t, err, "at most 4096", "the caller freezes only outputs CanBackdrop accepts") | |
| 34 | + | assert.ErrorContains(t, err, "at most 8192", "the caller freezes only outputs CanBackdrop accepts") | |
| 35 | + | ||
| 36 | + | huge = ports.Frame{Width: 7680, Height: 4320, Stride: 7680 * 4, Format: ports.XRGB8888} | |
| 37 | + | _, err = New(ports.Screenshot, ports.VideoSettings{}, nil, false).WithBackdrops(map[uint32]ports.Frame{9: huge}) | |
| 38 | + | assert.ErrorContains(t, err, "67108864 bytes") | |
| 35 | 39 | } | |
| 36 | 40 | ||
| 37 | 41 | func TestCanBackdrop(t *testing.T) { | |
| 38 | 42 | assert.True(t, CanBackdrop(ports.Output{Width: 3840, Height: 2160})) | |
| 39 | 43 | assert.True(t, CanBackdrop(ports.Output{Width: 2160, Height: 4096})) | |
| 40 | - | assert.False(t, CanBackdrop(ports.Output{Width: 5120, Height: 2880})) | |
| 44 | + | assert.True(t, CanBackdrop(ports.Output{Width: 5120, Height: 2160})) | |
| 45 | + | assert.True(t, CanBackdrop(ports.Output{Width: 8192, Height: 2048}), "exact byte budget") | |
| 46 | + | assert.False(t, CanBackdrop(ports.Output{Width: 8192, Height: 2049})) | |
| 47 | + | assert.False(t, CanBackdrop(ports.Output{Width: 7680, Height: 4320})) | |
| 48 | + | assert.False(t, CanBackdrop(ports.Output{Width: 8193, Height: 1})) | |
| 49 | + | assert.False(t, CanBackdrop(ports.Output{Width: 1, Height: 8193})) | |
| 41 | 50 | assert.False(t, CanBackdrop(ports.Output{}), "an unknown mode stays live") | |
| 42 | 51 | } | |
| 43 | 52 | ||
| @@ -31,13 +31,22 @@ func TestWithBackdrops(t *testing.T) { | |||||
| 31 | 31 | ||||
| 32 | huge := ports.Frame{Width: maxBackdrop + 1, Height: 1, Stride: (maxBackdrop + 1) * 4, Format: ports.XRGB8888} | 32 | huge := ports.Frame{Width: maxBackdrop + 1, Height: 1, Stride: (maxBackdrop + 1) * 4, Format: ports.XRGB8888} | ||
| 33 | _, err = New(ports.Screenshot, ports.VideoSettings{}, nil, false).WithBackdrops(map[uint32]ports.Frame{9: huge}) | 33 | _, err = New(ports.Screenshot, ports.VideoSettings{}, nil, false).WithBackdrops(map[uint32]ports.Frame{9: huge}) | ||
| 34 | - | assert.ErrorContains(t, err, "at most 4096", "the caller freezes only outputs CanBackdrop accepts") | 34 | + | assert.ErrorContains(t, err, "at most 8192", "the caller freezes only outputs CanBackdrop accepts") |
| 35 | + | ||||
| 36 | + | huge = ports.Frame{Width: 7680, Height: 4320, Stride: 7680 * 4, Format: ports.XRGB8888} | |||
| 37 | + | _, err = New(ports.Screenshot, ports.VideoSettings{}, nil, false).WithBackdrops(map[uint32]ports.Frame{9: huge}) | |||
| 38 | + | assert.ErrorContains(t, err, "67108864 bytes") | |||
| 35 | } | 39 | } | ||
| 36 | 40 | ||||
| 37 | func TestCanBackdrop(t *testing.T) { | 41 | func TestCanBackdrop(t *testing.T) { | ||
| 38 | assert.True(t, CanBackdrop(ports.Output{Width: 3840, Height: 2160})) | 42 | assert.True(t, CanBackdrop(ports.Output{Width: 3840, Height: 2160})) | ||
| 39 | assert.True(t, CanBackdrop(ports.Output{Width: 2160, Height: 4096})) | 43 | assert.True(t, CanBackdrop(ports.Output{Width: 2160, Height: 4096})) | ||
| 40 | - | assert.False(t, CanBackdrop(ports.Output{Width: 5120, Height: 2880})) | 44 | + | assert.True(t, CanBackdrop(ports.Output{Width: 5120, Height: 2160})) |
| 45 | + | assert.True(t, CanBackdrop(ports.Output{Width: 8192, Height: 2048}), "exact byte budget") | |||
| 46 | + | assert.False(t, CanBackdrop(ports.Output{Width: 8192, Height: 2049})) | |||
| 47 | + | assert.False(t, CanBackdrop(ports.Output{Width: 7680, Height: 4320})) | |||
| 48 | + | assert.False(t, CanBackdrop(ports.Output{Width: 8193, Height: 1})) | |||
| 49 | + | assert.False(t, CanBackdrop(ports.Output{Width: 1, Height: 8193})) | |||
| 41 | assert.False(t, CanBackdrop(ports.Output{}), "an unknown mode stays live") | 50 | assert.False(t, CanBackdrop(ports.Output{}), "an unknown mode stays live") | ||
| 42 | } | 51 | } | ||
| 43 | 52 | ||||
M internal/adapters/selection/selector.go +11 -7
| @@ -87,13 +87,17 @@ func (s *Selector) WithCapabilities(c ports.Capabilities) *Selector { | |||
| 87 | 87 | return s | |
| 88 | 88 | } | |
| 89 | 89 | ||
| 90 | - | // maxBackdrop is the largest side NeferGUI accepts for one image. | |
| 91 | - | const maxBackdrop = 4096 | |
| 90 | + | // These bounds mirror NeferGUI's image dimension and cache byte limits. | |
| 91 | + | const ( | |
| 92 | + | maxBackdrop = 8192 | |
| 93 | + | maxBackdropBytes = 64 << 20 | |
| 94 | + | ) | |
| 92 | 95 | ||
| 93 | - | // CanBackdrop reports whether an output of this physical mode can show a | |
| 94 | - | // frozen frame. A larger output must stay live: freeze only the others. | |
| 96 | + | // CanBackdrop reports whether an output's physical mode fits NeferGUI's image | |
| 97 | + | // limits. Outputs exceeding either the side or byte limit stay live. | |
| 95 | 98 | func CanBackdrop(o ports.Output) bool { | |
| 96 | - | return o.Width > 0 && o.Height > 0 && max(o.Width, o.Height) <= maxBackdrop | |
| 99 | + | return o.Width > 0 && o.Height > 0 && max(o.Width, o.Height) <= maxBackdrop && | |
| 100 | + | o.Width <= maxBackdropBytes/ports.BytesPerPixel/o.Height | |
| 97 | 101 | } | |
| 98 | 102 | ||
| 99 | 103 | // WithBackdrops draws each output's frozen frame under its overlay instead of | |
| @@ -103,8 +107,8 @@ func CanBackdrop(o ports.Output) bool { | |||
| 103 | 107 | func (s *Selector) WithBackdrops(frames map[uint32]ports.Frame) (*Selector, error) { | |
| 104 | 108 | s.backdrops = make(map[uint32]image.Image, len(frames)) | |
| 105 | 109 | for id, f := range frames { | |
| 106 | - | if f.Width > maxBackdrop || f.Height > maxBackdrop { | |
| 107 | - | return s, fmt.Errorf("selection: frozen frame of output %d is %dx%d, at most %d per side", id, f.Width, f.Height, maxBackdrop) | |
| 110 | + | if !CanBackdrop(ports.Output{Width: f.Width, Height: f.Height}) { | |
| 111 | + | return s, fmt.Errorf("selection: frozen frame of output %d is %dx%d, at most %d per side and %d bytes", id, f.Width, f.Height, maxBackdrop, maxBackdropBytes) | |
| 108 | 112 | } | |
| 109 | 113 | s.backdrops[id] = backdropImage(f) | |
| 110 | 114 | } | |
| @@ -87,13 +87,17 @@ func (s *Selector) WithCapabilities(c ports.Capabilities) *Selector { | |||||
| 87 | return s | 87 | return s | ||
| 88 | } | 88 | } | ||
| 89 | 89 | ||||
| 90 | - | // maxBackdrop is the largest side NeferGUI accepts for one image. | 90 | + | // These bounds mirror NeferGUI's image dimension and cache byte limits. |
| 91 | - | const maxBackdrop = 4096 | 91 | + | const ( |
| 92 | + | maxBackdrop = 8192 | |||
| 93 | + | maxBackdropBytes = 64 << 20 | |||
| 94 | + | ) | |||
| 92 | 95 | ||||
| 93 | - | // CanBackdrop reports whether an output of this physical mode can show a | 96 | + | // CanBackdrop reports whether an output's physical mode fits NeferGUI's image |
| 94 | - | // frozen frame. A larger output must stay live: freeze only the others. | 97 | + | // limits. Outputs exceeding either the side or byte limit stay live. |
| 95 | func CanBackdrop(o ports.Output) bool { | 98 | func CanBackdrop(o ports.Output) bool { | ||
| 96 | - | return o.Width > 0 && o.Height > 0 && max(o.Width, o.Height) <= maxBackdrop | 99 | + | return o.Width > 0 && o.Height > 0 && max(o.Width, o.Height) <= maxBackdrop && |
| 100 | + | o.Width <= maxBackdropBytes/ports.BytesPerPixel/o.Height | |||
| 97 | } | 101 | } | ||
| 98 | 102 | ||||
| 99 | // WithBackdrops draws each output's frozen frame under its overlay instead of | 103 | // WithBackdrops draws each output's frozen frame under its overlay instead of | ||
| @@ -103,8 +107,8 @@ func CanBackdrop(o ports.Output) bool { | |||||
| 103 | func (s *Selector) WithBackdrops(frames map[uint32]ports.Frame) (*Selector, error) { | 107 | func (s *Selector) WithBackdrops(frames map[uint32]ports.Frame) (*Selector, error) { | ||
| 104 | s.backdrops = make(map[uint32]image.Image, len(frames)) | 108 | s.backdrops = make(map[uint32]image.Image, len(frames)) | ||
| 105 | for id, f := range frames { | 109 | for id, f := range frames { | ||
| 106 | - | if f.Width > maxBackdrop || f.Height > maxBackdrop { | 110 | + | if !CanBackdrop(ports.Output{Width: f.Width, Height: f.Height}) { |
| 107 | - | return s, fmt.Errorf("selection: frozen frame of output %d is %dx%d, at most %d per side", id, f.Width, f.Height, maxBackdrop) | 111 | + | return s, fmt.Errorf("selection: frozen frame of output %d is %dx%d, at most %d per side and %d bytes", id, f.Width, f.Height, maxBackdrop, maxBackdropBytes) |
| 108 | } | 112 | } | ||
| 109 | s.backdrops[id] = backdropImage(f) | 113 | s.backdrops[id] = backdropImage(f) | ||
| 110 | } | 114 | } | ||
M internal/adapters/wayland/extensions_test.go +2 -0
| @@ -259,6 +259,8 @@ func TestRefusedExclusionDoesNotPinStoppedSession(t *testing.T) { | |||
| 259 | 259 | target := ports.Target{OutputID: firstOutput(t, s).ID} | |
| 260 | 260 | _, err := s.BeginExclusion(context.Background(), target) | |
| 261 | 261 | require.ErrorIs(t, err, ErrExclusionUnavailable) | |
| 262 | + | // BeginExclusion sends destroy but does not wait for the server to read it. | |
| 263 | + | require.NoError(t, s.roundtrip()) | |
| 262 | 264 | require.Equal(t, 1, srv.Stats().DestroyedExclusions, "the failed exclusion object is destroyed") | |
| 263 | 265 | srv.StopSessions() | |
| 264 | 266 | _, err = s.Capture(context.Background(), target) | |
| @@ -259,6 +259,8 @@ func TestRefusedExclusionDoesNotPinStoppedSession(t *testing.T) { | |||||
| 259 | target := ports.Target{OutputID: firstOutput(t, s).ID} | 259 | target := ports.Target{OutputID: firstOutput(t, s).ID} | ||
| 260 | _, err := s.BeginExclusion(context.Background(), target) | 260 | _, err := s.BeginExclusion(context.Background(), target) | ||
| 261 | require.ErrorIs(t, err, ErrExclusionUnavailable) | 261 | require.ErrorIs(t, err, ErrExclusionUnavailable) | ||
| 262 | + | // BeginExclusion sends destroy but does not wait for the server to read it. | |||
| 263 | + | require.NoError(t, s.roundtrip()) | |||
| 262 | require.Equal(t, 1, srv.Stats().DestroyedExclusions, "the failed exclusion object is destroyed") | 264 | require.Equal(t, 1, srv.Stats().DestroyedExclusions, "the failed exclusion object is destroyed") | ||
| 263 | srv.StopSessions() | 265 | srv.StopSessions() | ||
| 264 | _, err = s.Capture(context.Background(), target) | 266 | _, err = s.Capture(context.Background(), target) | ||
M internal/adapters/wayland/source_test.go +4 -1
| @@ -171,8 +171,11 @@ func TestFailedUnknownRepeatsLastFrame(t *testing.T) { | |||
| 171 | 171 | require.NoError(t, err, "recording continues") | |
| 172 | 172 | require.NotEqual(t, want, fresh.Pixels, "with a new frame") | |
| 173 | 173 | ||
| 174 | + | // Capture prefetched the next frame. Wait for the server to answer it | |
| 175 | + | // before arming failures, so it cannot consume the first injected failure. | |
| 176 | + | require.NoError(t, s.roundtrip()) | |
| 174 | 177 | srv.Fail(maxFrameAttempts, 0) | |
| 175 | - | // The capture started after the previous frame was answered before Fail. | |
| 178 | + | // Consume the successful prefetched frame before counting failures. | |
| 176 | 179 | _, err = s.Capture(context.Background(), target) | |
| 177 | 180 | require.NoError(t, err) | |
| 178 | 181 | for range maxFrameAttempts - 1 { | |
| @@ -171,8 +171,11 @@ func TestFailedUnknownRepeatsLastFrame(t *testing.T) { | |||||
| 171 | require.NoError(t, err, "recording continues") | 171 | require.NoError(t, err, "recording continues") | ||
| 172 | require.NotEqual(t, want, fresh.Pixels, "with a new frame") | 172 | require.NotEqual(t, want, fresh.Pixels, "with a new frame") | ||
| 173 | 173 | ||||
| 174 | + | // Capture prefetched the next frame. Wait for the server to answer it | |||
| 175 | + | // before arming failures, so it cannot consume the first injected failure. | |||
| 176 | + | require.NoError(t, s.roundtrip()) | |||
| 174 | srv.Fail(maxFrameAttempts, 0) | 177 | srv.Fail(maxFrameAttempts, 0) | ||
| 175 | - | // The capture started after the previous frame was answered before Fail. | 178 | + | // Consume the successful prefetched frame before counting failures. |
| 176 | _, err = s.Capture(context.Background(), target) | 179 | _, err = s.Capture(context.Background(), target) | ||
| 177 | require.NoError(t, err) | 180 | require.NoError(t, err) | ||
| 178 | for range maxFrameAttempts - 1 { | 181 | for range maxFrameAttempts - 1 { | ||
M internal/app/freeze_test.go +2 -2
| @@ -32,6 +32,6 @@ func TestFreezes(t *testing.T) { | |||
| 32 | 32 | // Outputs too large for a backdrop are not frozen, so their screenshot is | |
| 33 | 33 | // live like their selector. | |
| 34 | 34 | func TestFrozenOutputs(t *testing.T) { | |
| 35 | - | outputs := []ports.Output{{ID: 7, Width: 3840, Height: 2160}, {ID: 8, Width: 5120, Height: 2880}, {ID: 9, Width: 1080, Height: 1920}, {ID: 10}} | |
| 36 | - | assert.Equal(t, []uint32{7, 9}, frozenOutputs(outputs)) | |
| 35 | + | outputs := []ports.Output{{ID: 7, Width: 3840, Height: 2160}, {ID: 8, Width: 5120, Height: 2160}, {ID: 9, Width: 1080, Height: 1920}, {ID: 10}, {ID: 11, Width: 7680, Height: 4320}} | |
| 36 | + | assert.Equal(t, []uint32{7, 8, 9}, frozenOutputs(outputs)) | |
| 37 | 37 | } | |
| @@ -32,6 +32,6 @@ func TestFreezes(t *testing.T) { | |||||
| 32 | // Outputs too large for a backdrop are not frozen, so their screenshot is | 32 | // Outputs too large for a backdrop are not frozen, so their screenshot is | ||
| 33 | // live like their selector. | 33 | // live like their selector. | ||
| 34 | func TestFrozenOutputs(t *testing.T) { | 34 | func TestFrozenOutputs(t *testing.T) { | ||
| 35 | - | outputs := []ports.Output{{ID: 7, Width: 3840, Height: 2160}, {ID: 8, Width: 5120, Height: 2880}, {ID: 9, Width: 1080, Height: 1920}, {ID: 10}} | 35 | + | outputs := []ports.Output{{ID: 7, Width: 3840, Height: 2160}, {ID: 8, Width: 5120, Height: 2160}, {ID: 9, Width: 1080, Height: 1920}, {ID: 10}, {ID: 11, Width: 7680, Height: 4320}} |
| 36 | - | assert.Equal(t, []uint32{7, 9}, frozenOutputs(outputs)) | 36 | + | assert.Equal(t, []uint32{7, 8, 9}, frozenOutputs(outputs)) |
| 37 | } | 37 | } | ||
Comments3 open / 3
bnema outdated
Blocked on the NeferGUI v0.7.3 bump. NeferGUI v0.7.2 still rejects images wider than 4096 px, so merging without the bump would make the selector fail on 5120x2160 outputs. v0.7.3 is tagged on ermite; the module resolves from GitHub, which gets the mirror sync after 18:00. Then go.mod moves to v0.7.3.
bnema outdated
Now requires nefergui v0.7.3 (0012c9e). Local make check/race/mocks-check/staticcheck pass, and a headless 5120x2160 run confirms the freeze with F toggling. CI run 323 failed on TestRefusedExclusionDoesNotPinStoppedSession in internal/adapters/wayland. That package is unchanged here, and main shows the same flakiness: TestFailedUnknownRepeatsLastFrame fails 7 times out of 60 with go test -count=20 -cpu 1,2,4. Separate pre-existing issue.
bnema
Fixed the flaky wayland tests in 3d41bc5: added the missing Wayland roundtrips before the server-state assertions. CI run 327 passes.