diff --git a/native.go b/native.go index 529ab4a57..ffef1db3c 100644 --- a/native.go +++ b/native.go @@ -37,6 +37,7 @@ func initNative(systemVersion *semver.Version, appVersion *semver.Version) { _ = reapplyHostDisplayAdvertisement("native_restarted") }, OnVideoStateChange: func(state native.VideoState) { + state = unsupportedResolutionState(state) lastVideoState = state triggerVideoStateUpdate() requestDisplayUpdate(false, "video_state_changed") diff --git a/video.go b/video.go index e981979d6..38e13f3c4 100644 --- a/video.go +++ b/video.go @@ -37,6 +37,14 @@ func rpcGetVideoState() (native.VideoState, error) { return lastVideoState, nil } +func unsupportedResolutionState(state native.VideoState) native.VideoState { + if state.Error == "" && (state.Width > 1920 || state.Height > 1080) { + state.Error = "out_of_range" + state.Ready = false + } + return state +} + var ( hostDisplayAdvertiseLock = sync.Mutex{} hostDisplayAdvertised bool diff --git a/video_test.go b/video_test.go new file mode 100644 index 000000000..b78e0e6b5 --- /dev/null +++ b/video_test.go @@ -0,0 +1,47 @@ +//go:build linux && arm + +package kvm + +import ( + "testing" + + "github.com/jetkvm/kvm/internal/native" +) + +func TestUnsupportedResolutionState(t *testing.T) { + tests := []struct { + name string + input native.VideoState + want native.VideoState + }{ + { + name: "1920x1080 no error unchanged", + input: native.VideoState{Ready: true, Width: 1920, Height: 1080}, + want: native.VideoState{Ready: true, Width: 1920, Height: 1080}, + }, + { + name: "3840x2160 no error becomes out_of_range", + input: native.VideoState{Ready: true, Width: 3840, Height: 2160}, + want: native.VideoState{Ready: false, Error: "out_of_range", Width: 3840, Height: 2160}, + }, + { + name: "1920x1080 no_signal unchanged", + input: native.VideoState{Ready: false, Error: "no_signal", Width: 1920, Height: 1080}, + want: native.VideoState{Ready: false, Error: "no_signal", Width: 1920, Height: 1080}, + }, + { + name: "3840x2160 no_lock keeps no_lock", + input: native.VideoState{Ready: false, Error: "no_lock", Width: 3840, Height: 2160}, + want: native.VideoState{Ready: false, Error: "no_lock", Width: 3840, Height: 2160}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := unsupportedResolutionState(tt.input) + if got != tt.want { + t.Errorf("unsupportedResolutionState(%+v) = %+v, want %+v", tt.input, got, tt.want) + } + }) + } +}